00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 package jpl;
00029
00030 import java.util.Enumeration;
00031 import java.util.Hashtable;
00032 import java.util.Map;
00033 import java.util.Vector;
00034 import jpl.fli.*;
00035
00036
00037
00099
00100
00101
00102 public class Query implements Enumeration {
00103
00104
00105
00106 private static Map m = new Hashtable();
00110 protected final Compound goal_;
00111 protected final String hostModule = "user";
00112 protected final String contextModule = "user";
00117 public final String name() {
00118 return goal_.name();
00119 }
00124 public final Term[] args() {
00125 return goal_.args();
00126 }
00131 public final Compound goal() {
00132 return goal_;
00133 }
00134
00135
00136
00137
00138
00148 public Query(Term t) {
00149 this.goal_ = Query1(t);
00150 }
00151 private Compound Query1(Term t) {
00152 if (t instanceof Compound) {
00153 return (Compound) t;
00154 } else if (t instanceof Integer) {
00155 throw new JPLException("a Query's goal must be an Atom or Compound (not an Integer)");
00156 } else if (t instanceof Float) {
00157 throw new JPLException("a Query's goal must be an Atom or Compound (not a Float)");
00158 } else if (t instanceof Variable) {
00159 throw new JPLException("a Query's goal must be an Atom or Compound (not a Variable)");
00160 } else {
00161 throw new JPLException("a Query's goal must be an Atom or Compound");
00162 }
00163 }
00164
00175 public Query(String text, Term[] args) {
00176 this(Query1(text, args));
00177 }
00178
00179 public Query(String text, Term arg) {
00180 this(Query1(text, new Term[] { arg }));
00181 }
00182 private static Term Query1(String text, Term[] args) {
00183 Term t = Util.textToTerm(text);
00184 if (t instanceof Atom) {
00185 return new Compound(text, args);
00186 } else {
00187 return t.putParams(args);
00188 }
00189 }
00190
00197 public Query(String text) {
00198 this(Util.textToTerm(text));
00199 }
00200
00201
00202
00207 private boolean open = false;
00208
00209
00210 private engine_t engine = null;
00211 private Query subQuery = null;
00212 private predicate_t predicate = null;
00213 private fid_t fid = null;
00214 private term_t term0 = null;
00215 private qid_t qid = null;
00216
00221 public synchronized final boolean isOpen() {
00222 return open;
00223 }
00224
00225
00254 public synchronized final boolean hasMoreSolutions() {
00255 if (!open) {
00256 open();
00257 }
00258 return get1();
00259 }
00260
00261
00280 public synchronized final void open() {
00281 if (open) {
00282 throw new JPLException("Query is already open");
00283 }
00284
00285
00286 if (Prolog.thread_self() == -1) {
00287 engine = Prolog.attach_pool_engine();
00288
00289 } else {
00290 engine = Prolog.current_engine();
00291
00292 }
00293 if (m.containsKey(new Long(engine.value))) {
00294 subQuery = (Query) m.get(new Long(engine.value));
00295
00296 } else {
00297 subQuery = null;
00298 }
00299 m.put(new Long(engine.value), this);
00300
00301
00302 String module;
00303 Term goal;
00304 if (goal_.hasFunctor(":", 2)) {
00305 if (goal_.arg(1).isAtom()) {
00306 module = goal_.arg(1).name();
00307 } else if (goal_.arg(1).isVariable()) {
00308 throw new PrologException(Util.textParamsToTerm("error(instantiation_error,?)", new Term[] { goal_ }));
00309 } else {
00310 throw new PrologException(Util.textParamsToTerm("error(type_error(atom,?),?)", new Term[] { goal_.arg(1), goal_ }));
00311 }
00312 goal = goal_.arg(2);
00313 } else {
00314 module = contextModule;
00315 goal = goal_;
00316 }
00317 predicate = Prolog.predicate(goal.name(), goal.arity(), module);
00318 fid = Prolog.open_foreign_frame();
00319 Map varnames_to_vars = new Hashtable();
00320 term0 = Term.putTerms(varnames_to_vars, goal.args());
00321
00322 qid = Prolog.open_query(Prolog.new_module(Prolog.new_atom(contextModule)), Prolog.Q_CATCH_EXCEPTION, predicate, term0);
00323 open = true;
00324
00325 }
00326 private final boolean get1() {
00327 if (Prolog.next_solution(qid)) {
00328
00329 return true;
00330 } else {
00331
00332 term_t exception_term_t = Prolog.exception(qid);
00333 if (exception_term_t.value != 0L) {
00334 Term exception_term = Term.getTerm(new Hashtable(), exception_term_t);
00335 close();
00336 throw new PrologException(exception_term);
00337 } else {
00338 close();
00339 return false;
00340 }
00341 }
00342 }
00343
00344
00376 public synchronized final Hashtable getSolution() {
00377
00378 if (!open) {
00379 throw new JPLException("Query is not open");
00380 } else if (get1()) {
00381 return get2();
00382 } else {
00383 return null;
00384 }
00385 }
00386 public synchronized final Hashtable getSubstWithNameVars() {
00387
00388 if (!open) {
00389 throw new JPLException("Query is not open");
00390 } else if (get1()) {
00391 return get2WithNameVars();
00392 } else {
00393 return null;
00394 }
00395 }
00396
00397
00429 public synchronized final Hashtable nextSolution() {
00430 return get2();
00431 }
00432 private final Hashtable get2() {
00433 if (!open) {
00434 throw new JPLException("Query is not open");
00435 } else {
00436 Hashtable substitution = new Hashtable();
00437
00438 Term.getSubsts(substitution, new Hashtable(), goal_.args);
00439 return substitution;
00440 }
00441 }
00442
00443 private final Hashtable get2WithNameVars() {
00444 if (!open) {
00445 throw new JPLException("Query is not open");
00446 } else {
00447 Term[] args = goal_.args;
00448 Term argNV = args[args.length - 1];
00449 String nameNV = ((Variable) argNV).name;
00450
00451 Map varnames_to_Terms1 = new Hashtable();
00452 Map vars_to_Vars1 = new Hashtable();
00453 args[args.length - 1].getSubst(varnames_to_Terms1, vars_to_Vars1);
00454 Hashtable varnames_to_Terms2 = new Hashtable();
00455 Term nvs = (Term) varnames_to_Terms1.get(nameNV);
00456 Map vars_to_Vars2 = Util.namevarsToMap(nvs);
00457 for (int i = 0; i < args.length - 1; ++i) {
00458 args[i].getSubst(varnames_to_Terms2, vars_to_Vars2);
00459 }
00460 return varnames_to_Terms2;
00461 }
00462 }
00463
00464
00471 public synchronized final boolean hasMoreElements() {
00472 return hasMoreSolutions();
00473 }
00474
00475
00483 public synchronized final Object nextElement() {
00484 return nextSolution();
00485 }
00486 public synchronized final void rewind() {
00487 close();
00488 }
00503 public synchronized final void close() {
00504 if (!open) {
00505 return;
00506 }
00507 if (Prolog.thread_self() == -1) {
00508 throw new JPLException("no engine is attached to this thread");
00509 }
00510 if (Prolog.current_engine().value != engine.value) {
00511 throw new JPLException("this Query's engine is not that which is attached to this thread");
00512 }
00513 Query topmost = (Query) m.get(new Long(engine.value));
00514 if (topmost != this) {
00515 throw new JPLException("this Query (" + this.hashCode() + ":" + this.toString() + ") is not topmost (" + topmost.hashCode() + ":" + topmost.toString() + ") within its engine["
00516 + engine.value + "]");
00517 }
00518 Prolog.close_query(qid);
00519 qid = null;
00520 jpl.fli.Prolog.discard_foreign_frame(fid);
00521 fid = null;
00522 m.remove(new Long(engine.value));
00523 if (subQuery == null) {
00524 if (Prolog.current_engine_is_pool()) {
00525 Prolog.release_pool_engine();
00526
00527 } else {
00528
00529 }
00530 } else {
00531 m.put(new Long(engine.value), subQuery);
00532
00533 }
00534 open = false;
00535 engine = null;
00536 subQuery = null;
00537 }
00549 public synchronized final Hashtable[] allSolutions() {
00550 if (open) {
00551 throw new JPLException("Query is already open");
00552 } else {
00553
00554 Vector v = new Vector();
00555 while (hasMoreSolutions()) {
00556 v.addElement(nextSolution());
00557 }
00558
00559 Hashtable solutions[] = new Hashtable[v.size()];
00560 v.copyInto(solutions);
00561 return solutions;
00562 }
00563 }
00574 public static final Hashtable[] allSolutions(Term goal) {
00575 return (new Query(goal)).allSolutions();
00576 }
00587 public static final Hashtable[] allSolutions(String text) {
00588 return (new Query(text)).allSolutions();
00589 }
00606 public static final Hashtable[] allSolutions(String text, Term[] params) {
00607 return (new Query(text, params)).allSolutions();
00608 }
00621 public synchronized final Hashtable[] nSolutions(long n) {
00622 if (open) {
00623 throw new JPLException("Query is already open");
00624 } else {
00625
00626 Vector v = new Vector();
00627 for (long i = 0; i++ < n && hasMoreSolutions();) {
00628 v.addElement(nextSolution());
00629 }
00630
00631 Hashtable solutions[] = new Hashtable[v.size()];
00632 v.copyInto(solutions);
00633 return solutions;
00634 }
00635 }
00644 public static final Hashtable[] nSolutions(Term goal, long n) {
00645 return (new Query(goal)).nSolutions(n);
00646 }
00655 public static final Hashtable[] nSolutions(String text, long n) {
00656 return (new Query(text)).nSolutions(n);
00657 }
00672 public static final Hashtable[] nSolutions(String text, Term[] params, long n) {
00673 return (new Query(text, params)).nSolutions(n);
00674 }
00683 public synchronized final Hashtable oneSolution() {
00684 if (open) {
00685 throw new JPLException("Query is already open");
00686 } else {
00687 Hashtable solution;
00688 if (hasMoreSolutions()) {
00689 solution = nextSolution();
00690 close();
00691 } else {
00692 solution = null;
00693 }
00694 return solution;
00695 }
00696 }
00705 public static final Hashtable oneSolution(Term goal) {
00706 return (new Query(goal)).oneSolution();
00707 }
00715 public static final Hashtable oneSolution(String text) {
00716 return (new Query(text)).oneSolution();
00717 }
00732 public static final Hashtable oneSolution(String text, Term[] params) {
00733 return (new Query(text, params)).oneSolution();
00734 }
00746 public synchronized final boolean query() {
00747 return oneSolution() != null;
00748 }
00758 public synchronized final boolean hasSolution() {
00759 return oneSolution() != null;
00760 }
00769 public static final boolean hasSolution(Term goal) {
00770 return (new Query(goal)).hasSolution();
00771 }
00779 public static final boolean hasSolution(String text) {
00780 return (new Query(text)).hasSolution();
00781 }
00795 public static final boolean hasSolution(String text, Term[] params) {
00796 return (new Query(text, params)).hasSolution();
00797 }
00798
00799
00800
00801 public final int abort() {
00802 if (open) {
00803 (new Thread(new Runnable() {
00804 public void run() {
00805 try {
00806 int rc1 = Prolog.attach_engine(engine);
00807 System.out.println("q.abort(): attach_engine() returns " + rc1);
00808 int rc2 = Prolog.action_abort();
00809 System.out.println("q.abort(): action_abort() returns " + rc2);
00810
00811
00812 } catch (Exception e) {
00813 }
00814 }
00815 })).start();
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844 return 0;
00845 } else {
00846 System.out.println("q.abort(): query is not open");
00847 return -1;
00848 }
00849 }
00850
00851
00852
00858 public String toString() {
00859 return goal_.name + "( " + Term.toString(goal_.args) + " )";
00860 }
00861
00862
00863
00870 public String debugString() {
00871 return "(Query " + goal_.name + " " + Term.debugString(goal_.args) + ")";
00872 }
00873 }