JLogQuery.java
/*
* #%L
* prolobjectlink-jpi-jlog
* %%
* Copyright (C) 2019 Prolobjectlink Project
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-3.0.html>.
* #L%
*/
package io.github.prolobjectlink.prolog.jlog;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import io.github.prolobjectlink.prolog.AbstractEngine;
import io.github.prolobjectlink.prolog.AbstractQuery;
import io.github.prolobjectlink.prolog.PrologQuery;
import io.github.prolobjectlink.prolog.PrologTerm;
import ubc.cs.JLog.Foundation.jKnowledgeBase;
import ubc.cs.JLog.Foundation.jPrologAPI;
import ubc.cs.JLog.Foundation.jVariableVector;
import ubc.cs.JLog.Parser.pOperatorRegistry;
import ubc.cs.JLog.Parser.pParseStream;
import ubc.cs.JLog.Parser.pPredicateRegistry;
import ubc.cs.JLog.Terms.jPredicateTerms;
import ubc.cs.JLog.Terms.jVariable;
/**
*
* @author Jose Zalacain
* @since 1.0
*/
final class JLogQuery extends AbstractQuery implements PrologQuery {
private Map<?, ?> solution;
private jPrologAPI jlogApi;
private jVariableVector vector = new jVariableVector();
private static final String PROLOG_EXCEPTION = "PrologException";
private static final String JAVA_EXCEPTION = "JavaException";
protected JLogQuery(AbstractEngine engine, String str) {
super(engine);
// saving variable order
str = JLogUtil.rectify(str);
JLogEngine pe = (JLogEngine) engine;
jKnowledgeBase kb = pe.engine.getKnowledgeBase();
pOperatorRegistry or = pe.engine.getOperatorRegistry();
pPredicateRegistry pr = pe.engine.getPredicateRegistry();
String s = str.charAt(str.length() - 1) == '.' ? str : str + '.';
pParseStream parser = new pParseStream(s, kb, pr, or);
jPredicateTerms terms = parser.parseQuery();
terms.enumerateVariables(vector, true);
// adapt program to string
String source = JLogUtil.toString(pe.engine);
jlogApi = new jPrologAPI(source);
try {
solution = jlogApi.query(s);
} catch (Exception e) {
solution = null;
// getLogger().error(getClass(), PrologLogger.RUNTIME_ERROR, e)
Map<String, PrologTerm> m = new HashMap<String, PrologTerm>();
JLogReference prologexception = new JLogReference(getProvider(), e);
m.put("PrologException", prologexception);
m.put(JAVA_EXCEPTION, prologexception);
solution = m;
}
}
JLogQuery(AbstractEngine engine, PrologTerm term) {
super(engine);
String str = "" + term + "";
// saving variable order
str = JLogUtil.rectify(str);
JLogEngine pe = (JLogEngine) engine;
jKnowledgeBase kb = pe.engine.getKnowledgeBase();
pOperatorRegistry or = pe.engine.getOperatorRegistry();
pPredicateRegistry pr = pe.engine.getPredicateRegistry();
pParseStream parser = new pParseStream(str + '.', kb, pr, or);
jPredicateTerms jpts = parser.parseQuery();
jpts.enumerateVariables(vector, true);
// adapt program to string
String source = JLogUtil.toString(pe.engine);
jlogApi = new jPrologAPI(source);
try {
solution = jlogApi.query(str + '.');
} catch (Exception e) {
solution = null;
// getLogger().error(getClass(), PrologLogger.RUNTIME_ERROR, e)
Map<String, PrologTerm> m = new HashMap<String, PrologTerm>();
JLogReference prologexception = new JLogReference(getProvider(), e);
m.put(PROLOG_EXCEPTION, prologexception);
m.put(JAVA_EXCEPTION, prologexception);
solution = m;
}
}
protected JLogQuery(AbstractEngine engine, PrologTerm[] terms) {
super(engine);
if (terms != null && terms.length > 0) {
String str = Arrays.toString(terms).substring(1);
str = str.substring(0, str.length() - 1) + '.';
// saving variable order
str = JLogUtil.rectify(str);
JLogEngine pe = (JLogEngine) engine;
jKnowledgeBase kb = pe.engine.getKnowledgeBase();
pOperatorRegistry or = pe.engine.getOperatorRegistry();
pPredicateRegistry pr = pe.engine.getPredicateRegistry();
pParseStream parser = new pParseStream(str, kb, pr, or);
jPredicateTerms jpts = parser.parseQuery();
jpts.enumerateVariables(vector, true);
// adapt program to string
String source = JLogUtil.toString(pe.engine);
jlogApi = new jPrologAPI(source);
try {
solution = jlogApi.query(str);
} catch (Exception e) {
solution = null;
// getLogger().error(getClass(), PrologLogger.RUNTIME_ERROR, e)
Map<String, PrologTerm> m = new HashMap<String, PrologTerm>();
JLogReference prologexception = new JLogReference(getProvider(), e);
m.put(PROLOG_EXCEPTION, prologexception);
m.put(JAVA_EXCEPTION, prologexception);
solution = m;
}
}
}
protected JLogQuery(AbstractEngine engine, PrologTerm term, PrologTerm[] terms) {
super(engine);
String str = "" + term + "";
// saving variable order
str = JLogUtil.rectify(str);
JLogEngine pe = (JLogEngine) engine;
jKnowledgeBase kb = pe.engine.getKnowledgeBase();
pOperatorRegistry or = pe.engine.getOperatorRegistry();
pPredicateRegistry pr = pe.engine.getPredicateRegistry();
pParseStream parser = new pParseStream(str + '.', kb, pr, or);
jPredicateTerms jpts = parser.parseQuery();
jpts.enumerateVariables(vector, true);
if (terms != null && terms.length > 0) {
str = str + ", " + Arrays.toString(terms).substring(1);
str = str.substring(0, str.length() - 1);
// saving variable order
str = JLogUtil.rectify(str);
parser = new pParseStream(str + '.', kb, pr, or);
jpts = parser.parseQuery();
jpts.enumerateVariables(vector, true);
}
// adapt program to string
String source = JLogUtil.toString(pe.engine);
jlogApi = new jPrologAPI(source);
try {
solution = jlogApi.query(str + '.');
} catch (Exception e) {
solution = null;
// getLogger().error(getClass(), PrologLogger.RUNTIME_ERROR, e)
Map<String, PrologTerm> m = new HashMap<String, PrologTerm>();
JLogReference prologexception = new JLogReference(getProvider(), e);
m.put(PROLOG_EXCEPTION, prologexception);
m.put(JAVA_EXCEPTION, prologexception);
solution = m;
}
}
public boolean hasSolution() {
return solution != null;
}
public boolean hasMoreSolutions() {
return solution != null;
}
public PrologTerm[] oneSolution() {
if (hasSolution()) {
int index = 0;
PrologTerm[] array = new PrologTerm[solution.size()];
for (Enumeration<?> e = vector.enumerate(); e.hasMoreElements() && index < solution.size();) {
Object object = e.nextElement();
if (object instanceof jVariable) {
String key = ((jVariable) object).getName();
array[index++] = JLogUtil.toTerm(getProvider(), solution.get(key));
}
}
return array;
}
return new PrologTerm[0];
}
public Map<String, PrologTerm> oneVariablesSolution() {
if (hasSolution()) {
Map<String, PrologTerm> varMap = new HashMap<String, PrologTerm>(solution.size());
for (Enumeration<?> e = vector.enumerate(); e.hasMoreElements();) {
Object object = e.nextElement();
if (object instanceof jVariable) {
String key = ((jVariable) object).getName();
varMap.put(key, JLogUtil.toTerm(getProvider(), solution.get(key)));
}
}
return varMap;
}
return new HashMap<String, PrologTerm>(0);
}
public PrologTerm[] nextSolution() {
PrologTerm[] array = oneSolution();
solution = jlogApi.retry();
return array;
}
public Map<String, PrologTerm> nextVariablesSolution() {
Map<String, PrologTerm> varMap = oneVariablesSolution();
solution = jlogApi.retry();
return varMap;
}
public PrologTerm[][] nSolutions(int n) {
if (n > 0) {
int m = 0;
int index = 0;
List<PrologTerm[]> all = new ArrayList<PrologTerm[]>();
while (hasMoreSolutions() && index < n) {
PrologTerm[] solutions = oneSolution();
m = solutions.length > m ? solutions.length : m;
all.add(solutions);
index++;
solution = jlogApi.retry();
}
PrologTerm[][] allSolutions = new PrologTerm[n][m];
for (int i = 0; i < n; i++) {
PrologTerm[] solutionArray = all.get(i);
System.arraycopy(solutionArray, 0, allSolutions[i], 0, m);
}
return allSolutions;
}
return new PrologTerm[0][0];
}
@SuppressWarnings("unchecked")
public Map<String, PrologTerm>[] nVariablesSolutions(int n) {
if (n > 0) {
int index = 0;
Map<String, PrologTerm>[] solutionMaps = new HashMap[n];
while (hasMoreSolutions() && index < n) {
Map<String, PrologTerm> solutionMap = oneVariablesSolution();
solutionMaps[index++] = solutionMap;
solution = jlogApi.retry();
}
return solutionMaps;
}
return new HashMap[0];
}
public PrologTerm[][] allSolutions() {
// n:solutionCount, m:solutionSize
int n = 0;
int m = 0;
List<PrologTerm[]> all = new ArrayList<PrologTerm[]>();
while (hasMoreSolutions()) {
PrologTerm[] solutions = oneSolution();
m = solutions.length > m ? solutions.length : m;
n++;
all.add(solutions);
solution = jlogApi.retry();
}
PrologTerm[][] allSolutions = new PrologTerm[n][m];
for (int i = 0; i < n; i++) {
PrologTerm[] solutionArray = all.get(i);
System.arraycopy(solutionArray, 0, allSolutions[i], 0, m);
}
return allSolutions;
}
@SuppressWarnings("unchecked")
public Map<String, PrologTerm>[] allVariablesSolutions() {
List<Map<String, PrologTerm>> allVariables = new ArrayList<Map<String, PrologTerm>>();
while (hasMoreSolutions()) {
Map<String, PrologTerm> variables = oneVariablesSolution();
allVariables.add(variables);
solution = jlogApi.retry();
}
int lenght = allVariables.size();
Map<String, PrologTerm>[] allVariablesSolution = new HashMap[lenght];
for (int i = 0; i < lenght; i++) {
allVariablesSolution[i] = allVariables.get(i);
}
return allVariablesSolution;
}
public List<Map<String, PrologTerm>> all() {
List<Map<String, PrologTerm>> allVariables = new ArrayList<Map<String, PrologTerm>>();
while (hasMoreSolutions()) {
Map<String, PrologTerm> variables = oneVariablesSolution();
allVariables.add(variables);
solution = jlogApi.retry();
}
return allVariables;
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((solution == null) ? 0 : solution.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
JLogQuery other = (JLogQuery) obj;
if (solution == null) {
if (other.solution != null)
return false;
} else if (!solution.equals(other.solution)) {
return false;
}
return true;
}
public void dispose() {
vector = new jVariableVector();
if (solution != null) {
solution.clear();
}
jlogApi.stop();
}
}