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 }