blob: f0b1db644b1969367f83c8701b29125dda6f1ed8 [file] [log] [blame]
package com.googlecode.prolog_cafe.lang;
import java.io.Serializable;
import java.lang.reflect.Constructor;
/**
* Prolog class loader.
*
* @author Mutsunori Banbara (banbara@kobe-u.ac.jp)
* @author Naoyuki Tamura (tamura@kobe-u.ac.jp)
* @version 1.1
*/
public class PrologClassLoader extends ClassLoader implements Serializable {
/** Initialize using the {@link ClassLoader#getSystemClassLoader()}. */
public PrologClassLoader() {
}
/**
* Initialize using a specific parent ClassLoader.
*
* @param parent source for all predicates in this context.
*/
public PrologClassLoader(ClassLoader parent) {
super(parent);
}
/**
* Returns a <code>java.lang.Class</code> object associated with the predicate
* class with the given arguments.
* @param pkg package name
* @param functor predicate name
* @param arity predicate arity
* @param resolve If <code>true</code> then resolve the class
* @return a <code>java.lang.Class</code> object associated with the predicate
* class that corresponds to <code>pkg:functor/arity</code>
* if exists, otherwise throws <code>ClassNotFoundException</code>.
* @exception ClassNotFoundException
*/
public Class loadPredicateClass(String pkg,
String functor,
int arity,
boolean resolve) throws ClassNotFoundException {
return loadClass(PredicateEncoder.encode(pkg, functor, arity), resolve);
}
/**
* Check whether the predicate class for the given arguments is defined.
* @param pkg package name
* @param functor predicate name
* @param arity predicate arity
* @return <code>true</code> if the predicate <code>pkg:functor/arity</code>
* is defined, otherwise <code>false</code>.
*/
public boolean definedPredicate(String pkg,
String functor,
int arity) {
String cname = PredicateEncoder.encode(pkg, functor, arity);
return getResource(cname.replace('.', '/') + ".class") != null;
}
/**
* Allocate a predicate and configure it with the specified arguments.
*
* @param pkg package the predicate is in.
* @param functor name of the predicate.
* @param args arguments to pass. The arity is derived from the arguments.
* @return the predicate encapsulating the logic and the arguments.
*/
public Predicate predicate(String pkg, String functor, Term... args) {
return predicate(pkg, functor, Success.SUCCESS, args);
}
/**
* Allocate a predicate and configure it with the specified arguments.
*
* @param pkg package the predicate is in.
* @param functor name of the predicate.
* @param cont operation to execute if the predicate is successful. Usually
* this is {@link Success#SUCCESS}.
* @param args arguments to pass. The arity is derived from the arguments.
* @return the predicate encapsulating the logic and the arguments.
*/
public Predicate predicate(String pkg, String functor, Operation cont, Term... args) {
int arity = args.length;
try {
Class<Predicate> clazz = loadPredicateClass(pkg, functor, arity, true);
Class[] params = new Class[arity + 1];
for (int i = 0; i < arity; i++)
params[i] = Term.class;
params[arity] = Operation.class;
Object[] a = new Object[arity + 1];
for (int i = 0; i < arity; i++)
a[i] = args[i];
a[arity] = cont;
Constructor<Predicate> cons = clazz.getDeclaredConstructor(params);
cons.setAccessible(true);
return cons.newInstance(a);
} catch (Exception err) {
SymbolTerm colon2 = SymbolTerm.makeSymbol(":", 2);
SymbolTerm slash2 = SymbolTerm.makeSymbol("/", 2);
Term[] fa = {SymbolTerm.makeSymbol(functor), new IntegerTerm(arity)};
Term[] r = {SymbolTerm.makeSymbol(pkg), new StructureTerm(slash2, fa)};
Term what = new StructureTerm(colon2, r);
ExistenceException e2 = new ExistenceException("procedure", new StructureTerm(slash2, fa), err.toString());
e2.initCause(err);
throw e2;
}
}
}