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}