View Javadoc

1   /*
2    * #%L
3    * prolobjectlink-jpi-jtrolog
4    * %%
5    * Copyright (C) 2012 - 2018 WorkLogic 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 jTrolog.engine;
23  
24  import jTrolog.terms.*;
25  
26  import java.io.*;
27  import java.util.*;
28  
29  /**
30   * Sorts the result into a Solution object. Arranges the bindings into a
31   * LinkedHashMap.
32   * 
33   * @author janerist@stud.ntnu.no
34   * @author ivar.orstavik@hist.no
35   */
36  @SuppressWarnings({ "rawtypes", "unchecked","serial" })
37  class SolutionManager implements Serializable {
38  
39  	private static HashMap setupResultTable(BindingsTable result, Struct query) {
40  		// 1. stringToStructList a new goal object based on the results and
41  		// query
42  		HashMap bindings = new HashMap();
43  		if (query.getVarList() == null)
44  			return bindings;
45  		// 2. stringToStructList a simple HashMap based on only the query vars.
46  		for (int i = 0; i < query.getVarList().length; i++) {
47  			Var var = query.getVarList()[i];
48  			Term link = result.flatCopy(var, 0);
49  			if (link.equals(var))
50  				link = null;
51  			bindings.put(var, link);
52  		}
53  		bindings = replaceUnknownManInTheMiddle(bindings);
54  		bindings = reverseAnyNullLinks(bindings);
55  		return bindings;
56  	}
57  
58  	private static HashMap reverseAnyNullLinks(HashMap bindings) {
59  		LinkedHashMap almostACopy = new LinkedHashMap();
60  		for (Iterator it = bindings.keySet().iterator(); it.hasNext();) {
61  			Term key1 = (Term) it.next();
62  			Object link1 = bindings.get(key1);
63  			if (link1 == null && bindings.containsValue(key1)) {
64  				// key1 is not linked, find another key2 that links to key1
65  				for (Iterator iterator = bindings.keySet().iterator(); iterator.hasNext();) {
66  					Term key2 = (Term) iterator.next();
67  					Term link2 = (Term) bindings.get(key2);
68  					// key2 links to key1, return key2
69  					if (key1.equals(link2)) {
70  						almostACopy.put(key1.toString(), key2);
71  						break;
72  					}
73  				}
74  			} else
75  				almostACopy.put(key1.toString(), link1);
76  		}
77  		return almostACopy;
78  	}
79  
80  	private static HashMap replaceUnknownManInTheMiddle(HashMap bindings) {
81  		Collection linked = bindings.values();
82  		for (Iterator it = linked.iterator(); it.hasNext();) {
83  			Term isLinked = (Term) it.next();
84  			if (!(isLinked instanceof Var))
85  				continue;
86  			if (bindings.keySet().contains(isLinked))
87  				continue;
88  			int howOftenIsIsLinkedLinked = Collections.frequency(linked, isLinked);
89  			if (howOftenIsIsLinkedLinked <= 1)
90  				continue;
91  			// isLinked is manInTheMiddle
92  			LinkedList keys = new LinkedList();
93  			for (Iterator it2 = bindings.keySet().iterator(); it2.hasNext();) {
94  				Term varName = (Term) it2.next();
95  				if (isLinked.equals(bindings.get(varName)))
96  					keys.add(varName);
97  			}
98  			for (int i = 0; i < keys.size(); i++) {
99  				Var key = (Var) keys.get(i);
100 				if (i == keys.size() - 1)
101 					bindings.put(key, null);
102 				else
103 					bindings.put(key, (Var) keys.getLast());
104 			}
105 		}
106 		return bindings;
107 	}
108 
109 	static Solution prepareSolution(Struct query, BindingsTable result) {
110 		if (result == null)
111 			return new Solution(null);
112 
113 		HashMap bindings = SolutionManager.setupResultTable(result, query);
114 		Term goal = result.flatCopy(query, 0);
115 		return new Solution(bindings, goal);
116 	}
117 }