View Javadoc

1   /*
2    * #%L
3    * prolobjectlink-jpi-jpl
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.jpl;
23  
24  import static io.github.prolobjectlink.prolog.PrologTermType.CUT_TYPE;
25  import static io.github.prolobjectlink.prolog.PrologTermType.DOUBLE_TYPE;
26  import static io.github.prolobjectlink.prolog.PrologTermType.FLOAT_TYPE;
27  import static io.github.prolobjectlink.prolog.PrologTermType.INTEGER_TYPE;
28  import static io.github.prolobjectlink.prolog.PrologTermType.LONG_TYPE;
29  
30  import java.util.Map;
31  
32  import io.github.prolobjectlink.prolog.AbstractTerm;
33  import io.github.prolobjectlink.prolog.PrologList;
34  import io.github.prolobjectlink.prolog.PrologProvider;
35  import io.github.prolobjectlink.prolog.PrologQuery;
36  import io.github.prolobjectlink.prolog.PrologTerm;
37  import jpl.Atom;
38  import jpl.Query;
39  import jpl.Term;
40  
41  /**
42   * 
43   * @author Jose Zalacain
44   * @since 1.0
45   */
46  abstract class JplTerm extends AbstractTerm implements PrologTerm {
47  
48  	protected Term value;
49  
50  	static final Term JPL_TRUE = new Atom("true");
51  
52  	protected JplTerm(int type, PrologProvider provider) {
53  		super(type, provider);
54  	}
55  
56  	protected JplTerm(int type, PrologProvider provider, Term value) {
57  		super(type, provider);
58  		this.value = value;
59  	}
60  
61  	public final boolean isAtom() {
62  		return value.isAtom();
63  	}
64  
65  	public final boolean isNumber() {
66  		return isFloat() || isDouble() || isInteger() || isLong();
67  	}
68  
69  	public final boolean isFloat() {
70  		return type == FLOAT_TYPE && value.isFloat();
71  	}
72  
73  	public final boolean isDouble() {
74  		return type == DOUBLE_TYPE;
75  	}
76  
77  	public final boolean isInteger() {
78  		return type == INTEGER_TYPE && value.isInteger();
79  	}
80  
81  	public final boolean isLong() {
82  		return type == LONG_TYPE;
83  	}
84  
85  	public final boolean isVariable() {
86  		return value.isVariable();
87  	}
88  
89  	public final boolean isList() {
90  		if (!isVariable()) {
91  			return value.equals(JplList.EMPTY) || value.hasFunctor(".", 2);
92  		}
93  		return false;
94  	}
95  
96  	public final boolean isStructure() {
97  		return isCompound() && !isList();
98  	}
99  
100 	public final boolean isNil() {
101 		if (!isVariable() && !isNumber()) {
102 			return value.hasFunctor("nil", 0);
103 		}
104 		return false;
105 	}
106 
107 	public final boolean isEmptyList() {
108 		return value.equals(JplList.EMPTY);
109 	}
110 
111 	public final boolean isEvaluable() {
112 		if (!isVariable() && !isList() && !isNumber() && getArity() == 2) {
113 			String key = "LIST";
114 			String stringQuery = "findall(OP,current_op(_,_,OP)," + key + ")";
115 			JplEngine engine = (JplEngine) provider.newEngine();
116 			PrologQuery query = new JplQuery(engine, engine.getCache(), stringQuery);
117 			Map<String, PrologTerm>[] solution = query.allVariablesSolutions();
118 			for (Map<String, PrologTerm> map : solution) {
119 				for (PrologTerm operatorList : map.values()) {
120 					if (!operatorList.isVariable() && operatorList.isList()) {
121 						PrologList l = (PrologList) operatorList;
122 						for (PrologTerm operator : l) {
123 							if (operator.getFunctor().equals(getFunctor())) {
124 								return true;
125 							}
126 						}
127 					}
128 				}
129 			}
130 		}
131 		return false;
132 	}
133 
134 	public final boolean isAtomic() {
135 		return !isCompound() && !isList();
136 	}
137 
138 	public final boolean isCompound() {
139 		return value.isCompound() && !isAtom();
140 	}
141 
142 	public final boolean isTrueType() {
143 		return value.isJTrue();
144 	}
145 
146 	public final boolean isFalseType() {
147 		return value.isJFalse();
148 	}
149 
150 	public final boolean isNullType() {
151 		return value.isJNull();
152 	}
153 
154 	public final boolean isVoidType() {
155 		return value.isJVoid();
156 	}
157 
158 	public final boolean isObjectType() {
159 		return value.isJObject();
160 	}
161 
162 	public final boolean isReference() {
163 		return value.isJRef();
164 	}
165 
166 	public final PrologTerm getTerm() {
167 		return this;
168 	}
169 
170 	public final boolean unify(PrologTerm o) {
171 		return unify(fromTerm(o, Term.class));
172 	}
173 
174 	private final boolean unify(Term o) {
175 		String q = "unify_with_occurs_check(" + value + "," + o + ")";
176 		Query query = new Query(q);
177 		boolean result = query.hasSolution();
178 		query.close();
179 		return result;
180 	}
181 
182 	public final int compareTo(PrologTerm o) {
183 
184 		String key = "Order";
185 		Term term = fromTerm(o, Term.class);
186 		String arguments = key + "," + value + "," + term;
187 		Query query = new Query("compare(" + arguments + ")");
188 
189 		query.open();
190 		Term order = (Term) query.getSolution().get(key);
191 		query.close();
192 
193 		if (order.hasFunctor("<", 0)) {
194 			return -1;
195 		} else if (order.hasFunctor(">", 0)) {
196 			return 1;
197 		}
198 
199 		return 0;
200 
201 	}
202 
203 	public int hashCode() {
204 		final int prime = 31;
205 		int result = 1;
206 		result = prime * result + type;
207 		// Term not implement hashCode()
208 		result = prime * result + ((value == null) ? 0 : value.toString().hashCode());
209 		return result;
210 	}
211 
212 	public boolean equals(Object obj) {
213 		if (this == obj)
214 			return true;
215 		if (obj == null)
216 			return false;
217 		JplTerm other = (JplTerm) obj;
218 		if (value == null) {
219 			if (other.value != null)
220 				return false;
221 		} else if (!unify(other.value)) {
222 			return false;
223 		}
224 		return true;
225 	}
226 
227 	public String toString() {
228 		if (type == CUT_TYPE) {
229 			return getFunctor();
230 		}
231 		return "" + value + "";
232 	}
233 
234 }