001: /*
002: * @(#)Expression.java 1.10 03/01/23
003: *
004: * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
005: * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
006: */
007:
008: package org.conform.mdl;
009:
010: /**
011: * An <code>Expression</code> object represents a primitive expression
012: * in which a single method is applied to a target and a set of
013: * arguments to return a result - as in <code>"a.getFoo()"</code>.
014: * <p>
015: * In addition to the properties of the super class, the
016: * <code>Expression</code> object provides a <em>value</em> which
017: * is the object returned when this expression is evaluated.
018: * The return value is typically not provided by the caller and
019: * is instead computed by dynamically finding the method and invoking
020: * it when the first call to <code>getValue</code> is made.
021: *
022: * @see #getValue
023: * @see #setValue
024: *
025: * @since 1.4
026: *
027: * @version 1.3 11/15/00
028: * @author Philip Milne
029: */
030:
031: class Expression extends Statement {
032:
033: private static Object unbound = new Object();
034:
035: private Object value = unbound;
036:
037: /**
038: * Creates a new <code>Statement</code> object with a <code>target</code>,
039: * <code>methodName</code> and <code>arguments</code> as per the parameters.
040: *
041: * @param target The target of this expression.
042: * @param methodName The methodName of this expression.
043: * @param arguments The arguments of this expression.
044: *
045: * @see #getValue
046: */
047: public Expression(Object target, String methodName,
048: Object[] arguments) {
049: super (target, methodName, arguments);
050: }
051:
052: /**
053: * Creates a new <code>Expression</code> object for a method
054: * that returns a result. The result will never be calculated
055: * however, since this constructor uses the <code>value</code>
056: * parameter to set the value property by calling the
057: * <code>setValue</code> method.
058: *
059: * @param value The value of this expression.
060: * @param target The target of this expression.
061: * @param methodName The methodName of this expression.
062: * @param arguments The arguments of this expression.
063: *
064: * @see #setValue
065: */
066: public Expression(Object value, Object target, String methodName,
067: Object[] arguments) {
068: this (target, methodName, arguments);
069: setValue(value);
070: }
071:
072: /**
073: * If the value property of this instance is not already set,
074: * this method dynamically finds the method with the specified
075: * methodName on this target with these arguments and calls it.
076: * The result of the method invocation is first copied
077: * into the value property of this expression and then returned
078: * as the result of <code>getValue</code>. If the value property
079: * was already set, either by a call to <code>setValue</code>
080: * or a previous call to <code>getValue</code> then the value
081: * property is returned without either looking up or calling the method.
082: * <p>
083: * The value property of an <code>Expression</code> is set to
084: * a unique private (non-<code>null</code>) value by default and
085: * this value is used as an internal indication that the method
086: * has not yet been called. A return value of <code>null</code>
087: * replaces this default value in the same way that any other value
088: * would, ensuring that expressions are never evaluated more than once.
089: * <p>
090: * See the <code>excecute<code> method for details on how
091: * methods are chosen using the dynamic types of the target
092: * and arguments.
093: *
094: * @see Statement#execute
095: * @see #setValue
096: *
097: * @return The result of applying this method to these arguments.
098: */
099: public Object getValue() throws Exception {
100: if (value == unbound) {
101: setValue(invoke());
102: }
103: return value;
104: }
105:
106: /**
107: * Sets the value of this expression to <code>value</code>.
108: * This value will be returned by the getValue method
109: * without calling the method associated with this
110: * expression.
111: *
112: * @param value The value of this expression.
113: *
114: * @see #getValue
115: */
116: public void setValue(Object value) {
117: this .value = value;
118: }
119:
120: /*pp*/String instanceName(Object instance) {
121: return instance == unbound ? "<unbound>" : super
122: .instanceName(instance);
123: }
124:
125: /**
126: * Prints the value of this expression using a Java-style syntax.
127: */
128: public String toString() {
129: return instanceName(value) + "=" + super.toString();
130: }
131: }
|