| 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; |
| } |
| } |
| } |