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.op.logical;
028:
029: import java.util.*;
030:
031: import org.cougaar.lib.contract.lang.*;
032: import org.cougaar.lib.contract.lang.op.OpCodes;
033:
034: /**
035: * "and" <code>Op</code> -- returns true if all the given <code>Op</code>
036: * arguments return true.
037: **/
038: public final class AndOp extends OpImpl {
039:
040: public Op[] ops;
041:
042: public AndOp() {
043: }
044:
045: public final int getID() {
046: return OpCodes.AND_ID;
047: }
048:
049: public final Op parse(final OpParser p) throws ParseException {
050: TypeList origTypeList = p.cloneTypeList();
051:
052: Op u1 = p.nextOp();
053: if (u1 == null) {
054: // (and) is (false)
055: return FalseOp.singleInstance;
056: } else if (!(u1.isReturnBoolean())) {
057: throw new ParseException("\"" + OpCodes.AND_NAME
058: + "\" given invalid argument 1 of " + u1
059: + " with non-boolean return type of "
060: + u1.getReturnClass());
061: }
062:
063: Op uCurr = p.nextOp();
064: if (uCurr == null) {
065: // (and u1) is (u1)
066: p.setTypeList(origTypeList);
067: return u1;
068: } else if (!(uCurr.isReturnBoolean())) {
069: throw new ParseException("\"" + OpCodes.AND_NAME
070: + "\" given invalid argument 2 of " + uCurr
071: + " with non-boolean return type of "
072: + uCurr.getReturnClass());
073: }
074:
075: // Make list, sorted as given, expanding Ands out.
076: // Could replace "contains" with relationship comparison
077: List nl = new ArrayList(3);
078: boolean hasTrue = false;
079: int nlsize = 0;
080: if (u1.getID() == OpCodes.TRUE_ID) {
081: hasTrue = true;
082: } else {
083: nl.add(u1);
084: nlsize++;
085: }
086: parseOps: while (true) {
087: switch (uCurr.getID()) {
088: case OpCodes.TRUE_ID:
089: // (and x true y) is (and x y)
090: hasTrue = true;
091: break;
092: case OpCodes.FALSE_ID:
093: // (and x false y) is (false)
094: hasTrue = false;
095: nlsize = 0;
096: while (p.nextOp() != null) {
097: // skip remaining ops
098: }
099: break parseOps;
100: case OpCodes.AND_ID: {
101: // (and x (and m n o) y) is (and x m n o y)
102: // sub-and can't contain (true/false/and), since it was created by
103: // this parse method! Therefore no need for recursion...
104: Op[] xops = ((AndOp) uCurr).ops;
105: for (int j = 0; j < xops.length; j++) {
106: Op uj = xops[j];
107: // (and x y x) is (and x y)
108: if (!(nl.contains(uj))) {
109: nl.add(uj);
110: nlsize++;
111: }
112: }
113: }
114: break;
115: default:
116: // (and x y x) is (and x y)
117: if (!(nl.contains(uCurr))) {
118: nl.add(uCurr);
119: nlsize++;
120: }
121: break;
122: }
123: uCurr = p.nextOp();
124: if (uCurr == null) {
125: break parseOps;
126: } else if (!(uCurr.isReturnBoolean())) {
127: throw new ParseException("\"" + OpCodes.AND_NAME
128: + "\" given invalid argument " + nlsize
129: + " of " + uCurr
130: + " with non-boolean return type of "
131: + uCurr.getReturnClass());
132: }
133: }
134:
135: // return to original type
136: p.setTypeList(origTypeList);
137:
138: if (nlsize == 0) {
139: // (and) is (false)
140: if (hasTrue) {
141: return TrueOp.singleInstance;
142: } else {
143: return FalseOp.singleInstance;
144: }
145: } else if (nlsize == 1) {
146: // (and x) is (x)
147: return (Op) nl.get(0);
148: } else {
149: // set and
150: // FIXME: prefer instance tests in front!
151: ops = new Op[nlsize];
152: for (int k = 0; k < nlsize; k++) {
153: ops[k] = (Op) nl.get(k);
154: }
155: return this ;
156: }
157: }
158:
159: public final boolean execute(final Object o) {
160: for (int i = 0; i < ops.length; i++) {
161: if (!(ops[i].execute(o))) {
162: return false;
163: }
164: }
165: return true;
166: }
167:
168: public final void setConst(final String key, final Object val) {
169: for (int i = 0; i < ops.length; i++) {
170: ops[i].setConst(key, val);
171: }
172: }
173:
174: public final void accept(TreeVisitor visitor) {
175: // (and op0 op1 .. opN)
176: visitor.visitWord(OpCodes.AND_NAME);
177: if (ops != null) {
178: for (int i = 0; i < ops.length; i++) {
179: ops[i].accept(visitor);
180: }
181: } else {
182: visitor.visitConstant(null, "?");
183: }
184: visitor.visitEnd();
185: }
186: }
|