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            /**
050             * Creates a new parser object. You should create at most one such object per JVM.
051             * 
052             * @param prologCommand The command to run the SWI Prolog interpreter.
053             *     On Windows this is usually "plcon", on Linux "pl", and on Mac "swipl".
054             * @param apeExeFile The path (with filename) of the file "ape.exe".
055             */
056            public APELocal(String prologCommand, String apeExeFile) {
057                    JPL.init(new String[] {prologCommand, "-x", apeExeFile, "-g", "true"});
058                    // clearMessages();
059            }
060    
061            public synchronized String getSoloOutput(String text, Lexicon lexicon, OutputType outputType) throws ACEParserException {
062                    clearMessages();
063                    String ulextext = "";
064                    if (lexicon != null) {
065                            ulextext = ",ulextext=" + PrologUtils.escape(lexicon.toString());
066                    }
067                    Term input = Util.textToTerm("[text=" + PrologUtils.escape(text) + ulextext + ",solo=" + outputType.toString().toLowerCase() + getOptions() + "]");
068                    Query q = new Query("get_ape_results", new Term[] {input, new Variable("Result")});
069                    Atom result = (Atom) q.oneSolution().get("Result");
070                    String s = result.name();
071    
072                    return checkForErrors(s);
073            }
074    
075            public synchronized ACEParserResult getMultiOutput(String text, Lexicon lexicon, OutputType... outputTypes) {
076                    clearMessages();
077                    String outputs = "";
078                    for (OutputType t : outputTypes) {
079                            outputs += ",c" + t.toString().toLowerCase() + "=on";
080                    }
081                    String ulextext = "";
082                    if (lexicon != null) {
083                            ulextext = ",ulextext=" + PrologUtils.escape(lexicon.toString());
084                    }
085                    Term input = Util.textToTerm("[text=" + PrologUtils.escape(text) + ulextext + outputs + getOptions() + "]");
086                    Query q = new Query("get_ape_results", new Term[] {input, new Variable("Result")});
087                    Atom result = (Atom) q.oneSolution().get("Result");
088                    return new ACEParserResult(result.name());
089            }
090    
091            /**
092             * Loads the lexicon by adding all lexicon entries of the lexicon. Note that these lexicon entries
093             * are automatically discarded the first time you call getSoloOutput or getMultiOutput with a lexicon
094             * parameter that is not null.
095             * 
096             * @param lexicon The lexicon to be loaded.
097             * @see #addLexiconEntry
098             * @see #discardLexicon
099             */
100            public synchronized void addLexicon(Lexicon lexicon) {
101                    clearMessages();
102                    Query q = new Query(new Compound("add_lexicon_entries", new Term[] { Util.textToTerm(lexicon.toList()) }));
103                    q.oneSolution();
104            }
105    
106            /**
107             * Adds a new lexicon entry. Note that this lexicon entry is automatically discarded the first time
108             * you call getSoloOutput or getMultiOutput with a lexicon parameter that is not null.
109             * 
110             * @param lexiconEntry The lexicon entry to be added.
111             * @see #addLexicon
112             * @see #discardLexicon
113             */
114            public synchronized void addLexiconEntry(LexiconEntry lexiconEntry) {
115                    clearMessages();
116                    Query q = new Query(new Compound("add_lexicon_entry", new Term[] { Util.textToTerm(lexiconEntry.toString()) }) );
117                    q.oneSolution();
118            }
119    
120            /**
121             * Discards the dynamically added lexicon entries. Note that the lexicon entries that are complied into
122             * the SWI Prolog executable are not affected by this operation.
123             *
124             * @see #addLexiconEntry
125             * @see #addLexicon
126             */
127            public synchronized void discardLexicon() {
128                    clearMessages();
129                    Query q = new Query("discard_ulex");
130                    q.oneSolution();
131            }
132    
133            private void clearMessages() {
134                    Query q = new Query("clear_messages");
135                    q.oneSolution();
136            }
137    }