001: package org.mandarax.reference;
002:
003: /*
004: * Copyright (C) 1999-2004 <A href="http://www-ist.massey.ac.nz/JBDietrich" target="_top">Jens Dietrich</a>
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2 of the License, or (at your option) any later version.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: */
020:
021: import java.util.Vector;
022: import org.mandarax.kernel.*;
023: import org.mandarax.util.TermIterator;
024: import java.util.*;
025:
026: /**
027: * Reference implementation for complex terms.
028: * @author <A href="http://www-ist.massey.ac.nz/JBDietrich" target="_top">Jens Dietrich</A>
029: * @version 3.4 <7 March 05>
030: * @since 1.1
031: * Prova re-integration modifications
032: * @author <A HREF="mailto:a.kozlenkov@city.ac.uk">Alex Kozlenkov</A>
033: * @version 3.4 <7 March 05>
034: */
035: public class ComplexTermImpl extends Complex implements ComplexTerm {
036:
037: private Function function = null;
038:
039: /**
040: * Constructor.
041: */
042: public ComplexTermImpl() {
043: super ();
044: }
045:
046: /**
047: * Constructor.
048: * @param f the function
049: */
050: ComplexTermImpl(org.mandarax.kernel.Function f) {
051: super ();
052:
053: setFunction(f);
054: }
055:
056: /**
057: * Constructor.
058: * @param f the function
059: * @param t an array of terms
060: */
061: ComplexTermImpl(org.mandarax.kernel.Function f, Term[] t) {
062: super ();
063:
064: setFunction(f);
065:
066: for (int i = 0; i < t.length; i++) {
067: setTerm(t[i], i);
068: }
069: }
070:
071: /**
072: * Get a term iterator for the subterms, including the term itself.
073: * Looks up the term tree recursively.
074: * @return a term iterator
075: */
076: public TermIterator allSubterms() {
077: return new TermIterator(getAllSubterms());
078: }
079:
080: /**
081: * Apply a replacement to a term.
082: * Prova: see nt.terms[i]
083: * @return the new term resulting from applying the replacement
084: * @param r the replacement
085: */
086: public Term apply(Replacement r) {
087: Term[] t = getTerms();
088:
089: // create a new term
090: ComplexTermImpl nt = new ComplexTermImpl();
091:
092: copyStructure(nt);
093:
094: for (int i = 0; i < t.length; i++) {
095: nt.terms[i] = t[i].apply(r);
096: // nt.setTerm (t[i].apply (r), i);
097: }
098:
099: return nt;
100: }
101:
102: public void getAllSubtermsA(List result) {
103: result.add(this );
104: for (int i = 0; i < terms.length; i++) {
105: terms[i].getAllSubtermsA(result);
106: }
107: }
108:
109: public void getAllSubtermsA(List result, boolean left) {
110: Term[] tt = terms;
111: ComplexTerm ct = this ;
112: do {
113: if (left)
114: result.add(ct);
115: tt[1].getAllSubtermsA(result, true);
116: if (tt[0] instanceof ComplexTerm) {
117: ct = (ComplexTerm) tt[0];
118: tt = ct.getTerms();
119: } else {
120: tt[0].getAllSubtermsA(result, true);
121: tt = null;
122: }
123: } while (tt != null);
124:
125: }
126:
127: public boolean getAllSubtermsB(List result, Iterator aux) {
128: Term[] tt = terms;
129: ComplexTerm ct = this ;
130: do {
131: Object t = ConstantTermImpl.nextNotNull(aux);
132: if (t == null) {
133: return false;
134: }
135: if (!(t instanceof ComplexTerm)) {
136: result.add(t);
137: return false;
138: }
139: aux.remove();
140: if (!tt[1].getAllSubtermsB(result, aux)) {
141: return false;
142: }
143: if (tt[0] instanceof ComplexTerm) {
144: ct = (ComplexTerm) tt[0];
145: tt = ct.getTerms();
146: } else {
147: if (!tt[0].getAllSubtermsB(result, aux)) {
148: return false;
149: }
150: tt = null;
151: }
152: } while (tt != null);
153: return true;
154: }
155:
156: public boolean getAllSubtermsB(List result, Iterator aux,
157: boolean left) {
158: if (left) {
159: Object t = ConstantTermImpl.nextNotNull(aux);
160: if (t == null) {
161: return false;
162: }
163: if (!(t instanceof ComplexTerm)) {
164: result.add(this );
165: return false;
166: }
167: aux.remove();
168: }
169: for (int i = terms.length; i-- > 0;) {
170: left = i != 0;
171: if (!terms[i].getAllSubtermsB(result, aux, left)) {
172: return false;
173: }
174: }
175: return true;
176: }
177:
178: /**
179: * Indicates whether the term containes variables.
180: * @return true if the term contains a variable, false otherwise. Looks up the term tree recursively.
181: */
182: public boolean containsVariables() {
183: for (TermIterator e = terms(); e.hasMoreTerms();) {
184: if (e.nextTerm().containsVariables()) {
185: return true;
186: }
187: }
188:
189: return false;
190: }
191:
192: /**
193: * Indicates whether the term contains the provided variable term.
194: * @return true if the term contains the variable term provided, false otherwise
195: * @param var a variable term
196: */
197: public boolean containsVariable(VariableTerm var) {
198: for (int i = terms.length; i-- != 0;) {
199: if (terms[i].containsVariable(var)) {
200: return true;
201: }
202: }
203:
204: return false;
205: }
206:
207: /**
208: * Copy the structure, i.e. length of the terms, types of the terms and methods
209: * into the term passed as parameter.
210: * @param t another complex term that takes the structure from this term
211: */
212: private void copyStructure(ComplexTermImpl t) {
213: t.types = types;
214: t.terms = new Term[terms.length];
215: t.function = function;
216: }
217:
218: /**
219: * Check whether objects are equal.
220: * @param obj the object to compare this object with
221: * @return true if the objects are equal, false otherwise
222: */
223: public boolean equals(Object obj) {
224: if ((obj != null) && (obj instanceof ComplexTermImpl)) {
225: ComplexTermImpl t = (ComplexTermImpl) obj;
226: boolean result = (function == null) ? t.function == null
227: : function.equals(t.function);
228: Term[] terms1 = terms;
229: Term[] terms2 = t.terms;
230:
231: for (int i = 0; i < terms.length; i++) {
232: result = result
233: && (((terms[i] == null) && (terms2[i] == null)) || (terms1[i]
234: .equals(terms2[i])));
235:
236: if (!result) {
237: return false;
238: }
239: }
240:
241: return result;
242: }
243:
244: return false;
245: }
246:
247: /**
248: * Get an array comprising all subterms, including the term itself.
249: * Looks up the term tree recursively.
250: * @return an array of terms
251: */
252: public org.mandarax.kernel.Term[] getAllSubterms() {
253: Vector t = new Vector();
254: Term c = null;
255:
256: t.addElement(this );
257:
258: for (TermIterator e = terms(); e.hasMoreTerms();) {
259: c = e.nextTerm();
260:
261: for (TermIterator ec = c.allSubterms(); ec.hasMoreTerms();) {
262: t.addElement(ec.nextTerm());
263: }
264: }
265:
266: // copy collected terms in an array
267: Term[] arr = new Term[t.size()];
268:
269: t.copyInto(arr);
270:
271: return arr;
272: }
273:
274: /**
275: * Get the object constructing the complex.
276: * @return the function of this term
277: */
278: protected Constructor getConstructor() {
279: return getFunction();
280: }
281:
282: /**
283: * Get the function.
284: * @return org.mandarax.kernel.Function
285: */
286: public org.mandarax.kernel.Function getFunction() {
287: return function;
288: }
289:
290: /**
291: * Get the type of the term.
292: * @return the term type
293: */
294: public Class getType() {
295: return getFunction().getReturnType();
296: }
297:
298: /**
299: * Get the hash code of a fact.
300: * @return the hash value
301: */
302: public int hashCode() {
303: int i = (function == null) ? 0 : function.hashCode();
304:
305: if (terms.length == 0) {
306: return i;
307: }
308:
309: if (terms.length == 1) {
310: return i ^ ((terms[0] == null) ? 0 : terms[0].hashCode());
311: } else {
312: return i
313: ^ ((terms[0] == null) ? 0 : terms[0].hashCode())
314: ^ ((terms[terms.length - 1] == null) ? 0
315: : terms[terms.length - 1].hashCode());
316: }
317: }
318:
319: /**
320: * Indicates whether the term is compound.
321: * @return true
322: */
323: public boolean isCompound() {
324: return true;
325: }
326:
327: /**
328: * Indicates whether the term is a constant.
329: * @return false
330: */
331: public boolean isConstant() {
332: return false;
333: }
334:
335: /**
336: * Indicates whether the object (usually a term or a clause set) can be performed
337: * using the java semantics.
338: * @return a boolean
339: */
340: public boolean isExecutable() {
341: if ((function != null) && function.isExecutable()) {
342: Term[] t = getTerms();
343:
344: for (int i = 0; i < t.length; i++) {
345: if (!t[i].isExecutable()) {
346: return false;
347: }
348: }
349:
350: return true;
351: }
352:
353: return false;
354: }
355:
356: /**
357: * Indicates whether the term is a variable.
358: * @return false
359: */
360: public boolean isVariable() {
361: return false;
362: }
363:
364: /**
365: * Resolve a complex term: if supported, the function
366: * should be performed using its semantic. E.g., for a complex term
367: * like <i>color(window)</i> the function <i>color</i> is performed for the <i>window</i>
368: * object and the result (e.g., <i>white</i>) is returned.
369: * Note that not all functions support this (since not all functions
370: * have a semantic), and the operation can also fail
371: * in case <i>window</i> is a variable term. In these cases we throw an exception.
372: * @param session a session object
373: * @return the result of resolving the term
374: * @throws java.lang.UnsupportedOperationException
375: * @throws java.lang.IllegalArgumentException
376: */
377: public Object resolve(Session session)
378: throws UnsupportedOperationException,
379: IllegalArgumentException {
380: return function.perform(terms, session);
381: }
382:
383: // /**
384: // * Resolve a complex term: if supported, the function
385: // * should be performed using its semantic. E.g., for a complex term
386: // * like <i>color(window)</i> the function <i>color</i> is performed for the <i>window</i>
387: // * object and the result (e.g., <i>white</i>) is returned.
388: // * Note that not all functions support this (since not all functions
389: // * have a semantic), and the operation can also fail
390: // * in case <i>window</i> is a variable term. In these cases we throw an exception.
391: // * @return the result of resolving the term
392: // * @throws java.lang.UnsupportedOperationException
393: // * @throws java.lang.IllegalArgumentException
394: // */
395: // public Object resolve()
396: // throws UnsupportedOperationException, IllegalArgumentException {
397: // return null;//return function.perform (terms);
398: // }
399:
400: /**
401: * Indicates whether the object is the same as the parameter.
402: * This function does not compare subterms but only the functions !
403: * @return true if the both objects are the same
404: * @param t another term
405: */
406: public boolean sameAs(Term t) {
407: if (!(t instanceof org.mandarax.kernel.ComplexTerm)) {
408: return false;
409: }
410:
411: return (getFunction().equals(((ComplexTerm) t).getFunction()));
412: }
413:
414: /**
415: * Set a new function.
416: * @param f the function
417: */
418: public void setFunction(Function f) {
419: function = f;
420: terms = new Term[f.getStructure().length];
421: types = f.getStructure();
422: }
423: }
|