001package net.filebot.cli;
002
003import java.io.File;
004
005import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;
006
007import groovy.lang.Closure;
008
009import net.filebot.InvalidInputException;
010import net.filebot.RenameAction;
011import net.filebot.util.FileUtilities;
012
013public class GroovyAction implements RenameAction, ConflictAction {
014
015        private final String name;
016        private final String code;
017
018        // compile on demand
019        private transient Closure<?> closure;
020
021        public GroovyAction(String name, String code) {
022                this.name = name;
023                this.code = code;
024                this.closure = null;
025        }
026
027        public GroovyAction(String name, String code, Closure<?> closure) {
028                this.name = name;
029                this.code = code;
030                this.closure = closure;
031        }
032
033        private synchronized Closure<?> compile() {
034                // compile on demand
035                if (closure == null) {
036                        try {
037                                closure = new ScriptShell().callable(code);
038                        } catch (Throwable e) {
039                                throw new InvalidInputException("Invalid Groovy action", e);
040                        }
041                }
042                return closure;
043        }
044
045        @Override
046        public File rename(File from, File to) throws Exception {
047                return apply(from, to);
048        }
049
050        @Override
051        public File conflict(File from, File to) throws Exception {
052                File target = apply(from, to);
053
054                // create target directory if necessary
055                if (target != null && target.getParentFile() != null) {
056                        FileUtilities.createFolders(target.getParentFile());
057                }
058                return target;
059        }
060
061        public File apply(File from, File to) throws Exception {
062                Object result = compile().call(from, to);
063
064                // conflict: skip this file
065                // rename: remote target file
066                if (result == null) {
067                        return null;
068                }
069
070                // conflict: confirm target file
071                // rename: local target file
072                if (result instanceof File) {
073                        return FileUtilities.resolveSibling(to, (File) result);
074                }
075
076                // conflict: confirm target file
077                // rename: local target file
078                if (result instanceof CharSequence) {
079                        return FileUtilities.resolveSibling(to, new File(result.toString()));
080                }
081
082                // GroovyCastException: Cannot cast object 'X' with class 'java.lang.String' to class 'java.io.File'
083                return (File) DefaultTypeTransformation.castToType(result, File.class);
084        }
085
086        @Override
087        public String toString() {
088                return name;
089        }
090
091        public static GroovyAction wrap(Closure<?> closure) {
092                return new GroovyAction("CLOSURE", null, closure);
093        }
094
095}