/* * tuProlog - Copyright (C) 2001-2002 aliCE team at deis.unibo.it * * This library 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 library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package alice.tuprolog; import java.util.ArrayList; import java.util.List; import alice.tuprolog.event.LibraryEvent; import alice.tuprolog.event.LibraryListener; import alice.tuprolog.event.OutputEvent; import alice.tuprolog.event.OutputListener; import alice.tuprolog.event.QueryEvent; import alice.tuprolog.event.QueryListener; import alice.tuprolog.event.SpyEvent; import alice.tuprolog.event.SpyListener; import alice.tuprolog.event.TheoryEvent; import alice.tuprolog.event.TheoryListener; import alice.tuprolog.event.WarningEvent; import alice.tuprolog.event.WarningListener; /** * The Prolog class represents a tuProlog engine. */ public class Prolog { // 2P version private static final String VERSION = "2.1.1"; /* manager of current theory */ private TheoryManager theoryManager; /* component managing primitive */ private PrimitiveManager primitiveManager; /* component managing operators */ private OperatorManager opManager; /* component managing flags */ private FlagManager flagManager; /* component managing libraries */ private LibraryManager libraryManager; /* component managing engine */ private EngineManager engineManager; /* spying activated ? */ private boolean spy; /* warning activated ? */ private boolean warning; /* listeners registered for virtual machine output events */ private ArrayList<OutputListener> outputListeners; /* listeners registered for virtual machine internal events */ private ArrayList<SpyListener> spyListeners; /* listeners registered for virtual machine state change events */ private ArrayList<WarningListener> warningListeners; /* listeners to theory events */ private ArrayList<TheoryListener> theoryListeners; /* listeners to library events */ private ArrayList<LibraryListener> libraryListeners; /* listeners to query events */ private ArrayList<QueryListener> queryListeners; /** * Builds a prolog engine with default libraries loaded. * * The default libraries are BasicLibrary, ISOLibrary, * IOLibrary, and JavaLibrary. */ public Prolog() { this(false,true); try { loadLibrary("alice.tuprolog.lib.BasicLibrary"); } catch (Exception ex) { ex.printStackTrace(); } try { loadLibrary("alice.tuprolog.lib.ISOLibrary"); } catch (Exception ex) { ex.printStackTrace(); } try { loadLibrary("alice.tuprolog.lib.IOLibrary"); } catch (Exception ex) { ex.printStackTrace(); } try { loadLibrary("alice.tuprolog.lib.JavaLibrary"); } catch (Exception ex) { ex.printStackTrace(); } } /** * Builds a tuProlog engine with loaded the specified libraries. * * @param libs the (class) name of the libraries to be loaded */ public Prolog(String[] libs) throws InvalidLibraryException { this(false,true); if (libs != null) { for (int i = 0; i < libs.length; i++) { loadLibrary(libs[i]); } } } /** * Initialize basic engine structures. * * @param spy spying activated * @param warning warning activated */ private Prolog(boolean spy, boolean warning) { outputListeners = new ArrayList<OutputListener>(); spyListeners = new ArrayList<SpyListener>(); warningListeners = new ArrayList<WarningListener>(); this.spy = spy; this.warning = warning; theoryListeners = new ArrayList<TheoryListener>(); queryListeners = new ArrayList<QueryListener>(); libraryListeners = new ArrayList<LibraryListener>(); initializeManagers(); } private void initializeManagers() { flagManager = new FlagManager(); libraryManager = new LibraryManager(); opManager = new OperatorManager(); theoryManager = new TheoryManager(); primitiveManager = new PrimitiveManager(); engineManager = new EngineManager(); // config managers theoryManager.initialize(this); libraryManager.initialize(this); flagManager.initialize(this); primitiveManager.initialize(this); engineManager.initialize(this); } /** Gets the component managing flags. */ FlagManager getFlagManager() { return flagManager; } /** Gets the component managing theory. */ TheoryManager getTheoryManager() { return theoryManager; } /** Gets the component managing primitives. */ PrimitiveManager getPrimitiveManager() { return primitiveManager; } /** Gets the component managing libraries. */ LibraryManager getLibraryManager() { return libraryManager; } /** Gets the component managing operators. */ OperatorManager getOperatorManager() { return opManager; } /** Gets the component managing engine. */ EngineManager getEngineManager() { return engineManager; } /** * Gets the current version of the tuProlog system. */ public static String getVersion() { return VERSION; } // theory management interface /** * Sets a new theory. * * @param th is the new theory * @throws InvalidTheoryException if the new theory is not valid * @see Theory */ public synchronized void setTheory(Theory th) throws InvalidTheoryException { theoryManager.clear(); addTheory(th); } /** * Adds (appends) a theory. * * @param th is the theory to be added * @throws InvalidTheoryException if the new theory is not valid * @see Theory */ public synchronized void addTheory(Theory th) throws InvalidTheoryException { Theory oldTh = getTheory(); theoryManager.consult(th, true, null); theoryManager.solveTheoryGoal(); Theory newTh = getTheory(); TheoryEvent ev = new TheoryEvent(this, oldTh, newTh); this.notifyChangedTheory(ev); } /** * Gets current theory. * * @return current(dynamic) theory */ public synchronized Theory getTheory() { try { return new Theory(theoryManager.getTheory(true)); } catch (Exception ex){ return null; } } /** * Gets last consulted theory, with the original textual format. * * @return theory */ public synchronized Theory getLastConsultedTheory() { return theoryManager.getLastConsultedTheory(); } /** * Clears current theory. */ public synchronized void clearTheory() { try { setTheory(new Theory()); } catch (InvalidTheoryException e) { // this should never happen } } // libraries management interface /** * Loads a library. * * If a library with the same name is already present, * a warning event is notified and the request is ignored. * * @param className name of the Java class containing the library to be loaded * @return the reference to the Library just loaded * @throws InvalidLibraryException if name is not a valid library */ public synchronized Library loadLibrary(String className) throws InvalidLibraryException { return libraryManager.loadLibrary(className); } /** * Loads a specific instance of a library. * * If a library with the same name is already present, * a warning event is notified. * * @param lib the (Java class) name of the library to be loaded * @throws InvalidLibraryException if name is not a valid library */ public synchronized void loadLibrary(Library lib) throws InvalidLibraryException { libraryManager.loadLibrary(lib); } /** * Gets the list of current libraries loaded. * * @return the list of the library names */ public synchronized String[] getCurrentLibraries() { return libraryManager.getCurrentLibraries(); } /** * Unloads a previously loaded library. * * @param name of the library to be unloaded * @throws InvalidLibraryException if name is not a valid loaded library */ public synchronized void unloadLibrary(String name) throws InvalidLibraryException { libraryManager.unloadLibrary(name); } /** * Gets the reference to a loaded library. * * @param name the name of the library already loaded * @return the reference to the library loaded, null if the library is * not found */ public synchronized Library getLibrary(String name) { return libraryManager.getLibrary(name); } protected Library getLibraryPredicate(String name, int nArgs) { return primitiveManager.getLibraryPredicate(name,nArgs); } protected Library getLibraryFunctor(String name, int nArgs) { return primitiveManager.getLibraryFunctor(name,nArgs); } // operators management /** * Gets the list of the operators currently defined. * * @return the list of the operators */ public synchronized List<Operator> getCurrentOperatorList() { return opManager.getOperators(); } // solve interface /** * Solves a query. * * @param g the term representing the goal to be demonstrated * @return the result of the demonstration * @see SolveInfo */ public synchronized SolveInfo solve(Term g) { //System.out.println("ENGINE SOLVE #0: "+g); if (g == null) return null; SolveInfo sinfo = engineManager.solve(g); QueryEvent ev = new QueryEvent(this,sinfo); notifyNewQueryResultAvailable(ev); return sinfo; } /** * Solves a query. * * @param st the string representing the goal to be demonstrated * @return the result of the demonstration * @see SolveInfo */ public synchronized SolveInfo solve(String st) throws MalformedGoalException { try { Parser p = new Parser(opManager, st); Term t = p.nextTerm(true); return solve(t); } catch (InvalidTermException ex) { throw new MalformedGoalException(); } } /** * Gets next solution. * * @return the result of the demonstration * @throws NoMoreSolutionException if no more solutions are present * @see SolveInfo */ public synchronized SolveInfo solveNext() throws NoMoreSolutionException { if (hasOpenAlternatives()) { SolveInfo sinfo = engineManager.solveNext(); QueryEvent ev = new QueryEvent(this,sinfo); notifyNewQueryResultAvailable(ev); return sinfo; } else throw new NoMoreSolutionException(); } /** * Halts current solve computation. */ public void solveHalt() { engineManager.solveHalt(); } /** * Accepts current solution. */ public synchronized void solveEnd() { engineManager.solveEnd(); } /** * Asks for the presence of open alternatives to be explored * in current demonstration process. * * @return true if open alternatives are present */ public synchronized boolean hasOpenAlternatives() { return engineManager.hasOpenAlternatives(); } /** * Checks if the demonstration process was stopped by an halt command. * * @return true if the demonstration was stopped */ public synchronized boolean isHalted() { return engineManager.isHalted(); } /** * Unifies two terms using current demonstration context. * * @param t0 first term to be unified * @param t1 second term to be unified * @return true if the unification was successful */ public synchronized boolean match(Term t0, Term t1) { return t0.match(t1); } /** * Unifies two terms using current demonstration context. * * @param t0 first term to be unified * @param t1 second term to be unified * @return true if the unification was successful */ public synchronized boolean unify(Term t0, Term t1) { return t0.unify(this,t1); } /** * Identify functors. * * @param term term to identify */ public synchronized void identifyFunctor(Term term) { primitiveManager.identifyFunctor(term); } /** * Gets a term from a string, using the operators currently * defined by the engine. * * @param st the string representing a term * @return the term parsed from the string * @throws InvalidTermException if the string does not represent a valid term */ public synchronized Term toTerm(String st) throws InvalidTermException { return Parser.parseSingleTerm(st, opManager); } /** * Gets the string representation of a term, using operators * currently defined by engine. * * @param term the term to be represented as a string * @return the string representing the term */ public synchronized String toString(Term term) { return (term.toStringAsArgY(opManager, OperatorManager.OP_HIGH)); } /** Defines a new flag. */ boolean defineFlag(String name, Struct valueList, Term defValue, boolean modifiable, String libName) { return flagManager.defineFlag(name,valueList,defValue,modifiable,libName); } // spy interface ---------------------------------------------------------- /** * Switches on/off the notification of spy information events. * * @param state - true for enabling the notification of spy event */ public synchronized void setSpy(boolean state) { spy = state; } /** * Checks the spy state of the engine. * * @return true if the engine emits spy information */ public synchronized boolean isSpy() { return spy; } /** * Notifies a spy information event. */ protected void spy(String s) { if (spy) notifySpy(new SpyEvent(this, s)); } /** * Notifies a spy information event. */ protected void spy(String s, Engine e) { //System.out.println("spy: "+i+" "+s+" "+g); if (spy) { ExecutionContext ctx = e.currentContext; int i = 0; String g = "-"; if (ctx.fatherCtx != null) { i = ctx.depth-1; g = ctx.fatherCtx.currentGoal.toString(); } notifySpy(new SpyEvent(this, e, "spy: " + i + " " + s + " " + g)); } } /** * Switches on/off the notification of warning information events. * * @param state - true for enabling warning information notification */ public synchronized void setWarning(boolean state) { warning = state; } /** * Checks if warning information are notified. * * @return true if the engine emits warning information */ public synchronized boolean isWarning() { return warning; } /** * Notifies a warn information event. * * @param m the warning message */ public void warn(String m) { if (warning) notifyWarning(new WarningEvent(this, m)); } /** * Produces an output information event. * * @param m the output string */ public synchronized void stdOutput(String m) { notifyOutput(new OutputEvent(this, m)); } // event listeners management /** * Adds a listener to output events. * * @param l the listener */ public synchronized void addOutputListener(OutputListener l) { outputListeners.add(l); } /** * Adds a listener to theory events. * * @param l the listener */ public synchronized void addTheoryListener(TheoryListener l) { theoryListeners.add(l); } /** * Adds a listener to library events. * * @param l the listener */ public synchronized void addLibraryListener(LibraryListener l) { libraryListeners.add(l); } /** * Adds a listener to theory events. * * @param l the listener */ public synchronized void addQueryListener(QueryListener l) { queryListeners.add(l); } /** * Adds a listener to spy events. * * @param l the listener */ public synchronized void addSpyListener(SpyListener l) { spyListeners.add(l); } /** * Adds a listener to warning events. * * @param l the listener */ public synchronized void addWarningListener(WarningListener l) { warningListeners.add(l); } /** * Removes a listener to output events. * * @param l the listener */ public synchronized void removeOutputListener(OutputListener l) { outputListeners.remove(l); } /** Removes all output event listeners. */ public synchronized void removeAllOutputListeners() { outputListeners.clear(); } /** * Removes a listener to theory events. * * @param l the listener */ public synchronized void removeTheoryListener(TheoryListener l) { theoryListeners.remove(l); } /** * Removes a listener to library events. * * @param l the listener */ public synchronized void removeLibraryListener(LibraryListener l) { libraryListeners.remove(l); } /** * Removes a listener to query events. * * @param l the listener */ public synchronized void removeQueryListener(QueryListener l) { queryListeners.remove(l); } /** * Removes a listener to spy events. * * @param l the listener */ public synchronized void removeSpyListener(SpyListener l) { spyListeners.remove(l); } /** Removes all spy event listeners. */ public synchronized void removeAllSpyListeners() { spyListeners.clear(); } /** * Removes a listener to warning events. * * @param l the listener */ public synchronized void removeWarningListener(WarningListener l) { warningListeners.remove(l); } /** Removes all warning event listeners. */ public synchronized void removeAllWarningListeners() { warningListeners.clear(); } /** Gets a copy of current listener list to output events. */ @SuppressWarnings("unchecked") public synchronized List<OutputListener> getOutputListenerList() { // Unchecked cast from Object, but safe return (List<OutputListener>) outputListeners.clone(); } /** Gets a copy of current listener list to warning events. */ @SuppressWarnings("unchecked") public synchronized List<WarningListener> getWarningListenerList() { // Unchecked cast from Object, but safe return (List<WarningListener>) warningListeners.clone(); } /** Gets a copy of current listener list to spy events. */ @SuppressWarnings("unchecked") public synchronized List<SpyListener> getSpyListenerList() { // Unchecked cast from Object, but safe return (List<SpyListener>) spyListeners.clone(); } /** Gets a copy of current listener list to theory events. */ @SuppressWarnings("unchecked") public synchronized List<TheoryListener> getTheoryListenerList() { // Unchecked cast from Object, but safe return (List<TheoryListener>) theoryListeners.clone(); } /** Gets a copy of current listener list to library events. */ @SuppressWarnings("unchecked") public synchronized List<LibraryListener> getLibraryListenerList() { // Unchecked cast from Object, but safe return (List<LibraryListener>) libraryListeners.clone(); } /** Gets a copy of current listener list to query events. */ @SuppressWarnings("unchecked") public synchronized List<QueryListener> getQueryListenerList() { // Unchecked cast from Object, but safe return (List<QueryListener>) queryListeners.clone(); } // notification /** * Notifies an output information event. * * @param e the event */ protected void notifyOutput(OutputEvent e) { for (OutputListener ol : outputListeners) ol.onOutput(e); } /** * Notifies a spy information event. * * @param e the event */ protected void notifySpy(SpyEvent e) { for (SpyListener sl : spyListeners) sl.onSpy(e); } /** * Notifies a warning information event. * * @param e the event */ protected void notifyWarning(WarningEvent e) { for (WarningListener wl : warningListeners) wl.onWarning(e); } /** * Notifies a new theory set or updated event. * * @param e the event */ protected void notifyChangedTheory(TheoryEvent e) { for (TheoryListener tl : theoryListeners) tl.theoryChanged(e); } /** * Notifies a library loaded event. * * @param e the event */ protected void notifyLoadedLibrary(LibraryEvent e) { for (LibraryListener ll : libraryListeners) ll.libraryLoaded(e); } /** * Notifies a library unloaded event. * * @param e the event */ protected void notifyUnloadedLibrary(LibraryEvent e) { for (LibraryListener ll : libraryListeners) ll.libraryUnloaded(e); } /** * Notifies a library loaded event. * * @param e the event */ protected void notifyNewQueryResultAvailable(QueryEvent e) { for (QueryListener ql : queryListeners) ql.newQueryResultAvailable(e); } }