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.constant;
028:
029: import org.cougaar.lib.contract.lang.*;
030: import org.cougaar.lib.contract.lang.op.OpCodes;
031: import org.cougaar.lib.contract.lang.cache.ClassCache;
032:
033: /**
034: * Gets a constant state variable.
035: * <p>
036: * <pre>
037: * This value only changes when the <code>Op</code> is initialized using
038: * <tt>setConst</tt>. Also, if the type is specified via
039: * (get "key" "classname")
040: * e.g.
041: * (get "myList" "java.util.List")
042: * then the <tt>setConst</tt> value must be of the given type.
043: * </pre>
044: * <p>
045: * Note that "SetOp" is not implemented in the contract language --
046: * only code external to this contract language should be setting
047: * constants.
048: * <p>
049: * The "spreading" of the <tt>setConst</tt> is only an artifact of the
050: * current "tree-like" structure -- a bytecode translator would shortcut
051: * most of this work.
052: */
053: public final class GetOp extends OpImpl {
054:
055: public String key;
056: public Object val;
057: public Class clazz;
058:
059: public GetOp() {
060: }
061:
062: public final int getID() {
063: return OpCodes.GET_ID;
064: }
065:
066: public final Op parse(final OpParser p) throws ParseException {
067: Op u1 = p.nextOp();
068: if ((u1 == null) || (u1.getID() != OpCodes.CONSTANT_ID)) {
069: throw new ParseException(
070: "\""
071: + OpCodes.GET_NAME
072: + "\" expecting \"key\" argument, not "
073: + ((u1 != null) ? u1.getClass().toString()
074: : "null"));
075: }
076:
077: // take String key
078: Object u1val = ((ConstantOp) u1).val;
079: if (!(u1val instanceof String)) {
080: throw new ParseException("\""
081: + OpCodes.GET_NAME
082: + "\" expecting String \"key\", not "
083: + ((u1val != null) ? u1val.getClass().toString()
084: : "null"));
085: }
086: this .key = (String) u1val;
087:
088: // value is initially null
089: this .val = null;
090:
091: Op u2 = p.nextOp();
092: if (u2 == null) {
093: // type is Object
094: this .clazz = Object.class;
095: } else {
096: // take constant string type
097: if (u2.getID() != OpCodes.CONSTANT_ID) {
098: throw new ParseException("\"" + OpCodes.GET_NAME
099: + "\" expecting \"class\" argument, not "
100: + u2.getClass().toString());
101: }
102: Object u2val = ((ConstantOp) u2).val;
103: if (!(u2val instanceof String)) {
104: throw new ParseException("\""
105: + OpCodes.GET_NAME
106: + "\" expecting String \"class\", not "
107: + ((u2val != null) ? u2val.getClass()
108: .toString() : "null"));
109: }
110:
111: this .clazz = ClassCache.lookup((String) u2val);
112: if (clazz == null) {
113: throw new ParseException("\"" + OpCodes.GET_NAME
114: + "\" of unknown Class " + u2val);
115: }
116:
117: Op u3 = p.nextOp();
118: if (u3 != null) {
119: throw new ParseException("\"" + OpCodes.GET_NAME
120: + "\" expecting single \"key\" argument,"
121: + " but given additional "
122: + u3.getClass().toString());
123: }
124: }
125:
126: p.setTypeList(clazz);
127: return this ;
128: }
129:
130: public final boolean isReturnBoolean() {
131: return (clazz == Boolean.TYPE);
132: }
133:
134: public final Class getReturnClass() {
135: return clazz;
136: }
137:
138: public final boolean execute(final Object o) {
139: // ignore o
140: return ((Boolean) val).booleanValue();
141: }
142:
143: public final Object operate(final Object o) {
144: // ignore o, return val of type clazz
145: return val;
146: }
147:
148: public final void setConst(final String key, final Object val) {
149: if ((this .key).equals(key)) {
150: // check type
151: if ((val != null) && (clazz != Object.class)
152: && (!((val.getClass()).isAssignableFrom(clazz)))) {
153: throw new IllegalArgumentException("\""
154: + OpCodes.GET_NAME + "\" key \"" + key
155: + "\" expecting type \"" + clazz + "\", not \""
156: + val.getClass() + "\"");
157: }
158: this .val = val;
159: }
160: }
161:
162: public final void accept(TreeVisitor visitor) {
163: // (get (key) [(type)])
164: visitor.visitWord(OpCodes.GET_NAME);
165: visitor.visitConstant(null, key);
166: if (clazz != Object.class) {
167: visitor.visitConstant(null, clazz.getName());
168: }
169: visitor.visitEnd();
170: }
171: }
|