package net.filebot.ui.rename;
import static net.filebot.Logging.*;
import static net.filebot.media.MediaDetection.*;
import static net.filebot.util.FileUtilities.*;
import java.io.File;
import java.text.Format;
import java.util.Map;
import java.util.logging.Level;
import javax.script.ScriptException;
import net.filebot.ApplicationFolder;
import net.filebot.format.ExpressionFileFormat;
import net.filebot.format.MediaBindingBean;
import net.filebot.similarity.Match;
class ExpressionFormatter implements MatchFormatter {
private final String expression;
private ExpressionFileFormat format;
private Format preview;
private Class<?> target;
public ExpressionFormatter(String expression, Format preview, Class<?> target) {
if (expression == null || expression.isEmpty()) {
throw new IllegalArgumentException("Expression must not be null or empty");
}
this.expression = expression;
this.preview = preview;
this.target = target;
}
public ExpressionFormatter(ExpressionFileFormat format, Format preview, Class<?> target) {
this(format.getExpression(), preview, target);
// use compiled format expression right away
this.format = format;
}
public Class<?> getTargetClass() {
return target;
}
@Override
public boolean canFormat(Match<?, ?> match) {
// target object is required, file is optional
return target.isInstance(match.getValue()) && (match.getCandidate() == null || match.getCandidate() instanceof File);
}
@Override
public String preview(Match<?, ?> match) {
return preview != null ? preview.format(match.getValue()) : match.getValue().toString();
}
@Override
public synchronized String format(Match<?, ?> match, boolean extension, Map<?, ?> context) throws ScriptException {
// lazy initialize script engine
if (format == null) {
format = new ExpressionFileFormat(expression);
}
// evaluate the expression using the given bindings
Object bindingBean = new MediaBindingBean(match.getValue(), (File) match.getCandidate(), (Map) context);
String destination = format.format(bindingBean);
return getPath((File) match.getCandidate(), destination);
}
private String getPath(File source, String destination) {
if (source == null) {
return destination;
}
// resolve against parent folder
File parent = new File(destination).getParentFile();
if (parent == null || parent.isAbsolute() || destination.startsWith(".")) {
return destination;
}
// resolve against home folder
if (destination.startsWith("~")) {
return ApplicationFolder.UserHome.resolve(destination.substring(1)).getAbsolutePath();
}
// try to resolve against structure root folder by default
try {
File structureRoot = getStructureRoot(source);
if (structureRoot != null) {
for (File f : listPath(parent)) {
if (isVolumeRoot(structureRoot)) {
break;
}
if (isStructureRoot(f)) {
structureRoot = structureRoot.getParentFile();
}
}
return new File(structureRoot, destination).getAbsolutePath();
}
} catch (Exception e) {
debug.log(Level.SEVERE, "Failed to resolve structure root: " + source, e);
}
// resolve against parent folder by default
return destination;
}
}