SolutionManager.java
/*
* #%L
* prolobjectlink-jpi-jtrolog
* %%
* Copyright (C) 2012 - 2018 WorkLogic Project
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 2.1 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 Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/lgpl-2.1.html>.
* #L%
*/
package jTrolog.engine;
import jTrolog.terms.*;
import java.io.*;
import java.util.*;
/**
* Sorts the result into a Solution object. Arranges the bindings into a
* LinkedHashMap.
*
* @author janerist@stud.ntnu.no
* @author ivar.orstavik@hist.no
*/
@SuppressWarnings({ "rawtypes", "unchecked","serial" })
class SolutionManager implements Serializable {
private static HashMap setupResultTable(BindingsTable result, Struct query) {
// 1. stringToStructList a new goal object based on the results and
// query
HashMap bindings = new HashMap();
if (query.getVarList() == null)
return bindings;
// 2. stringToStructList a simple HashMap based on only the query vars.
for (int i = 0; i < query.getVarList().length; i++) {
Var var = query.getVarList()[i];
Term link = result.flatCopy(var, 0);
if (link.equals(var))
link = null;
bindings.put(var, link);
}
bindings = replaceUnknownManInTheMiddle(bindings);
bindings = reverseAnyNullLinks(bindings);
return bindings;
}
private static HashMap reverseAnyNullLinks(HashMap bindings) {
LinkedHashMap almostACopy = new LinkedHashMap();
for (Iterator it = bindings.keySet().iterator(); it.hasNext();) {
Term key1 = (Term) it.next();
Object link1 = bindings.get(key1);
if (link1 == null && bindings.containsValue(key1)) {
// key1 is not linked, find another key2 that links to key1
for (Iterator iterator = bindings.keySet().iterator(); iterator.hasNext();) {
Term key2 = (Term) iterator.next();
Term link2 = (Term) bindings.get(key2);
// key2 links to key1, return key2
if (key1.equals(link2)) {
almostACopy.put(key1.toString(), key2);
break;
}
}
} else
almostACopy.put(key1.toString(), link1);
}
return almostACopy;
}
private static HashMap replaceUnknownManInTheMiddle(HashMap bindings) {
Collection linked = bindings.values();
for (Iterator it = linked.iterator(); it.hasNext();) {
Term isLinked = (Term) it.next();
if (!(isLinked instanceof Var))
continue;
if (bindings.keySet().contains(isLinked))
continue;
int howOftenIsIsLinkedLinked = Collections.frequency(linked, isLinked);
if (howOftenIsIsLinkedLinked <= 1)
continue;
// isLinked is manInTheMiddle
LinkedList keys = new LinkedList();
for (Iterator it2 = bindings.keySet().iterator(); it2.hasNext();) {
Term varName = (Term) it2.next();
if (isLinked.equals(bindings.get(varName)))
keys.add(varName);
}
for (int i = 0; i < keys.size(); i++) {
Var key = (Var) keys.get(i);
if (i == keys.size() - 1)
bindings.put(key, null);
else
bindings.put(key, (Var) keys.getLast());
}
}
return bindings;
}
static Solution prepareSolution(Struct query, BindingsTable result) {
if (result == null)
return new Solution(null);
HashMap bindings = SolutionManager.setupResultTable(result, query);
Term goal = result.flatCopy(query, 0);
return new Solution(bindings, goal);
}
}