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: import org.mandarax.kernel.Constructor;
021: import org.mandarax.kernel.LObject;
022: import org.mandarax.kernel.Term;
023: import org.mandarax.util.TermIterator;
024:
025: /**
026: * Abstract super class for logical entities such as complex terms and facts.
027: * @author <A href="http://www-ist.massey.ac.nz/JBDietrich" target="_top">Jens Dietrich</A>
028: * @version 3.4 <7 March 05>
029: * @since 1.1
030: */
031: public abstract class Complex extends LObject {
032:
033: protected Term[] terms = null;
034: protected Class[] types = null;
035:
036: /** Cache the string representation for optimized debugging. */
037: private transient String cachedToString = null;
038:
039: /**
040: * Constructor.
041: */
042: protected Complex() {
043: super ();
044: }
045:
046: /**
047: * Get the object constructing the complex, i.e. the predicate or function.
048: * @return the constructor
049: */
050: protected abstract Constructor getConstructor();
051:
052: /**
053: * Get the terms (as an array).
054: * @return an array of terms
055: */
056: public Term[] getTerms() {
057: return terms;
058: }
059:
060: /**
061: * Set the terms (as an array).
062: * @param t an array of terms
063: */
064: public void setTerms(Term[] t) {
065: cachedToString = null;
066:
067: // new in 3.2 , more checks, enforce all checks done in setTerm
068: if (this .getConstructor() == null)
069: throw new IllegalStateException(
070: "Constructor (predicate or function) must be set before terms can be set in "
071: + this );
072: if (this .terms == null)
073: this .terms = new Term[this .getConstructor().getStructure().length];
074: for (int i = 0; i < t.length; i++) {
075: setTerm(t[i], i);
076: }
077: }
078:
079: /**
080: * Set a term at a certain position. Note that in case the type of the term does not
081: * match the type required by the constructor we do not throw an exception.
082: * Instead, we just do not set the term.
083: * <br>As from 3.2, some new checks have been added an runtime exceptions are thrown if
084: * one of these tests fails
085: * @param t a term
086: * @param i a position
087: */
088: public void setTerm(Term t, int i) {
089: cachedToString = null;
090:
091: // check whether the predicate is there and whether the slot is available
092: if (getConstructor() == null) {
093: throw new IllegalStateException(
094: "Constructor (predicate or function) must be set before terms can be set in \""
095: + this + "\"");
096: }
097: if (types == null) {
098: throw new IllegalStateException(
099: "Types must be set before terms can be set in "
100: + this );
101: }
102: if (terms.length <= i) {
103: String msg = new StringBuffer().append(
104: "Not enough terms slots in \"").append(this )
105: .append("\" to set term \"").append(t).append(
106: "\" at position ").append(i).toString();
107: throw new IllegalArgumentException(msg);
108: }
109: if (i < 0) {
110: String msg = new StringBuffer().append(
111: "Cannot set term at position 0 in \"").append(this )
112: .append("\"").toString();
113: throw new IllegalArgumentException(msg);
114: }
115:
116: // check whether the type matches the method type and if so, set the term
117: if (t == null || types[i].isAssignableFrom(t.getType())) {
118: terms[i] = t;
119: } else {
120: String msg = new StringBuffer()
121: .append("Cannot set term \"").append(t).append(
122: "\" in \"").append(this ).append(
123: "\" at position ").append(i).append(
124: " - the term type is \"").append(
125: t.getType())
126: .append("\" but expected is \"").append(types[i])
127: .append("\"").toString();
128: throw new IllegalArgumentException(msg);
129: }
130: }
131:
132: /**
133: * Iterate the terms.
134: * @return a term iterator
135: */
136: public TermIterator terms() {
137: return new TermIterator(terms);
138: }
139:
140: /**
141: * Convert the receiver to a string.
142: * @return the string representation of this object
143: */
144: public String toString() {
145: if (cachedToString == null) {
146: StringBuffer buf = new StringBuffer();
147:
148: buf.append(getConstructor().getName());
149: buf.append("(");
150:
151: boolean first = true;
152:
153: for (TermIterator e = terms(); e.hasMoreTerms();) {
154: if (first) {
155: first = false;
156: } else {
157: buf.append(",");
158: }
159:
160: Term nextTerm = e.nextTerm();
161:
162: buf.append((nextTerm == null) ? "null" : nextTerm
163: .toString());
164: }
165:
166: buf.append(")");
167:
168: cachedToString = new String(buf);
169: }
170: return cachedToString;
171: }
172: }
|