View Javadoc

1   /*
2    * #%L
3    * prolobjectlink-jpi-tuprolog
4    * %%
5    * Copyright (C) 2019 Prolobjectlink Project
6    * %%
7    * This program is free software: you can redistribute it and/or modify
8    * it under the terms of the GNU Lesser General Public License as 
9    * published by the Free Software Foundation, either version 2.1 of the 
10   * License, or (at your option) any later version.
11   * 
12   * This program is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   * GNU General Lesser Public License for more details.
16   * 
17   * You should have received a copy of the GNU General Lesser Public 
18   * License along with this program.  If not, see
19   * <http://www.gnu.org/licenses/lgpl-2.1.html>.
20   * #L%
21   */
22  package io.github.prolobjectlink.prolog.tuprolog;
23  
24  import java.util.ArrayList;
25  import java.util.HashMap;
26  import java.util.List;
27  import java.util.Map;
28  
29  import alice.tuprolog.MalformedGoalException;
30  import alice.tuprolog.NoMoreSolutionException;
31  import alice.tuprolog.NoSolutionException;
32  import alice.tuprolog.Prolog;
33  import alice.tuprolog.SolveInfo;
34  import alice.tuprolog.Struct;
35  import alice.tuprolog.Term;
36  import alice.tuprolog.Var;
37  import io.github.prolobjectlink.prolog.AbstractEngine;
38  import io.github.prolobjectlink.prolog.AbstractQuery;
39  import io.github.prolobjectlink.prolog.PrologLogger;
40  import io.github.prolobjectlink.prolog.PrologQuery;
41  import io.github.prolobjectlink.prolog.PrologTerm;
42  
43  /**
44   * 
45   * @author Jose Zalacain
46   * @since 1.0
47   */
48  final class TuPrologQuery extends AbstractQuery implements PrologQuery {
49  
50  	private Prolog tuProlog;
51  	private SolveInfo solution;
52  
53  	TuPrologQuery(AbstractEngine engine, String query) {
54  		super(engine);
55  		tuProlog = ((TuPrologEngine) engine).engine;
56  		try {
57  			solution = tuProlog.solve("" + query + ".");
58  		} catch (MalformedGoalException e) {
59  			getLogger().error(getClass(), PrologLogger.SYNTAX_ERROR, e);
60  		}
61  	}
62  
63  	TuPrologQuery(AbstractEngine engine, PrologTerm term) {
64  		super(engine);
65  		Term query = fromTerm(term, Term.class);
66  		tuProlog = ((TuPrologEngine) engine).engine;
67  		solution = tuProlog.solve(query);
68  	}
69  
70  	TuPrologQuery(AbstractEngine engine, PrologTerm[] terms) {
71  		super(engine);
72  		if (terms != null && terms.length > 0) {
73  			Term term = fromTerm(terms[terms.length - 1], Term.class);
74  			for (int i = terms.length; i > 1; i--) {
75  				term = new Struct(",", fromTerm(terms[i - 2], Term.class), term);
76  			}
77  			tuProlog = ((TuPrologEngine) engine).engine;
78  			solution = tuProlog.solve(term);
79  		}
80  	}
81  
82  	TuPrologQuery(AbstractEngine engine, PrologTerm term, PrologTerm[] terms) {
83  		super(engine);
84  		Term query = fromTerm(term, Term.class);
85  		if (terms != null && terms.length > 0) {
86  			query = fromTerm(terms[terms.length - 1], Term.class);
87  			for (int i = terms.length; i > 1; i--) {
88  				query = new Struct(",", fromTerm(terms[i - 2], Term.class), query);
89  			}
90  			query = new Struct(",", fromTerm(term, Term.class), query);
91  		}
92  		tuProlog = ((TuPrologEngine) engine).engine;
93  		solution = tuProlog.solve(query);
94  	}
95  
96  	public boolean hasSolution() {
97  		return solution != null && solution.isSuccess();
98  	}
99  
100 	public boolean hasMoreSolutions() {
101 		return tuProlog != null && tuProlog.hasOpenAlternatives();
102 	}
103 
104 	public PrologTerm[] oneSolution() {
105 		if (solution != null && solution.isSuccess()) {
106 			try {
107 				List<Var> vars = solution.getBindingVars();
108 				PrologTerm[] array = new PrologTerm[vars.size()];
109 				for (int i = 0; i < array.length; i++) {
110 					array[i] = toTerm(vars.get(i).getTerm(), PrologTerm.class);
111 				}
112 				return array;
113 			} catch (NoSolutionException e) {
114 				// do nothing
115 			}
116 		}
117 		return new PrologTerm[0];
118 	}
119 
120 	public Map<String, PrologTerm> oneVariablesSolution() {
121 		if (solution != null && solution.isSuccess()) {
122 			try {
123 				List<Var> vars = solution.getBindingVars();
124 				Map<String, PrologTerm> map = new HashMap<String, PrologTerm>(vars.size());
125 				for (Var var : vars) {
126 					map.put(var.getName(), toTerm(var.getTerm(), PrologTerm.class));
127 				}
128 				return map;
129 			} catch (NoSolutionException e) {
130 				// do nothing
131 			}
132 		}
133 		return new HashMap<String, PrologTerm>(0);
134 	}
135 
136 	public PrologTerm[] nextSolution() {
137 		try {
138 			PrologTerm[] array = oneSolution();
139 			if (hasMoreSolutions()) {
140 				solution = tuProlog.solveNext();
141 			}
142 			return array;
143 		} catch (NoMoreSolutionException e) {
144 			// do nothing
145 		}
146 		return new PrologTerm[0];
147 	}
148 
149 	public Map<String, PrologTerm> nextVariablesSolution() {
150 		try {
151 			Map<String, PrologTerm> map = oneVariablesSolution();
152 			if (hasMoreSolutions()) {
153 				solution = tuProlog.solveNext();
154 			}
155 			return map;
156 		} catch (NoMoreSolutionException e) {
157 			// do nothing
158 		}
159 		return new HashMap<String, PrologTerm>(0);
160 	}
161 
162 	public PrologTerm[][] nSolutions(int n) {
163 		if (n > 0) {
164 			// m:solutionSize
165 			int m = 0;
166 			int index = 0;
167 			List<PrologTerm[]> all = new ArrayList<PrologTerm[]>();
168 
169 			PrologTerm[] array = oneSolution();
170 			m = array.length > m ? array.length : m;
171 			all.add(array);
172 			index++;
173 
174 			while (hasMoreSolutions() && index < n) {
175 				try {
176 					solution = tuProlog.solveNext();
177 					array = oneSolution();
178 					if (array.length > 0 && !contains(all, array)) {
179 						m = array.length > m ? array.length : m;
180 						all.add(array);
181 						index++;
182 					}
183 
184 				} catch (NoMoreSolutionException e) {
185 					// do nothing
186 				}
187 
188 			}
189 
190 			PrologTerm[][] allSolutions = new PrologTerm[n][m];
191 			for (int i = 0; i < n; i++) {
192 				array = all.get(i);
193 				for (int j = 0; j < m; j++) {
194 					allSolutions[i][j] = array[j];
195 				}
196 			}
197 			return allSolutions;
198 		}
199 		return new PrologTerm[0][0];
200 	}
201 
202 	public Map<String, PrologTerm>[] nVariablesSolutions(int n) {
203 		if (n > 0) {
204 			int index = 0;
205 			Map<String, PrologTerm>[] solutionMaps = new HashMap[n];
206 
207 			Map<String, PrologTerm> solutionMap = oneVariablesSolution();
208 			solutionMaps[index++] = solutionMap;
209 
210 			while (hasMoreSolutions() && index < n) {
211 				try {
212 					TuPrologEngine pe = (TuPrologEngine) engine;
213 					solution = pe.engine.solveNext();
214 					solutionMap = oneVariablesSolution();
215 					solutionMaps[index++] = solutionMap;
216 				} catch (NoMoreSolutionException e) {
217 					// do nothing
218 				}
219 			}
220 			return solutionMaps;
221 		}
222 		return new HashMap[0];
223 	}
224 
225 	public PrologTerm[][] allSolutions() {
226 		// n:solutionCount, m:solutionSize
227 		int n = 0;
228 		int m = 0;
229 		List<PrologTerm[]> all = new ArrayList<PrologTerm[]>();
230 
231 		PrologTerm[] array = oneSolution();
232 		if (array.length > 0) {
233 			m = array.length > m ? array.length : m;
234 			n++;
235 			all.add(array);
236 		}
237 
238 		while (hasMoreSolutions()) {
239 			try {
240 				solution = tuProlog.solveNext();
241 				array = oneSolution();
242 				if (array.length > 0 && !contains(all, array)) {
243 					m = array.length > m ? array.length : m;
244 					n++;
245 					all.add(array);
246 				}
247 			} catch (NoMoreSolutionException e) {
248 				// do nothing
249 			}
250 
251 		}
252 
253 		PrologTerm[][] allSolutions = new PrologTerm[n][m];
254 		for (int i = 0; i < n; i++) {
255 			array = all.get(i);
256 			for (int j = 0; j < m; j++) {
257 				allSolutions[i][j] = array[j];
258 			}
259 		}
260 		return allSolutions;
261 	}
262 
263 	public Map<String, PrologTerm>[] allVariablesSolutions() {
264 		return all().toArray(new Map[0]);
265 	}
266 
267 	public List<Map<String, PrologTerm>> all() {
268 		List<Map<String, PrologTerm>> allVariables = new ArrayList<Map<String, PrologTerm>>();
269 
270 		Map<String, PrologTerm> variables = oneVariablesSolution();
271 		if (!variables.isEmpty()) {
272 			allVariables.add(variables);
273 		}
274 
275 		while (hasMoreSolutions()) {
276 			try {
277 				solution = tuProlog.solveNext();
278 				variables = oneVariablesSolution();
279 				if (!variables.isEmpty() && !contains(allVariables, variables)) {
280 					allVariables.add(variables);
281 				}
282 			} catch (NoMoreSolutionException e) {
283 				// do nothing
284 			}
285 		}
286 
287 		return allVariables;
288 	}
289 
290 	@Override
291 	public String toString() {
292 		return "" + solution.getQuery() + "";
293 	}
294 
295 	public void dispose() {
296 		solution = null;
297 	}
298 
299 	@Override
300 	public int hashCode() {
301 		final int prime = 31;
302 		int result = super.hashCode();
303 		result = prime * result + ((solution == null) ? 0 : solution.hashCode());
304 		result = prime * result + ((tuProlog == null) ? 0 : tuProlog.hashCode());
305 		return result;
306 	}
307 
308 	@Override
309 	public boolean equals(Object obj) {
310 		if (this == obj)
311 			return true;
312 		if (!super.equals(obj))
313 			return false;
314 		if (getClass() != obj.getClass())
315 			return false;
316 		TuPrologQuery other = (TuPrologQuery) obj;
317 		if (solution == null) {
318 			if (other.solution != null)
319 				return false;
320 		} else if (!solution.getQuery().equals(other.solution.getQuery())) {
321 			return false;
322 		}
323 		return true;
324 	}
325 
326 }