1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package io.github.prolobjectlink.prolog.jpl;
23
24 import java.util.ArrayList;
25 import java.util.Arrays;
26 import java.util.HashMap;
27 import java.util.Iterator;
28 import java.util.List;
29 import java.util.Map;
30 import java.util.NoSuchElementException;
31
32 import io.github.prolobjectlink.prolog.AbstractEngine;
33 import io.github.prolobjectlink.prolog.AbstractIterator;
34 import io.github.prolobjectlink.prolog.AbstractQuery;
35 import io.github.prolobjectlink.prolog.PrologError;
36 import io.github.prolobjectlink.prolog.PrologQuery;
37 import io.github.prolobjectlink.prolog.PrologTerm;
38 import jpl.PrologException;
39 import jpl.Query;
40 import jpl.Term;
41 import jpl.Util;
42 import jpl.Variable;
43
44
45
46
47
48
49 final class JplQuery extends AbstractQuery implements PrologQuery {
50
51 private String stringQuery;
52 private Map<String, PrologTerm>[] solutions;
53 private Iterator<Map<String, PrologTerm>> iter;
54
55 private final List<String> variables = new ArrayList<String>();
56
57 private void enumerateVariables(List<String> vector, Term term) {
58 if (!(term instanceof Variable)) {
59 Term[] terms = term.args();
60 for (Term t : terms) {
61 enumerateVariables(vector, t);
62 }
63 } else if (!vector.contains(term.name())) {
64 vector.add(term.name());
65 }
66 }
67
68 JplQuery(AbstractEngine engine, String file, String stringQuery) {
69 super(engine);
70
71 if (stringQuery != null && stringQuery.length() > 0) {
72 this.stringQuery = stringQuery;
73
74
75 enumerateVariables(variables, Util.textToTerm(stringQuery));
76
77 try {
78
79 Query.hasSolution("consult('" + file + "')");
80 Query query = new Query(stringQuery);
81 Map<String, Term>[] solve = query.allSolutions();
82 solutions = toTermMapArray(solve, PrologTerm.class);
83 iter = new JplQueryIter(solutions);
84
85 } catch (PrologException e) {
86
87 Map<String, PrologTerm> m = new HashMap<String, PrologTerm>();
88 JplReference prologexception = new JplReference(getProvider(), e);
89 Term error = e.term();
90 Term exception = error.arg(1);
91 Term ref = exception.arg(1);
92 if (ref.isJRef()) {
93 Object object = ref.jrefToObject();
94 if (object instanceof Throwable) {
95 Throwable k = (Throwable) object;
96
97 JplReference javaexception = new JplReference(getProvider(), k);
98 m.put("PrologException", prologexception);
99 m.put("JavaException", javaexception);
100 solutions = new Map[] { m };
101 }
102 }
103 }
104 }
105
106 }
107
108 public boolean hasSolution() {
109 return iter != null && iter.hasNext();
110 }
111
112 public boolean hasMoreSolutions() {
113 return iter != null && iter.hasNext();
114 }
115
116 public PrologTerm[] oneSolution() {
117 int index = 0;
118 Map<String, PrologTerm> solution = oneVariablesSolution();
119 PrologTerm[] array = new PrologTerm[solution.size()];
120 for (Iterator<String> i = variables.iterator(); i.hasNext();) {
121 array[index++] = solution.get(i.next());
122 }
123 return array;
124 }
125
126 public Map<String, PrologTerm> oneVariablesSolution() {
127 return solutions.length > 0 ? solutions[0] : new HashMap<String, PrologTerm>();
128 }
129
130 public PrologTerm[] nextSolution() {
131 int index = 0;
132 Map<String, PrologTerm> solution = nextVariablesSolution();
133 PrologTerm[] array = new PrologTerm[solution.size()];
134 for (Iterator<String> i = variables.iterator(); i.hasNext();) {
135 array[index++] = solution.get(i.next());
136 }
137 return array;
138 }
139
140 public Map<String, PrologTerm> nextVariablesSolution() {
141 return iter.next();
142 }
143
144 public PrologTerm[][] nSolutions(int n) {
145 if (n > 0) {
146
147 int m = 0;
148 int index = 0;
149 ArrayList<PrologTerm[]> all = new ArrayList<PrologTerm[]>();
150 while (hasNext() && index < n) {
151 PrologTerm[] solution = nextSolution();
152 m = solution.length > m ? solution.length : m;
153 index++;
154 all.add(solution);
155 }
156
157 PrologTerm[][] allSolutions = new PrologTerm[n][m];
158 for (int i = 0; i < n; i++) {
159 PrologTerm[] solution = all.get(i);
160 for (int j = 0; j < m; j++) {
161 allSolutions[i][j] = solution[j];
162 }
163 }
164 return allSolutions;
165 }
166 throw new PrologError("Impossible find " + n + " solutions");
167 }
168
169 public Map<String, PrologTerm>[] nVariablesSolutions(int n) {
170 return Arrays.copyOf(solutions, n);
171 }
172
173 public PrologTerm[][] allSolutions() {
174
175 int n = 0;
176 int m = 0;
177 ArrayList<PrologTerm[]> all = new ArrayList<PrologTerm[]>();
178 while (hasMoreSolutions()) {
179 PrologTerm[] solution = nextSolution();
180 m = solution.length > m ? solution.length : m;
181 n++;
182 all.add(solution);
183 }
184
185 PrologTerm[][] allSolutions = new PrologTerm[n][m];
186 for (int i = 0; i < n; i++) {
187 PrologTerm[] solution = all.get(i);
188 for (int j = 0; j < m; j++) {
189 allSolutions[i][j] = solution[j];
190 }
191 }
192 return allSolutions;
193 }
194
195 public Map<String, PrologTerm>[] allVariablesSolutions() {
196 return solutions;
197 }
198
199 public void dispose() {
200 iter = null;
201 variables.clear();
202 int l = solutions.length;
203 for (int i = 0; i < l; i++) {
204 solutions[i].clear();
205 solutions[i] = null;
206 }
207 solutions = null;
208 }
209
210 public List<Map<String, PrologTerm>> all() {
211 List<Map<String, PrologTerm>> l = new ArrayList<Map<String, PrologTerm>>();
212 for (Map<String, PrologTerm> map : solutions) {
213 l.add(map);
214 }
215 return l;
216 }
217
218 @Override
219 public int hashCode() {
220 final int prime = 31;
221 int result = super.hashCode();
222 result = prime * result + stringQuery.hashCode();
223 result = prime * result + variables.hashCode();
224 return result;
225 }
226
227 @Override
228 public boolean equals(Object obj) {
229 if (this == obj) {
230 return true;
231 }
232 if (!super.equals(obj)) {
233 return false;
234 }
235 if (getClass() != obj.getClass()) {
236 return false;
237 }
238 JplQuery other = (JplQuery) obj;
239 return variables.equals(other.variables);
240 }
241
242 @Override
243 public String toString() {
244 return stringQuery;
245 }
246
247 private class JplQueryIter extends AbstractIterator<Map<String, PrologTerm>>
248 implements Iterator<Map<String, PrologTerm>> {
249
250 private int nextIndex;
251 private final Map<String, PrologTerm>[] maps;
252
253 private JplQueryIter(Map<String, PrologTerm>[] maps) {
254 this.maps = maps;
255 }
256
257 public boolean hasNext() {
258 return nextIndex < maps.length;
259 }
260
261 public Map<String, PrologTerm> next() {
262 if (!hasNext()) {
263 throw new NoSuchElementException();
264 }
265 return maps[nextIndex++];
266 }
267
268 }
269
270 }