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: * "or" <code>Op</code> -- returns true if any of the given <code>Op</code>s
036: * return true.
037: **/
038: public final class OrOp extends OpImpl {
039:
040: public Op[] ops;
041:
042: public OrOp() {
043: }
044:
045: public final int getID() {
046: return OpCodes.OR_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: // (or) is (false)
055: return FalseOp.singleInstance;
056: } else if (!(u1.isReturnBoolean())) {
057: throw new ParseException("\"" + OpCodes.OR_NAME
058: + "\" given invalid argument 1 of " + u1
059: + " with non-boolean return type of "
060: + u1.getReturnClass());
061: }
062:
063: p.setTypeList((TypeList) origTypeList.clone());
064: Op uCurr = p.nextOp();
065: if (uCurr == null) {
066: // (or u1) is (u1)
067: return u1;
068: } else if (!(uCurr.isReturnBoolean())) {
069: throw new ParseException("\"" + OpCodes.OR_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 Ors out.
076: // Could replace "contains" with relationship comparison
077: List nl = new ArrayList(3);
078: nl.add(u1);
079: int nlsize = 1;
080: while (true) {
081: switch (uCurr.getID()) {
082: case OpCodes.TRUE_ID:
083: // (or x true y) is (true)
084: while (p.nextOp() != null) {
085: // skip remaining ops
086: }
087: p.setTypeList(origTypeList);
088: return uCurr;
089: case OpCodes.FALSE_ID:
090: // (or x false y) is (or x y)
091: break;
092: case OpCodes.OR_ID: {
093: // (or x (or m n o) y) is (or x m n o y)
094: // sub-or can't contain (true/false/or), since it was created by
095: // this parse method! Therefore no need for recursion...
096: Op[] xops = ((OrOp) uCurr).ops;
097: for (int j = 0; j < xops.length; j++) {
098: Op uj = xops[j];
099: // (or x y x) is (or x y)
100: if (!(nl.contains(uj))) {
101: nl.add(uj);
102: nlsize++;
103: }
104: }
105: }
106: break;
107: default:
108: // FIXME: if two or more children are AndOp, and they share
109: // instance tests, can hoist the tests.
110: // (or x y x) is (or x y)
111: if (!(nl.contains(uCurr))) {
112: nl.add(uCurr);
113: nlsize++;
114: }
115: }
116: p.setTypeList((TypeList) origTypeList.clone());
117: uCurr = p.nextOp();
118: if (uCurr == null) {
119: break;
120: } else if (!(uCurr.isReturnBoolean())) {
121: throw new ParseException("\"" + OpCodes.OR_NAME
122: + "\" given invalid argument " + nlsize
123: + " of " + uCurr
124: + " with non-boolean return type of "
125: + uCurr.getReturnClass());
126: }
127: }
128:
129: if (nlsize == 1) {
130: // (or x) is (x)
131: return (Op) nl.get(0);
132: } else {
133: // set or
134: ops = new Op[nlsize];
135: for (int k = 0; k < nlsize; k++) {
136: ops[k] = (Op) nl.get(k);
137: }
138: return this ;
139: }
140: }
141:
142: public final boolean execute(final Object o) {
143: for (int i = 0; i < ops.length; i++) {
144: if (ops[i].execute(o)) {
145: return true;
146: }
147: }
148: return false;
149: }
150:
151: public final void setConst(final String key, final Object val) {
152: for (int i = 0; i < ops.length; i++) {
153: ops[i].setConst(key, val);
154: }
155: }
156:
157: public final void accept(TreeVisitor visitor) {
158: // (or op0 op1 .. opN)
159: visitor.visitWord(OpCodes.OR_NAME);
160: if (ops != null) {
161: for (int i = 0; i < ops.length; i++) {
162: ops[i].accept(visitor);
163: }
164: } else {
165: visitor.visitConstant(null, "?");
166: }
167: visitor.visitEnd();
168: }
169: }
|