    001    // This file is part of the Attempto Java Packages.
    002    // Copyright 2008, Attempto Group, University of Zurich (see http://attempto.ifi.uzh.ch).
    003    //
    004    // The Attempto Java Packages is free software: you can redistribute it and/or modify it under the
    005    // terms of the GNU Lesser General Public License as published by the Free Software Foundation,
    006    // either version 3 of the License, or (at your option) any later version.
    007    //
    008    // The Attempto Java Packages is distributed in the hope that it will be useful, but WITHOUT ANY
    009    // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
    010    // PURPOSE. See the GNU Lesser General Public License for more details.
    011    //
    012    // You should have received a copy of the GNU Lesser General Public License along with the Attempto
    013    // Java Packages. If not, see http://www.gnu.org/licenses/.
    014
    015    package ch.uzh.ifi.attempto.ape;
    016
    017    import jpl.Atom;
    018    import jpl.Compound;
    019    import jpl.JPL;
    020    import jpl.Query;
    021    import jpl.Term;
    022    import jpl.Util;
    023    import jpl.Variable;
    024
    025    /**
    026     * This class provides an interface to the SWI Prolog executable of the Attempto Parsing Engine (APE).
    027     * Note that you need the file "ape.exe" (which can be compiled from the Attempto APE distribution) and that
    028     * SWI Prolog needs to be installed.
    029     * Furthermore, you have to make sure that the JPL libraries of SWI Prolog are in the java library path.
    030     * This can be achieved by a Java VM argument which looks like this (for Mac OS X):
    031     *
    032     * <blockquote><code>-Djava.library.path=/opt/local/lib/swipl-5.6.45/lib/i386-darwin8.10.1</code></blockquote>
    033     *
    034     * It is very likely that the path is different on your machine. Just look for the directory that contains
    035     * the file or symbolic link <em>libjpl.jnilib</em> (under Mac OS X), <em>libjpl.dll</em> (under Windows), or
    036     * <em>libjpl.so</em> (under Unix).
    037     *
    038     * If you get the error message
    039     *
    040     * <blockquote><code>java.lang.UnsatisfiedLinkError: no jpl in java.library.path</code></blockquote>
    041     *
    042     * then this is a strong indication that the SWI Prolog JPL libraries are not found.
    043     *
    044     *
    045     * @author Tobias Kuhn
    046     */
    047    public class APELocal extends ACEParser {
    048
    049            private static APELocal apeLocal;
    050
    051            /**
    052             * Creates a new parser object. You can create at most one such object per JVM. If you
    053             * try to create more than one such object or if you called the init method before
    054             * then a runtime exception is thrown.
    055             *
    056             * @param prologCommand The command to run the SWI Prolog interpreter.
    057             *     On Windows this is usually "plcon", on Linux "pl", and on Mac "swipl".
    058             * @param apeExeFile The path (with filename) of the file "ape.exe".
    059             */
    060            public APELocal(String prologCommand, String apeExeFile) {
    061                    if (apeLocal != null) {
    062                            throw new RuntimeException("Only one APELocal object can be created.");
    063                    }
    064                    JPL.init(new String[] {prologCommand, "-x", apeExeFile, "-g", "true"});
    065                    apeLocal = this;
    066            }
    067
    068            /**
    069             * Returns the singleton APELocal instance. Null is returned if the APELocal instance has not yet
    070             * been initialized by the constructor or the init method.
    071             *
    072             * @return The singleton APELocal instance.
    073             */
    074            public static APELocal getInstance() {
    075                    return apeLocal;
    076            }
    077
    078            /**
    079             * Initializes the APELocal singleton instance. This method can be called at most once.
    080             * If you call it twice or if you called the constructor before then a runtime exception
    081             * is thrown.
    082             *
    083             * @param prologCommand The command to run the SWI Prolog interpreter.
    084             *     On Windows this is usually "plcon", on Linux "pl", and on Mac "swipl".
    085             * @param apeExeFile The path (with filename) of the file "ape.exe".
    086             */
    087            public static void init(String prologCommand, String apeExeFile) {
    088                    new APELocal(prologCommand, apeExeFile);
    089            }
    090
    091            /**
    092             * Checks whether the singleton instance has already been initialized.
    093             *
    094             * @return true if the singleton instance has been initialized.
    095             */
    096            public static boolean isInitialized() {
    097                    return apeLocal != null;
    098            }
    099
    100            public synchronized String getSoloOutput(String text, Lexicon lexicon, OutputType outputType) throws ACEParserException {
    101                    clearMessages();
    102                    String ulextext = "";
    103                    if (lexicon != null) {
    104                            ulextext = ",ulextext=" + PrologUtils.escape(lexicon.toString());
    105                    }
    106                    Term input = Util.textToTerm("[text=" + PrologUtils.escape(text) + ulextext + ",solo=" + outputType.toString().toLowerCase() + getOptions() + "]");
    107                    Query q = new Query("get_ape_results", new Term[] {input, new Variable("Result")});
    108                    Atom result = (Atom) q.oneSolution().get("Result");
    109                    String s = result.name();
    110
    111                    return checkForErrors(s);
    112            }
    113
    114            public synchronized ACEParserResult getMultiOutput(String text, Lexicon lexicon, OutputType... outputTypes) {
    115                    clearMessages();
    116                    String outputs = "";
    117                    for (OutputType t : outputTypes) {
    118                            outputs += ",c" + t.toString().toLowerCase() + "=on";
    119                    }
    120                    String ulextext = "";
    121                    if (lexicon != null) {
    122                            ulextext = ",ulextext=" + PrologUtils.escape(lexicon.toString());
    123                    }
    124                    Term input = Util.textToTerm("[text=" + PrologUtils.escape(text) + ulextext + outputs + getOptions() + "]");
    125                    Query q = new Query("get_ape_results", new Term[] {input, new Variable("Result")});
    126                    Atom result = (Atom) q.oneSolution().get("Result");
    127                    return new ACEParserResult(result.name());
    128            }
    129
    130            /**
    131             * Loads the lexicon by adding all lexicon entries of the lexicon. Note that these lexicon entries
    132             * are automatically discarded the first time you call getSoloOutput or getMultiOutput with a lexicon
    133             * parameter that is not null.
    134             *
    135             * @param lexicon The lexicon to be loaded.
    136             * @see #addLexiconEntry
    137             * @see #discardLexicon
    138             */
    139            public synchronized void addLexicon(Lexicon lexicon) {
    140                    clearMessages();
    141                    Query q = new Query(new Compound("add_lexicon_entries", new Term[] { Util.textToTerm(lexicon.toList()) }));
    142                    q.oneSolution();
    143            }
    144
    145            /**
    146             * Adds a new lexicon entry. Note that this lexicon entry is automatically discarded the first time
    147             * you call getSoloOutput or getMultiOutput with a lexicon parameter that is not null.
    148             *
    149             * @param lexiconEntry The lexicon entry to be added.
    150             * @see #addLexicon
    151             * @see #discardLexicon
    152             */
    153            public synchronized void addLexiconEntry(LexiconEntry lexiconEntry) {
    154                    clearMessages();
    155                    Query q = new Query(new Compound("add_lexicon_entry", new Term[] { Util.textToTerm(lexiconEntry.toString()) }) );
    156                    q.oneSolution();
    157            }
    158
    159            /**
    160             * Discards the dynamically added lexicon entries. Note that the lexicon entries that are complied into
    161             * the SWI Prolog executable are not affected by this operation.
    162             *
    163             * @see #addLexiconEntry
    164             * @see #addLexicon
    165             */
    166            public synchronized void discardLexicon() {
    167                    clearMessages();
    168                    Query q = new Query("discard_ulex");
    169                    q.oneSolution();
    170            }
    171
    172            private void clearMessages() {
    173                    Query q = new Query("clear_messages");
    174                    q.oneSolution();
    175            }
    176    }