/*
* Created on 1-ott-2005
*
*/
package alice.tuprolog;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import alice.tuprolog.event.LibraryEvent;
import alice.tuprolog.event.WarningEvent;
/**
*
* @author Alex Benini
*/
class LibraryManager {
/* dynamically loaded built-in libraries */
private List<Library> currentLibraries;
private Prolog prolog;
private TheoryManager theoryManager;
private PrimitiveManager primitiveManager;
LibraryManager() {
currentLibraries = new ArrayList<Library>();
}
/**
* Configure this Manager
*/
void initialize(Prolog vm) {
prolog = vm;
theoryManager = vm.getTheoryManager();
primitiveManager = vm.getPrimitiveManager();
}
/**
* Loads a library.
*
* If a library with the same name is already present,
* a warning event is notified and the request is ignored.
*
* @param the 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 {
Library lib = null;
try {
lib = (Library) Class.forName(className).newInstance();
String name = lib.getName();
Library alib = getLibrary(name);
if (alib != null) {
if (prolog.isWarning()) {
String msg = "library " + alib.getName() + " already loaded.";
prolog.notifyWarning(new WarningEvent(prolog, msg));
}
return alib;
}
} catch (Exception ex) {
throw new InvalidLibraryException(className, -1, -1);
}
bindLibrary(lib);
LibraryEvent ev = new LibraryEvent(prolog, lib.getName());
prolog.notifyLoadedLibrary(ev);
return lib;
}
/**
* Loads a specific instance of a library.
*
* If a library of the same class is already present,
* a warning event is notified. Then, the current instance of
* that library is discarded, and the new instance gets loaded.
*
* @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 {
String name = lib.getName();
Library alib = getLibrary(name);
if (alib != null) {
if (prolog.isWarning()) {
String msg = "library " + alib.getName() + " already loaded.";
prolog.notifyWarning(new WarningEvent(prolog, msg));
}
unloadLibrary(name);
}
bindLibrary(lib);
LibraryEvent ev = new LibraryEvent(prolog, lib.getName());
prolog.notifyLoadedLibrary(ev);
}
/**
* Gets the list of current libraries loaded.
*
* @return the list of the library names
*/
public synchronized String[] getCurrentLibraries() {
String[] libs = new String[currentLibraries.size()];
for (int i = 0; i < libs.length; i++)
libs[i] = ((Library) currentLibraries.get(i)).getName();
return libs;
}
/**
* 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 {
boolean found = false;
for (Iterator<Library> i = currentLibraries.iterator(); i.hasNext();) {
Library library = i.next();
if (library.getName().equals(name)) {
found = true;
i.remove();
library.dismiss();
primitiveManager.deletePrimitiveInfo(library);
break;
}
}
if (!found)
throw new InvalidLibraryException();
theoryManager.removeLibraryTheory(name);
theoryManager.rebindPrimitives();
LibraryEvent ev = new LibraryEvent(prolog, name);
prolog.notifyUnloadedLibrary(ev);
}
/**
* Binds a library.
*
* @param lib is library object
* @return the reference to the Library just loaded
* @throws InvalidLibraryException if name is not a valid library
*/
private Library bindLibrary(Library lib) throws InvalidLibraryException {
try {
String name = lib.getName();
lib.setEngine(prolog);
currentLibraries.add(lib);
// set primitives
primitiveManager.createPrimitiveInfo(lib);
// set theory
String th = lib.getTheory();
if (th != null) {
theoryManager.consult(new Theory(th), false, name);
theoryManager.solveTheoryGoal();
}
// in current theory there could be predicates and functors
// which become built-in after library loading
theoryManager.rebindPrimitives();
//
return lib;
} catch (InvalidTheoryException ex) {
//System.out.println("line "+ex.line+" "+ex.pos);
throw new InvalidLibraryException(lib.getName(), ex.line, ex.pos);
} catch (Exception ex) {
ex.printStackTrace();
throw new InvalidLibraryException(lib.getName(), -1, -1);
}
}
/**
* 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) {
for (Library library : currentLibraries)
if (library.getName().equals(name))
return library;
return null;
}
public synchronized void onSolveBegin(Term g) {
for (Library library : currentLibraries)
library.onSolveBegin(g);
}
public synchronized void onSolveEnd() {
for (Library library : currentLibraries)
library.onSolveEnd();
}
}