View Javadoc

1   /*
2    * #%L
3    * prolobjectlink-jpi-jlog
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 General Public License as
9    * published by the Free Software Foundation, either version 3 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 Public License for more details.
16   * 
17   * You should have received a copy of the GNU General Public
18   * License along with this program.  If not, see
19   * <http://www.gnu.org/licenses/gpl-3.0.html>.
20   * #L%
21   */
22  package io.github.prolobjectlink.prolog.jlog;
23  
24  import java.util.ArrayList;
25  import java.util.Arrays;
26  import java.util.Enumeration;
27  import java.util.HashMap;
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.PrologQuery;
34  import io.github.prolobjectlink.prolog.PrologTerm;
35  import ubc.cs.JLog.Foundation.jKnowledgeBase;
36  import ubc.cs.JLog.Foundation.jPrologAPI;
37  import ubc.cs.JLog.Foundation.jVariableVector;
38  import ubc.cs.JLog.Parser.pOperatorRegistry;
39  import ubc.cs.JLog.Parser.pParseStream;
40  import ubc.cs.JLog.Parser.pPredicateRegistry;
41  import ubc.cs.JLog.Terms.jPredicateTerms;
42  import ubc.cs.JLog.Terms.jVariable;
43  
44  /**
45   * 
46   * @author Jose Zalacain
47   * @since 1.0
48   */
49  final class JLogQuery extends AbstractQuery implements PrologQuery {
50  
51  	private Map<?, ?> solution;
52  	private jPrologAPI jlogApi;
53  	private jVariableVector vector = new jVariableVector();
54  
55  	private static final String PROLOG_EXCEPTION = "PrologException";
56  	private static final String JAVA_EXCEPTION = "JavaException";
57  
58  	protected JLogQuery(AbstractEngine engine, String str) {
59  		super(engine);
60  
61  		// saving variable order
62  		str = JLogUtil.rectify(str);
63  		JLogEngine pe = (JLogEngine) engine;
64  		jKnowledgeBase kb = pe.engine.getKnowledgeBase();
65  		pOperatorRegistry or = pe.engine.getOperatorRegistry();
66  		pPredicateRegistry pr = pe.engine.getPredicateRegistry();
67  		String s = str.charAt(str.length() - 1) == '.' ? str : str + '.';
68  		pParseStream parser = new pParseStream(s, kb, pr, or);
69  		jPredicateTerms terms = parser.parseQuery();
70  		terms.enumerateVariables(vector, true);
71  
72  		// adapt program to string
73  		String source = JLogUtil.toString(pe.engine);
74  		jlogApi = new jPrologAPI(source);
75  		try {
76  			solution = jlogApi.query(s);
77  		} catch (Exception e) {
78  			solution = null;
79  			// getLogger().error(getClass(), PrologLogger.RUNTIME_ERROR, e)
80  			Map<String, PrologTerm> m = new HashMap<String, PrologTerm>();
81  			JLogReference prologexception = new JLogReference(getProvider(), e);
82  			m.put("PrologException", prologexception);
83  			m.put(JAVA_EXCEPTION, prologexception);
84  			solution = m;
85  		}
86  
87  	}
88  
89  	JLogQuery(AbstractEngine engine, PrologTerm term) {
90  		super(engine);
91  
92  		String str = "" + term + "";
93  
94  		// saving variable order
95  		str = JLogUtil.rectify(str);
96  		JLogEngine pe = (JLogEngine) engine;
97  		jKnowledgeBase kb = pe.engine.getKnowledgeBase();
98  		pOperatorRegistry or = pe.engine.getOperatorRegistry();
99  		pPredicateRegistry pr = pe.engine.getPredicateRegistry();
100 		pParseStream parser = new pParseStream(str + '.', kb, pr, or);
101 		jPredicateTerms jpts = parser.parseQuery();
102 		jpts.enumerateVariables(vector, true);
103 
104 		// adapt program to string
105 		String source = JLogUtil.toString(pe.engine);
106 		jlogApi = new jPrologAPI(source);
107 		try {
108 			solution = jlogApi.query(str + '.');
109 		} catch (Exception e) {
110 			solution = null;
111 			// getLogger().error(getClass(), PrologLogger.RUNTIME_ERROR, e)
112 			Map<String, PrologTerm> m = new HashMap<String, PrologTerm>();
113 			JLogReference prologexception = new JLogReference(getProvider(), e);
114 			m.put(PROLOG_EXCEPTION, prologexception);
115 			m.put(JAVA_EXCEPTION, prologexception);
116 			solution = m;
117 		}
118 
119 	}
120 
121 	protected JLogQuery(AbstractEngine engine, PrologTerm[] terms) {
122 		super(engine);
123 
124 		if (terms != null && terms.length > 0) {
125 
126 			String str = Arrays.toString(terms).substring(1);
127 			str = str.substring(0, str.length() - 1) + '.';
128 
129 			// saving variable order
130 			str = JLogUtil.rectify(str);
131 			JLogEngine pe = (JLogEngine) engine;
132 			jKnowledgeBase kb = pe.engine.getKnowledgeBase();
133 			pOperatorRegistry or = pe.engine.getOperatorRegistry();
134 			pPredicateRegistry pr = pe.engine.getPredicateRegistry();
135 			pParseStream parser = new pParseStream(str, kb, pr, or);
136 			jPredicateTerms jpts = parser.parseQuery();
137 			jpts.enumerateVariables(vector, true);
138 
139 			// adapt program to string
140 			String source = JLogUtil.toString(pe.engine);
141 			jlogApi = new jPrologAPI(source);
142 			try {
143 				solution = jlogApi.query(str);
144 			} catch (Exception e) {
145 				solution = null;
146 				// getLogger().error(getClass(), PrologLogger.RUNTIME_ERROR, e)
147 				Map<String, PrologTerm> m = new HashMap<String, PrologTerm>();
148 				JLogReference prologexception = new JLogReference(getProvider(), e);
149 				m.put(PROLOG_EXCEPTION, prologexception);
150 				m.put(JAVA_EXCEPTION, prologexception);
151 				solution = m;
152 			}
153 
154 		}
155 
156 	}
157 
158 	protected JLogQuery(AbstractEngine engine, PrologTerm term, PrologTerm[] terms) {
159 		super(engine);
160 
161 		String str = "" + term + "";
162 
163 		// saving variable order
164 		str = JLogUtil.rectify(str);
165 		JLogEngine pe = (JLogEngine) engine;
166 		jKnowledgeBase kb = pe.engine.getKnowledgeBase();
167 		pOperatorRegistry or = pe.engine.getOperatorRegistry();
168 		pPredicateRegistry pr = pe.engine.getPredicateRegistry();
169 		pParseStream parser = new pParseStream(str + '.', kb, pr, or);
170 		jPredicateTerms jpts = parser.parseQuery();
171 		jpts.enumerateVariables(vector, true);
172 
173 		if (terms != null && terms.length > 0) {
174 
175 			str = str + ", " + Arrays.toString(terms).substring(1);
176 			str = str.substring(0, str.length() - 1);
177 
178 			// saving variable order
179 			str = JLogUtil.rectify(str);
180 			parser = new pParseStream(str + '.', kb, pr, or);
181 			jpts = parser.parseQuery();
182 			jpts.enumerateVariables(vector, true);
183 
184 		}
185 
186 		// adapt program to string
187 		String source = JLogUtil.toString(pe.engine);
188 		jlogApi = new jPrologAPI(source);
189 		try {
190 			solution = jlogApi.query(str + '.');
191 		} catch (Exception e) {
192 			solution = null;
193 			// getLogger().error(getClass(), PrologLogger.RUNTIME_ERROR, e)
194 			Map<String, PrologTerm> m = new HashMap<String, PrologTerm>();
195 			JLogReference prologexception = new JLogReference(getProvider(), e);
196 			m.put(PROLOG_EXCEPTION, prologexception);
197 			m.put(JAVA_EXCEPTION, prologexception);
198 			solution = m;
199 		}
200 	}
201 
202 	public boolean hasSolution() {
203 		return solution != null;
204 	}
205 
206 	public boolean hasMoreSolutions() {
207 		return solution != null;
208 	}
209 
210 	public PrologTerm[] oneSolution() {
211 		if (hasSolution()) {
212 			int index = 0;
213 			PrologTerm[] array = new PrologTerm[solution.size()];
214 			for (Enumeration<?> e = vector.enumerate(); e.hasMoreElements() && index < solution.size();) {
215 				Object object = e.nextElement();
216 				if (object instanceof jVariable) {
217 					String key = ((jVariable) object).getName();
218 					array[index++] = JLogUtil.toTerm(getProvider(), solution.get(key));
219 				}
220 			}
221 			return array;
222 		}
223 		return new PrologTerm[0];
224 	}
225 
226 	public Map<String, PrologTerm> oneVariablesSolution() {
227 		if (hasSolution()) {
228 			Map<String, PrologTerm> varMap = new HashMap<String, PrologTerm>(solution.size());
229 			for (Enumeration<?> e = vector.enumerate(); e.hasMoreElements();) {
230 				Object object = e.nextElement();
231 				if (object instanceof jVariable) {
232 					String key = ((jVariable) object).getName();
233 					varMap.put(key, JLogUtil.toTerm(getProvider(), solution.get(key)));
234 				}
235 			}
236 			return varMap;
237 		}
238 		return new HashMap<String, PrologTerm>(0);
239 	}
240 
241 	public PrologTerm[] nextSolution() {
242 		PrologTerm[] array = oneSolution();
243 		solution = jlogApi.retry();
244 		return array;
245 	}
246 
247 	public Map<String, PrologTerm> nextVariablesSolution() {
248 		Map<String, PrologTerm> varMap = oneVariablesSolution();
249 		solution = jlogApi.retry();
250 		return varMap;
251 	}
252 
253 	public PrologTerm[][] nSolutions(int n) {
254 		if (n > 0) {
255 			int m = 0;
256 			int index = 0;
257 			List<PrologTerm[]> all = new ArrayList<PrologTerm[]>();
258 			while (hasMoreSolutions() && index < n) {
259 				PrologTerm[] solutions = oneSolution();
260 				m = solutions.length > m ? solutions.length : m;
261 				all.add(solutions);
262 				index++;
263 				solution = jlogApi.retry();
264 			}
265 
266 			PrologTerm[][] allSolutions = new PrologTerm[n][m];
267 			for (int i = 0; i < n; i++) {
268 				PrologTerm[] solutionArray = all.get(i);
269 				System.arraycopy(solutionArray, 0, allSolutions[i], 0, m);
270 			}
271 			return allSolutions;
272 		}
273 		return new PrologTerm[0][0];
274 	}
275 
276 	@SuppressWarnings("unchecked")
277 	public Map<String, PrologTerm>[] nVariablesSolutions(int n) {
278 		if (n > 0) {
279 			int index = 0;
280 			Map<String, PrologTerm>[] solutionMaps = new HashMap[n];
281 			while (hasMoreSolutions() && index < n) {
282 				Map<String, PrologTerm> solutionMap = oneVariablesSolution();
283 				solutionMaps[index++] = solutionMap;
284 				solution = jlogApi.retry();
285 			}
286 			return solutionMaps;
287 		}
288 		return new HashMap[0];
289 	}
290 
291 	public PrologTerm[][] allSolutions() {
292 		// n:solutionCount, m:solutionSize
293 		int n = 0;
294 		int m = 0;
295 		List<PrologTerm[]> all = new ArrayList<PrologTerm[]>();
296 		while (hasMoreSolutions()) {
297 			PrologTerm[] solutions = oneSolution();
298 			m = solutions.length > m ? solutions.length : m;
299 			n++;
300 			all.add(solutions);
301 			solution = jlogApi.retry();
302 		}
303 
304 		PrologTerm[][] allSolutions = new PrologTerm[n][m];
305 		for (int i = 0; i < n; i++) {
306 			PrologTerm[] solutionArray = all.get(i);
307 			System.arraycopy(solutionArray, 0, allSolutions[i], 0, m);
308 		}
309 		return allSolutions;
310 	}
311 
312 	@SuppressWarnings("unchecked")
313 	public Map<String, PrologTerm>[] allVariablesSolutions() {
314 		List<Map<String, PrologTerm>> allVariables = new ArrayList<Map<String, PrologTerm>>();
315 		while (hasMoreSolutions()) {
316 			Map<String, PrologTerm> variables = oneVariablesSolution();
317 			allVariables.add(variables);
318 			solution = jlogApi.retry();
319 		}
320 
321 		int lenght = allVariables.size();
322 		Map<String, PrologTerm>[] allVariablesSolution = new HashMap[lenght];
323 		for (int i = 0; i < lenght; i++) {
324 			allVariablesSolution[i] = allVariables.get(i);
325 		}
326 		return allVariablesSolution;
327 	}
328 
329 	public List<Map<String, PrologTerm>> all() {
330 		List<Map<String, PrologTerm>> allVariables = new ArrayList<Map<String, PrologTerm>>();
331 		while (hasMoreSolutions()) {
332 			Map<String, PrologTerm> variables = oneVariablesSolution();
333 			allVariables.add(variables);
334 			solution = jlogApi.retry();
335 		}
336 		return allVariables;
337 	}
338 
339 	@Override
340 	public int hashCode() {
341 		final int prime = 31;
342 		int result = super.hashCode();
343 		result = prime * result + ((solution == null) ? 0 : solution.hashCode());
344 		return result;
345 	}
346 
347 	@Override
348 	public boolean equals(Object obj) {
349 		if (this == obj)
350 			return true;
351 		if (!super.equals(obj))
352 			return false;
353 		if (getClass() != obj.getClass())
354 			return false;
355 		JLogQuery other = (JLogQuery) obj;
356 		if (solution == null) {
357 			if (other.solution != null)
358 				return false;
359 		} else if (!solution.equals(other.solution)) {
360 			return false;
361 		}
362 		return true;
363 	}
364 
365 	public void dispose() {
366 		vector = new jVariableVector();
367 		if (solution != null) {
368 			solution.clear();
369 		}
370 		jlogApi.stop();
371 	}
372 
373 }