org.grouplens.lenskit.eval.script.EvalScript Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of lenskit-eval Show documentation
Show all versions of lenskit-eval Show documentation
Facilities for evaluating recommender algorithms.
/*
* LensKit, an open source recommender systems toolkit.
* Copyright 2010-2014 LensKit Contributors. See CONTRIBUTORS.md.
* Work on LensKit has been funded by the National Science Foundation under
* grants IIS 05-34939, 08-08692, 08-12148, and 10-17697.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.grouplens.lenskit.eval.script;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.common.util.concurrent.Uninterruptibles;
import groovy.lang.*;
import groovy.util.AntBuilder;
import org.apache.commons.lang3.builder.Builder;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Target;
import org.apache.tools.ant.Task;
import org.codehaus.groovy.runtime.InvokerHelper;
import org.grouplens.lenskit.config.GroovyUtils;
import org.grouplens.lenskit.eval.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.ExecutionException;
/**
* Base class for evaluator configuration scripts. It contains the metaclass
* machinery to set up evaluation taskMap.
* @author GroupLens Research
* @since 0.10
*/
public class EvalScript extends Script implements GroovyObject {
public final Logger logger = LoggerFactory.getLogger(getClass());
private EvalScriptEngine engine;
private ConfigMethodInvoker helper;
private EvalProject project;
private Target currentTarget;
private AntBuilder ant;
public EvalScript() {}
//region Properties
public EvalConfig getConfig() {
return project.getConfig();
}
/**
* Get the engine in use for this script.
* @return The script engine for this script.
*/
public EvalScriptEngine getEngine() {
Preconditions.checkState(engine != null, "no script engine configured");
return engine;
}
/**
* Set the engine this script should use.
* @param ece The engine to be used by this script.
*/
public void setEngine(EvalScriptEngine ece) {
engine = ece;
if (project != null) {
helper = new ConfigMethodInvoker(ece, project);
}
}
/**
* Get the eval project configured by this script.
* @return The eval project.
* @throws IllegalStateException if no eval project has been configured.
* @see #setProject(EvalProject)
*/
public EvalProject getProject() {
Preconditions.checkState(project != null, "no project configured");
return project;
}
/**
* Set the eval project to be configured by this script.
* @param prj The eval project to configure.
*/
public void setProject(EvalProject prj) {
project = prj;
ant = new LenskitAntBuilder(getAntProject());
if (engine != null) {
helper = new ConfigMethodInvoker(engine, project);
}
}
/**
* Get the evaluator script. Provides global access to evaluator properties (such as the config).
*
* @return The eval script.
*/
public EvalScript getEval() {
return this;
}
/**
* Get the Ant project.
*/
public Project getAntProject() {
return getProject().getAntProject();
}
/**
* Get the Ant builder.
*/
public AntBuilder getAnt() {
Preconditions.checkState(ant != null, "no project configured");
return ant;
}
/**
* Invoke an Ant block.
*/
public Task ant(Closure> block) {
return (Task) getAnt().invokeMethod("sequential", block);
}
//endregion
//region Utilities
/**
* Evaluate another script.
* @param file The script to evaluate.
* @return The return value of the script (typically the return value of its last expression).
*/
public Object evalScript(File file) throws IOException, TaskExecutionException {
return engine.runScript(file, project);
}
/**
* Evaluate another script.
* @param fn The script to evaluate.
* @return The return value of the script (typically the return value of its last expression).
*/
public Object evalScript(String fn) throws IOException, TaskExecutionException {
return evalScript(new File(fn));
}
/**
* Performs a file search based upon the parameter glob pattern.
*
* @param globPattern String in glob syntax giving the glob to expand.
* @return A list of paths from the working directory to matching file names.
*/
public List glob(String globPattern) {
return glob(globPattern, ".");
}
/**
* Performs a file search based upon the parameter glob pattern.
*
* @param globPattern String in glob syntax giving the glob to expand.
* @param baseDir The base directory from which to search.
* @return A list of paths from the base directory matching the glob.
*/
public List glob(String globPattern, String baseDir) {
DirectoryScanner ds = new DirectoryScanner();
ds.setIncludes(new String[]{globPattern});
ds.setBasedir(baseDir);
ds.scan();
return ImmutableList.copyOf(ds.getIncludedFiles());
}
//endregion
public EvalTarget target(String name,
@DelegatesTo(value=TargetDelegate.class,
strategy=Closure.DELEGATE_FIRST) Closure> closure) {
if (currentTarget != null) {
throw new IllegalStateException("cannot nest targets");
}
EvalTarget target = new EvalTarget();
target.setName(name);
target.setProject(getAntProject());
TargetDelegate delegate = new TargetDelegate(target);
currentTarget = target;
try {
GroovyUtils.callWithDelegate(closure, delegate);
} finally {
currentTarget = null;
}
getAntProject().addTarget(target);
return target;
}
public void defaultTarget(String name) {
project.setDefaultTarget(name);
}
public void defaultTarget(Target target) {
if (target == null) {
project.setDefaultTarget(null);
} else {
project.setDefaultTarget(target.getName());
}
}
//region Plumbing
public Object methodMissing(String name, Object arg) {
Object[] args = InvokerHelper.asArray(arg);
logger.debug("searching for eval command {}", name);
Object obj = null;
try {
obj = helper.callExternalMethod(name, args);
} catch (NoSuchMethodException e) {
throw new MissingMethodException(name, getClass(), args, true);
}
if (obj instanceof Builder) {
return helper.finishBuilder((Builder>) obj);
} else if (obj instanceof EvalTask) {
final EvalTask> task = (EvalTask>) obj;
if (currentTarget == null) {
try {
ListenableFuture> deps = Futures.allAsList(helper.getDeps(task));
helper.clearDeps(task);
Runnable execute = new Runnable() {
@Override
public void run() {
try {
task.execute();
} catch (TaskExecutionException e) {
throw new RuntimeException("task failure", e);
}
}
};
deps.addListener(execute, MoreExecutors.directExecutor());
if (task.isDone()) {
return Uninterruptibles.getUninterruptibly(task);
} else {
return task;
}
} catch (ExecutionException e) {
throw new RuntimeException("task failure", e);
}
} else {
EvalAntTask aTask = new EvalAntTask(task, helper.getDeps(task));
aTask.setProject(getAntProject());
aTask.setOwningTarget(currentTarget);
aTask.init();
currentTarget.addTask(aTask);
return obj;
}
} else {
return obj;
}
}
@Override
public Object run() {
throw new UnsupportedOperationException("script not implemented");
}
//endregion
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy