001: /*
002: * <copyright>
003: *
004: * Copyright 1997-2004 BBNT Solutions, LLC
005: * under sponsorship of the Defense Advanced Research Projects
006: * Agency (DARPA).
007: *
008: * You can redistribute this software and/or modify it under the
009: * terms of the Cougaar Open Source License as published on the
010: * Cougaar Open Source Website (www.cougaar.org).
011: *
012: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
013: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
014: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
015: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
016: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
017: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
018: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
019: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
020: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
021: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
022: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
023: *
024: * </copyright>
025: */
026:
027: package org.cougaar.lib.contract.lang.compare;
028:
029: import java.util.*;
030:
031: import org.cougaar.lib.contract.lang.*;
032: import org.cougaar.lib.contract.lang.op.OpCodes;
033: import org.cougaar.lib.contract.lang.op.constant.*;
034: import org.cougaar.lib.contract.lang.op.list.*;
035: import org.cougaar.lib.contract.lang.op.logical.*;
036: import org.cougaar.lib.contract.lang.op.reflect.*;
037:
038: /**
039: * Compares two <code>Op</code>s for equality.
040: */
041: public final class Equal implements OpCodes {
042:
043: private Equal() {
044: }
045:
046: public static final boolean compute(final Object o1, final Object o2) {
047: return ((o1 instanceof Op) ? compute((Op) o1, o2) : false);
048: }
049:
050: public static final boolean compute(final Op o1, final Object o2) {
051: return ((o2 instanceof Op) ? compute(o1, (Op) o2) : false);
052: }
053:
054: public static final boolean compute(final Op o1, final Op o2) {
055: switch (o1.getID()) {
056: // constant
057: case CONSTANT_ID:
058: return compute((ConstantOp) o1, o2);
059: case GET_ID:
060: return compute((GetOp) o1, o2);
061: // list
062: case ALL_ID:
063: return compute((AllOp) o1, o2);
064: case EMPTY_ID:
065: return compute((EmptyOp) o1, o2);
066: case EXISTS_ID:
067: return compute((ExistsOp) o1, o2);
068: // logical
069: case AND_ID:
070: return compute((AndOp) o1, o2);
071: case FALSE_ID:
072: return compute((FalseOp) o1, o2);
073: case NOT_ID:
074: return compute((NotOp) o1, o2);
075: case OR_ID:
076: return compute((OrOp) o1, o2);
077: case TRUE_ID:
078: return compute((TrueOp) o1, o2);
079: // reflect
080: case APPLY_ID:
081: return compute((ApplyOp) o1, o2);
082: case FIELD_ID:
083: return compute((FieldOp) o1, o2);
084: case INSTANCEOF_ID:
085: return compute((InstanceOfOp) o1, o2);
086: case METHOD_ID:
087: return compute((MethodOp) o1, o2);
088: case REFLECT_ID:
089: throw new UnsupportedOperationException(
090: "ReflectOps should be parsed to MethodOps/FieldOps!");
091: case THIS_ID:
092: return compute((ThisOp) o1, o2);
093: default:
094: throw new RuntimeException("Unknown Op: " + o1);
095: }
096: }
097:
098: protected static final boolean compute(final ConstantOp o1,
099: final Op o2) {
100: if (o2.getID() == CONSTANT_ID) {
101: ConstantOp u2 = ((ConstantOp) o2);
102: // constants are equal if both the clazz and value are equal
103: if (o1.clazz == u2.clazz) {
104: Object o1val = o1.val;
105: Object o2val = u2.val;
106: if (o1val == null) {
107: return (o2val == null);
108: } else {
109: return o1val.equals(o2val);
110: }
111: } else {
112: return false;
113: }
114: } else {
115: return false;
116: }
117: }
118:
119: protected static final boolean compute(final GetOp o1, final Op o2) {
120: if (o2.getID() == GET_ID) {
121: // gets are equal if both the key and clazz are equal
122: GetOp u2 = (GetOp) o2;
123: return ((o1.key).equals(u2.key) && ((o1.clazz) == (u2.clazz)));
124: } else {
125: return false;
126: }
127: }
128:
129: protected static final boolean compute(final AllOp o1, final Op o2) {
130: if (o2.getID() == ALL_ID) {
131: // alls are equal if the element-operators are equal
132: return compute((o1.u), (((AllOp) o2).u));
133: } else {
134: return false;
135: }
136: }
137:
138: protected static final boolean compute(final EmptyOp o1, final Op o2) {
139: // single EmptyOp
140: return ((o1 == o2) && (o1 != null));
141: }
142:
143: protected static final boolean compute(final ExistsOp o1,
144: final Op o2) {
145: if (o2.getID() == EXISTS_ID) {
146: // exists are equal if the element-operators are equal
147: return compute((o1.u), (((ExistsOp) o2).u));
148: } else {
149: return false;
150: }
151: }
152:
153: protected static final boolean compute(final AndOp o1, final Op o2) {
154: if (o2.getID() == AND_ID) {
155: // and1 is equal to and2 if all of and1's elements are in and2
156: Op[] ops = o1.ops;
157: Op[] xops = ((AndOp) o2).ops;
158: int nxops = xops.length;
159: // for each operator in and1
160: for (int i = 0; i < ops.length; i++) {
161: Op ui = ops[i];
162: // for each operator in and2
163: for (int j = 0;; j++) {
164: if (j >= nxops) {
165: // and1[i] is not in and2[]
166: return false;
167: }
168: if (compute(ui, xops[j])) {
169: // and1[i] was found in and2[]
170: break;
171: }
172: }
173: }
174: // all of and1's elements were in and2
175: return true;
176: } else {
177: return false;
178: }
179: }
180:
181: protected static final boolean compute(final FalseOp o1, final Op o2) {
182: // single FalseOp
183: return ((o1 == o2) && (o1 != null));
184: }
185:
186: protected static final boolean compute(final NotOp o1, final Op o2) {
187: if (o2.getID() == NOT_ID) {
188: // nots are equal if their operator's are equal
189: return compute(o1.u1, ((NotOp) o2).u1);
190: } else {
191: return false;
192: }
193: }
194:
195: protected static final boolean compute(final OrOp o1, final Op o2) {
196: if (o2.getID() == OR_ID) {
197: // or1 is equal to or2 if any of or1's elements are in or2
198: Op[] ops = o1.ops;
199: Op[] xops = ((OrOp) o2).ops;
200: int nxops = xops.length;
201: // for each operator in or1
202: for (int i = 0; i < ops.length; i++) {
203: Op ui = ops[i];
204: // for each operator in or2
205: for (int j = 0; j < nxops; j++) {
206: if (compute(ui, xops[j])) {
207: // or1[i] equals or2[j]
208: return true;
209: }
210: }
211: }
212: // none of or1's elements were in or2
213: return false;
214: } else {
215: return false;
216: }
217: }
218:
219: protected static final boolean compute(final TrueOp o1, final Op o2) {
220: // single TrueOp
221: return ((o1 == o2) && (o1 != null));
222: }
223:
224: protected static final boolean compute(final ApplyOp o1, final Op o2) {
225: if (o2.getID() == APPLY_ID) {
226: // apply1 is equal to apply2 if their arguments are equal
227: ApplyOp x = (ApplyOp) o2;
228: Op u1 = o1.u1;
229: Op xu1 = x.u1;
230: // test if the operators are the same
231: if (!(compute(u1, xu1))) {
232: return false;
233: }
234: Op u2 = o1.u2;
235: Op xu2 = x.u2;
236: // test if the operators are the same
237: return (compute(u2, xu2));
238: } else {
239: return false;
240: }
241: }
242:
243: protected static final boolean compute(final FieldOp o1, final Op o2) {
244: if (o2.getID() == FIELD_ID) {
245: // fields are the same if they are equal
246: FieldOp f2 = (FieldOp) o2;
247: return ((o1.field).equals(f2.field));
248: } else {
249: return false;
250: }
251: }
252:
253: protected static final boolean compute(final InstanceOfOp o1,
254: final Op o2) {
255: if (o2.getID() == INSTANCEOF_ID) {
256: // instanceofs are equal if they have the same "not" and "clazz"
257: Type t1 = (Type) o1;
258: Type t2 = (Type) o2;
259: if (t1.isNot() != t2.isNot()) {
260: return false;
261: }
262: Class cl1 = t1.getClazz();
263: Class cl2 = t2.getClazz();
264: return ((cl1 == cl2) || (cl1.equals(cl2)));
265: } else {
266: return false;
267: }
268: }
269:
270: protected static final boolean compute(final MethodOp o1,
271: final Op o2) {
272: if (o2.getID() == METHOD_ID) {
273: // methods are the same if they call the same method and have the
274: // same arguments
275: MethodOp m2 = (MethodOp) o2;
276: if (!((o1.meth).equals(m2.meth))) {
277: return false;
278: }
279: Op[] ao1 = o1.argOps;
280: Op[] ao2 = m2.argOps;
281: if (ao1 == MethodOp.zeroOps) {
282: return (ao2 == MethodOp.zeroOps);
283: } else if (ao1 != null) {
284: if ((ao2 == MethodOp.zeroOps) || (ao2 == null)
285: || (ao2.length != ao1.length)) {
286: return false;
287: }
288: for (int i = 0; i < ao1.length; i++) {
289: if (!(compute(ao1[i], ao2[i]))) {
290: return false;
291: }
292: }
293: return true;
294: } else {
295: return (ao2 == null);
296: }
297: } else {
298: return false;
299: }
300: }
301:
302: protected static final boolean compute(final ThisOp o1, final Op o2) {
303: // type is context-sensitive, so just see if the
304: // other op is also a thisOp
305: return (o2.getID() == THIS_ID);
306: }
307: }
|