package edu.umd.rhsmith.diads.tools.sentiment; import org.plyjy.factory.PySystemObjectFactory; import org.python.core.Py; import org.python.core.PyString; import org.python.core.PySystemState; /** * A utility class providing a means of getting the Python-based implementation * of a sentiment analysis tool. (See {@link /py/SentimentAnalyzerP.py}). The * {@link #getSentimentAnalyzer(String, String)} method will construct and * return an {@link ISentimentAnalyzer} instance backed by an instance of the * Python tool, loading its training and feature-set data from the given * filenames. * * @author dmonner * @author rmachedo * * @see ISentimentAnalyzer * @see PySentimentAnalyzer#getSentimentAnalyzer(String, String) * @see PySentimentAnalyzer.LoadFailureException * */ public class PySentimentAnalyzer { private PySentimentAnalyzer() { } /* * -------------------------------- * Python interaction * -------------------------------- */ /** * Construct and * return an {@link ISentimentAnalyzer} instance backed by an instance of * the * Python tool, loading its training and feature-set data from the given * filenames. * * @param classifierFilename * the name of the serialized classifier pickle file for the * Python tool to load * @param featuresFilename * the name of the serialized feature-set pickle file for the * Python tool to load * @return the Python sentiment analysis tool instance * * @throws NullPointerException * if either parameter is {@code null} * @throws PySentimentAnalyzer.LoadFailureException * if tool instantiation fails for any * other reason. */ public static ISentimentAnalyzer getSentimentAnalyzer( String classifierFilename, String featuresFilename) throws NullPointerException, PySentimentAnalyzer.LoadFailureException { String workingDir = System.getProperty("user.dir"); String pyDir = workingDir + "/py"; PySystemState sys = Py.getSystemState(); sys.path.append(new PyString(workingDir)); sys.path.append(new PyString(pyDir)); final PySystemObjectFactory factory = new PySystemObjectFactory(sys, ISentimentAnalyzer.class, "SentimentAnalyzerP", "SentimentAnalyzerP"); return (ISentimentAnalyzer) factory.createObject(classifierFilename, featuresFilename); } /** * <p> * An {@code Exception} representing a failed load of a Python sentiment * analysis tool. Thrown by * {@link PySentimentAnalyzer#getSentimentAnalyzer(String, String)} in the * event of a load failure. The underlying cause of the failure is available * via {@link #getCause()}. * </p> * <p> * The parameters supplied to the failed call are available via * {@link #getClassifierFilename()} and {@link #getFeaturesFilename()} * respectively. * </p> * * @author rmachedo * */ public static class LoadFailureException extends Exception { private static final String MSG_ERR_LOADFAIL_FMT = "Unable to load SentimentAnalyzerP with classifier-file '%s', feature-file '%s'"; private static final long serialVersionUID = 1L; private final String cFile; private final String fFile; private LoadFailureException(String cFile, String fFile, Exception cause) { super(String.format(MSG_ERR_LOADFAIL_FMT, cFile, fFile), cause); this.cFile = cFile; this.fFile = fFile; } /** * Gets and returns the classifier filename parameter passed to the * {@link PySentimentAnalyzer#getSentimentAnalyzer(String, String)} call * which generated this {@code LoadFailureException}. * * @return the classifier filename parameter */ public String getClassifierFilename() { return cFile; } /** * Gets and returns the features filename parameter passed to the * {@link PySentimentAnalyzer#getSentimentAnalyzer(String, String)} call * which generated this {@code LoadFailureException}. * * @return the features filename parameter */ public String getFeaturesFilename() { return fFile; } } }