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 conflict(File from, File to) throws Exception {
047                return apply(from, to);
048        }
049
050        @Override
051        public File rename(File from, File to) throws Exception {
052                return apply(from, to);
053        }
054
055        public File apply(File from, File to) throws Exception {
056                Object result = compile().call(from, to);
057
058                // conflict: skip this file
059                // rename: remote target file
060                if (result == null) {
061                        return null;
062                }
063
064                // conflict: confirm target file
065                // rename: local target file
066                if (result instanceof File) {
067                        return FileUtilities.resolveSibling(to, (File) result);
068                }
069
070                // conflict: confirm target file
071                // rename: local target file
072                if (result instanceof CharSequence) {
073                        return FileUtilities.resolveSibling(to, new File(result.toString()));
074                }
075
076                // GroovyCastException: Cannot cast object 'X' with class 'java.lang.String' to class 'java.io.File'
077                return (File) DefaultTypeTransformation.castToType(result, File.class);
078        }
079
080        @Override
081        public String toString() {
082                return name;
083        }
084
085        public static GroovyAction wrap(Closure<?> closure) {
086                return new GroovyAction("CLOSURE", null, closure);
087        }
088
089}