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.reflect;
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: * Apply <code>Op</code> -- given two arguments, A and B, uses the
036: * value of A as an argument to B, in other workds "B(A())".
037: * <pre>
038: * Rearranges arguments to make
039: * <code> "(getField isNull)" </code>
040: * be more like <code>
041: * new Op() {
042: * public boolean execute(Object o) {
043: * Object tmp = "getField".getObject(o);
044: * return "is:Null".execute(tmp);
045: * }
046: * }
047: * </code>
048: * </pre>
049: */
050: public final class ApplyOp extends OpImpl {
051:
052: public Op u1;
053:
054: public Op u2;
055:
056: public ApplyOp() {
057: }
058:
059: public ApplyOp(final Op u1, final Op u2) {
060: // Make sure that u2 is be a boolean predicate
061: if (!(u2.isReturnBoolean())) {
062: throw new IllegalArgumentException("\""
063: + OpCodes.APPLY_NAME
064: + "\" given invalid second argument " + u2
065: + " with non-boolean return type of "
066: + u2.getReturnClass());
067: }
068: this .u1 = u1;
069: this .u2 = u2;
070: }
071:
072: public final int getID() {
073: return OpCodes.APPLY_ID;
074: }
075:
076: public final Op parse(final OpParser p) throws ParseException {
077: TypeList origTypeList = p.cloneTypeList();
078:
079: // typically u1 is a method...
080: Op u1 = p.nextOp();
081: if (u1 == null) {
082: throw new ParseException("\"" + OpCodes.APPLY_NAME
083: + "\" missing MethodOp");
084: }
085:
086: Op u2 = p.nextOp();
087: if (u2 == null) {
088: throw new ParseException("\"" + OpCodes.APPLY_NAME
089: + "\" given MethodOp " + u1
090: + "but missing applied Op");
091: } else if (!(u2.isReturnBoolean())) {
092: throw new ParseException("\"" + OpCodes.APPLY_NAME
093: + "\" given invalid second argument " + u2
094: + " with non-boolean return type of "
095: + u2.getReturnClass());
096: }
097:
098: Op u3 = p.nextOp();
099: if (u3 != null) {
100: throw new ParseException("\"" + OpCodes.APPLY_NAME
101: + "\" expecting single Op argument, "
102: + "but given additional " + u3.getClass().getName());
103: }
104:
105: int u2id = u2.getID();
106: if ((u2id == OpCodes.TRUE_ID) || (u2id == OpCodes.FALSE_ID)) {
107: // (apply u1 true) is (true)
108: // (apply u1 false) is (false)
109: return u2;
110: } else {
111: // (apply u1 u2)
112: // typical case
113: this .u1 = u1;
114: this .u2 = u2;
115: p.setTypeList(origTypeList);
116: return this ;
117: }
118: }
119:
120: public boolean execute(final Object o) {
121: return u2.execute(u1.operate(o));
122: }
123:
124: public final void setConst(final String key, final Object val) {
125: u1.setConst(key, val);
126: u2.setConst(key, val);
127: }
128:
129: public final void accept(TreeVisitor visitor) {
130: if (u1 != null) {
131: if (!(visitor.isVerbose()) && (u2 != null)) {
132: // special shorthand for method/fields
133: int u1id = u1.getID();
134: if (u1id == OpCodes.METHOD_ID) {
135: MethodOp m1 = (MethodOp) u1;
136: if (m1.argOps == MethodOp.zeroOps) {
137: // (method op)
138: String sm1 = m1.getMethodString(false);
139: visitor.visitWord(sm1);
140: u2.accept(visitor);
141: visitor.visitEnd();
142: return;
143: }
144: } else if (u1id == OpCodes.FIELD_ID) {
145: // (field op)
146: String sf1 = ((FieldOp) u1).getFieldString(false);
147: visitor.visitWord(sf1);
148: u2.accept(visitor);
149: visitor.visitEnd();
150: return;
151: }
152: }
153: // longhand (apply u1 u2)
154: visitor.visitWord(OpCodes.APPLY_NAME);
155: u1.accept(visitor);
156: if (u2 != null) {
157: u2.accept(visitor);
158: } else {
159: visitor.visitConstant(null, "?");
160: }
161: visitor.visitEnd();
162: } else {
163: // (apply ("?") ("?"))
164: visitor.visitWord(OpCodes.APPLY_NAME);
165: visitor.visitConstant(null, "?");
166: visitor.visitConstant(null, "?");
167: visitor.visitEnd();
168: }
169: }
170: }
|