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.jtrolog;
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
31 import io.github.prolobjectlink.prolog.AbstractEngine;
32 import io.github.prolobjectlink.prolog.AbstractQuery;
33 import io.github.prolobjectlink.prolog.PrologLogger;
34 import io.github.prolobjectlink.prolog.PrologQuery;
35 import io.github.prolobjectlink.prolog.PrologTerm;
36 import jTrolog.engine.Prolog;
37 import jTrolog.engine.Solution;
38 import jTrolog.parser.Parser;
39 import jTrolog.terms.Struct;
40 import jTrolog.terms.Term;
41 import jTrolog.terms.Var;
42
43
44
45
46
47
48 final class JTrologQuery extends AbstractQuery implements PrologQuery {
49
50 private Solution solution;
51 private Prolog jtrolog;
52 private List<String> variables = new ArrayList<String>();
53
54 private void enumerateVariables(List<String> vector, Term term) {
55 if (!(term instanceof Var)) {
56 if (term instanceof Struct) {
57 Struct struct = (Struct) term;
58 Var[] vars = struct.getVarList();
59 for (Var var : vars) {
60 enumerateVariables(variables, var);
61 }
62 }
63 } else if (!vector.contains(term.toString())) {
64 vector.add(term.toString());
65 }
66 }
67
68 JTrologQuery(AbstractEngine engine, String query) {
69 super(engine);
70 jtrolog = ((JTrologEngine) engine).engine;
71 enumerateVariables(variables, new Parser(query).nextTerm(false));
72 try {
73 this.solution = jtrolog.solve("" + query + ".");
74 } catch (Throwable e) {
75
76 }
77 }
78
79 JTrologQuery(AbstractEngine engine, PrologTerm term) {
80 super(engine);
81 String str = "" + term + "";
82 jtrolog = ((JTrologEngine) engine).engine;
83 enumerateVariables(variables, fromTerm(term, Term.class));
84 try {
85 this.solution = jtrolog.solve(str + '.');
86 } catch (Throwable e) {
87
88 }
89 }
90
91 JTrologQuery(AbstractEngine engine, PrologTerm[] terms) {
92 super(engine);
93 jtrolog = ((JTrologEngine) engine).engine;
94 if (terms != null && terms.length > 0) {
95 enumerateVariables(variables, fromTerm(terms[terms.length - 1], Term.class));
96 for (int i = terms.length; i > 1; i--) {
97 enumerateVariables(variables, fromTerm(terms[i - 2], Term.class));
98 }
99 String str = Arrays.toString(terms).substring(1);
100 str = str.substring(0, str.length() - 1) + '.';
101 try {
102 this.solution = jtrolog.solve(str);
103 } catch (Throwable e) {
104
105 }
106 }
107 }
108
109 JTrologQuery(AbstractEngine engine, PrologTerm term, PrologTerm[] terms) {
110 super(engine);
111 String str = "" + term + "";
112 jtrolog = ((JTrologEngine) engine).engine;
113 enumerateVariables(variables, fromTerm(term, Term.class));
114 if (terms != null && terms.length > 0) {
115 enumerateVariables(variables, fromTerm(terms[terms.length - 1], Term.class));
116 for (int i = terms.length; i > 1; i--) {
117 enumerateVariables(variables, fromTerm(terms[i - 2], Term.class));
118 }
119 str = str + ", " + Arrays.toString(terms).substring(1);
120 str = str.substring(0, str.length() - 1);
121 }
122 try {
123 this.solution = jtrolog.solve(str + '.');
124 } catch (Throwable e) {
125
126 }
127 }
128
129 public boolean hasSolution() {
130 return solution != null && solution.success();
131 }
132
133 public boolean hasMoreSolutions() {
134 try {
135 return jtrolog.hasOpenAlternatives();
136 } catch (Throwable e) {
137
138 }
139 return false;
140 }
141
142 public PrologTerm[] oneSolution() {
143 int index = 0;
144 Map<String, PrologTerm> solutionMap = oneVariablesSolution();
145 PrologTerm[] array = new PrologTerm[solutionMap.size()];
146 if (array.length > 0) {
147 for (Iterator<String> i = variables.iterator(); i.hasNext();) {
148 array[index++] = solutionMap.get(i.next());
149 }
150 }
151 return array;
152 }
153
154 public Map<String, PrologTerm> oneVariablesSolution() {
155 Map<String, PrologTerm> map = new HashMap<String, PrologTerm>();
156 for (String vName : variables) {
157 if (solution != null) {
158 Term vtTerm = solution.getBinding(vName);
159 if (vtTerm != null) {
160 PrologTerm pTerm = toTerm(vtTerm, PrologTerm.class);
161 map.put(vName, pTerm);
162 }
163 }
164 }
165 return map;
166 }
167
168 public PrologTerm[] nextSolution() {
169 PrologTerm[] array = oneSolution();
170 try {
171 if (hasMoreSolutions()) {
172 solution = jtrolog.solveNext();
173 return array;
174 }
175 } catch (Throwable e) {
176 getLogger().error(getClass(), PrologLogger.NON_SOLUTION, e);
177 }
178 return array;
179 }
180
181 public Map<String, PrologTerm> nextVariablesSolution() {
182 Map<String, PrologTerm> map = oneVariablesSolution();
183 try {
184
185 if (hasMoreSolutions()) {
186 solution = jtrolog.solveNext();
187 }
188 return map;
189 } catch (Throwable e) {
190 getLogger().error(getClass(), PrologLogger.NON_SOLUTION, e);
191 }
192 return new HashMap<String, PrologTerm>(0);
193 }
194
195 public PrologTerm[][] nSolutions(int n) {
196 if (n > 0) {
197
198 int m = 0;
199 int index = 0;
200 List<PrologTerm[]> all = new ArrayList<PrologTerm[]>();
201
202 PrologTerm[] array = oneSolution();
203 m = array.length > m ? array.length : m;
204 index++;
205 all.add(array);
206
207 while (hasMoreSolutions() && index < n) {
208 try {
209 solution = jtrolog.solveNext();
210 array = oneSolution();
211 if (array.length > 0 && !contains(all, array)) {
212 m = array.length > m ? array.length : m;
213 index++;
214 all.add(array);
215 }
216 } catch (Throwable e) {
217 getLogger().error(getClass(), PrologLogger.NON_SOLUTION, e);
218 }
219
220 }
221
222 PrologTerm[][] allSolutions = new PrologTerm[n][m];
223 for (int i = 0; i < n; i++) {
224 array = all.get(i);
225 System.arraycopy(array, 0, allSolutions[i], 0, m);
226 }
227 return allSolutions;
228 }
229 return new PrologTerm[0][0];
230 }
231
232 public Map<String, PrologTerm>[] nVariablesSolutions(int n) {
233 if (n > 0) {
234 int index = 0;
235 Map<String, PrologTerm>[] solutionMaps = new HashMap[n];
236
237 Map<String, PrologTerm> solutionMap = oneVariablesSolution();
238 solutionMaps[index++] = solutionMap;
239
240 while (hasMoreSolutions() && index < n) {
241 try {
242 solution = jtrolog.solveNext();
243 solutionMap = oneVariablesSolution();
244 solutionMaps[index++] = solutionMap;
245 } catch (Throwable e) {
246 getLogger().error(getClass(), PrologLogger.NON_SOLUTION, e);
247 }
248 }
249 return solutionMaps;
250 }
251 return new HashMap[0];
252 }
253
254 public PrologTerm[][] allSolutions() {
255
256 int n = 0;
257 int m = 0;
258 List<PrologTerm[]> all = new ArrayList<PrologTerm[]>();
259
260 PrologTerm[] array = oneSolution();
261 if (array.length > 0) {
262 m = array.length > m ? array.length : m;
263 n++;
264 all.add(array);
265 }
266
267 while (hasMoreSolutions()) {
268 try {
269 solution = jtrolog.solveNext();
270 array = oneSolution();
271 if (array.length > 0 && !contains(all, array)) {
272 m = array.length > m ? array.length : m;
273 n++;
274 all.add(array);
275 }
276 } catch (Throwable e) {
277 getLogger().error(getClass(), PrologLogger.NON_SOLUTION, e);
278 }
279
280 }
281
282 PrologTerm[][] allSolutions = new PrologTerm[n][m];
283 for (int i = 0; i < n; i++) {
284 array = all.get(i);
285 System.arraycopy(array, 0, allSolutions[i], 0, m);
286 }
287 return allSolutions;
288 }
289
290 public Map<String, PrologTerm>[] allVariablesSolutions() {
291 List<Map<String, PrologTerm>> allVariables = new ArrayList<Map<String, PrologTerm>>();
292
293 Map<String, PrologTerm> varMap = oneVariablesSolution();
294 if (!varMap.isEmpty()) {
295 allVariables.add(varMap);
296 }
297
298 while (hasMoreSolutions()) {
299 try {
300 solution = jtrolog.solveNext();
301 varMap = oneVariablesSolution();
302 if (!varMap.isEmpty() && !contains(allVariables, varMap)) {
303 allVariables.add(varMap);
304 }
305 } catch (Throwable e) {
306 getLogger().error(getClass(), PrologLogger.NON_SOLUTION, e);
307 }
308 }
309
310 int lenght = allVariables.size();
311 Map<String, PrologTerm>[] allVariablesSolution = new HashMap[lenght];
312 for (int i = 0; i < lenght; i++) {
313 allVariablesSolution[i] = allVariables.get(i);
314 }
315 return allVariablesSolution;
316 }
317
318 public List<Map<String, PrologTerm>> all() {
319 List<Map<String, PrologTerm>> all = new ArrayList<Map<String, PrologTerm>>();
320
321 Map<String, PrologTerm> varMap = oneVariablesSolution();
322 if (!varMap.isEmpty()) {
323 all.add(varMap);
324 }
325
326 while (hasMoreSolutions()) {
327 try {
328 solution = jtrolog.solveNext();
329 varMap = oneVariablesSolution();
330 if (!varMap.isEmpty() && !contains(all, varMap)) {
331 all.add(varMap);
332 }
333 } catch (Throwable e) {
334 getLogger().error(getClass(), PrologLogger.NON_SOLUTION, e);
335 }
336 }
337
338 return all;
339 }
340
341 @Override
342 public String toString() {
343 return "" + solution + "";
344 }
345
346 public void dispose() {
347 solution = null;
348 }
349
350 @Override
351 public int hashCode() {
352 final int prime = 31;
353 int result = super.hashCode();
354 result = prime * result + solution.hashCode();
355 result = prime * result + variables.hashCode();
356 return result;
357 }
358
359 @Override
360 public boolean equals(Object obj) {
361 if (this == obj)
362 return true;
363 if (!super.equals(obj))
364 return false;
365 if (getClass() != obj.getClass())
366 return false;
367 JTrologQuery other = (JTrologQuery) obj;
368 if (!Prolog.match(solution.getSolution(), other.solution.getSolution()))
369 return false;
370 return variables.equals(other.variables);
371 }
372
373 }