001: package com.xoetrope.builder.generic;
002:
003: import java.awt.Component;
004: import net.xoetrope.xml.XmlElement;
005: import net.xoetrope.xui.PageSupport;
006: import net.xoetrope.xui.XPage;
007: import net.xoetrope.xui.XProject;
008: import net.xoetrope.xui.evaluator.XDefaultAttributeEvaluator;
009:
010: /**
011: * <p>An attribute evaluator. This attribute evaluator extends the default
012: * evaluator by adding support for the ${values},${value} arguments. The
013: * evaluator also support mapping of attributes through the attribute names
014: * specified as ${attribName}.</p>
015: * <p>The attributes can also be defined in classes other than the current page
016: * or classes derived from XPage. The syntax for such expressions is as follows:</p>
017: * <ul>
018: * <li>1. <code>${mypackage.MyClass[referenceName].myMethod(args...)}</code> for a named object instance</li>
019: * <li>2. <code>${mypackage.MyClass[].myMethod(args...)}</code> to create a new instance of the class on each evaluation</li>
020: * <li>3. <code>${mypackage.MyClass.myMethod(args...)}</code> to invoke a static method</li>
021: * <li>4. <code>${myMethod[referenceName](args...)}</code> for a method contained with the invoking page</li>
022: * <li>5. <code>${this[componentName].componentMethod(args...)}</code> for a method contained within named component</li>
023: * <li>6. <code>${this.method(args...)}</code> for a method contained within the enclosing page, identical to 4 above</li>
024: * <li>7. <code>${project.method(args...)}</code> for a method contained within the project</li>
025: * <li>8. <code>${comp.method(args...)}</code> for a method contained within the component</li>
026: * <li>9. <code>${this}</code> for a reference to the page</li>
027: * <li>10. <code>${comp}</code> for a reference to the component</li>
028: * <li>11. <code>${value}</code> for a reference to the named argument value</li>
029: * <li>12. <code>${values}</code> for a reference to the named argument values</li>
030: * </ul>
031: * <p>where mypackage is the name of the Java package containing the class MyClass.
032: * The value of referenceName is a user defined value that identifies the instance
033: * of the class. The application instantiates an instance of the class when
034: * the expression is first encountered and thereafter maintains the instance with
035: * each subsequent call retrieving the same instance of the class.</p>
036: *
037: * <p> Copyright (c) Xoetrope Ltd., 2001-2008, This software is licensed under
038: * the GNU Public License (GPL), please see license.txt for more details. If
039: * you make commercial use of this software you must purchase a commercial
040: * license from Xoetrope.</p>
041: */
042: public class XGenericBuilderAttributeEvaluator extends
043: XDefaultAttributeEvaluator {
044: private PageSupport page;
045: private String sourceAttribute;
046: private Component sourceComp;
047: private XmlElement sourceNode;
048:
049: /**
050: * Create a new evaluator
051: * @param currentProject the current project
052: * @param project the current or owning project
053: */
054: public XGenericBuilderAttributeEvaluator(XProject project) {
055: super (project);
056: }
057:
058: /**
059: * Invoke the specified method
060: * @param attribValue the value of the attribute.
061: * @param childNode the source xml node
062: */
063: public Object evaluateAttribute(Component comp, String methodSpec,
064: String attribValue, XmlElement childNode) {
065: sourceComp = comp;
066: sourceAttribute = attribValue;
067: sourceNode = childNode;
068:
069: return super .evaluateAttribute(page, methodSpec);
070:
071: // Object methodValue = null;
072: // try {
073: // int expPos = methodSpec.indexOf( "${" );
074: // if ( expPos >= 0 ) {
075: // Class[] params;
076: // int endAttribName = methodSpec.indexOf( '(' );
077: // int endAttribArgs = XuiUtilities.indexOfMatchingEnding( methodSpec, '(', ')', endAttribName + 1 );
078: //
079: // String methodName = methodSpec.substring( expPos + 2, endAttribName );
080: // Object args[];
081: //
082: // // Check for an argumentless call
083: // if ( ( endAttribName + 1 ) == endAttribArgs ) {
084: // args = new Object[ 0 ];
085: // params = new Class[ 0 ];
086: // }
087: // else {
088: // String argValues = methodSpec.substring( endAttribName+1, endAttribArgs );
089: // // Count the number of commas
090: // int numArgs = 1 + XuiUtilities.count( argValues, ',', '(', ')' );
091: // args = new Object[ numArgs ];
092: // params = new Class[ numArgs ];
093: // XuiUtilities.getArguments( argValues, params, args, ',', '(', ')' );
094: // }
095: //
096: // // Override the argument values
097: // int pos = 0;
098: // for ( int i = 0; i < args.length; i++ ) {
099: // do {
100: // String argString = args[ i ].toString();
101: // if ( argString.equals( "${this}" )) {
102: // args[ i ] = this;
103: // break;
104: // }
105: // else if (( pos = argString.indexOf( "${values}" )) >= 0 ) {
106: // if ( pos == 0 )
107: // args[ i ] = attribValue.split( "," );
108: // else
109: // args[ i ] = argString.substring( 0, pos ) +
110: // attribValue +
111: // argString.substring( pos + 9 ).split( "," );
112: // }
113: // else if (( pos = argString.indexOf( "${value}" )) >= 0 ) {
114: // if ( pos == 0 )
115: // args[ i ] = attribValue;
116: // else
117: // args[ i ] = argString.substring( 0, pos ) +
118: // attribValue + argString.substring( pos + 8 );
119: // }
120: // else if ( argString.equals( "${comp}" )) {
121: // args[ i ] = comp;
122: // params[ i ] = Component.class;
123: // break;
124: // }
125: // else if ( argString.startsWith( "${" )) {
126: // // Check for other attributes of the node e.g. ${attribName}
127: // String attribName = argString.substring( 2, argString.lastIndexOf( '}' ) );
128: // String[] names = attribName.split( "," );
129: // String[] values = new String[ names.length ];
130: // // Do not use method calls - they are not attribute names
131: // for ( int j = 0; j < names.length; j++ ) {
132: // if ( names[ j ].indexOf( '(' ) < 0 )
133: // values[ j ] = childNode.getAttribute( names[ j ] );
134: // }
135: //
136: // if ( values != null )
137: // args[ i ] = values;
138: // else {
139: // args[ i ] = argString;
140: // break;
141: // }
142: // }
143: // else {
144: // args[ i ] = argString;
145: // break;
146: // }
147: // } while ( true );
148: // }
149: //
150: // // Find the class that implements the method
151: // Class clazz = null;
152: // Object classInstance = null;
153: // pos = -1;
154: // if (( pos = methodName.indexOf( "this." )) == 0 ) {
155: // classInstance = this;
156: // clazz = getClass();
157: // methodName = methodName.substring( pos + 5 );
158: // }
159: // else {
160: // pos = methodName.lastIndexOf( '.' );
161: // if ( pos > 0 ) {
162: // String className = methodName.substring( 0, pos );
163: // methodName = methodName.substring( pos + 1 );
164: //
165: // // Check for the class instance type
166: // className = className.substring( 0, pos );
167: // clazz = Class.forName( className.trim() );
168: // classInstance = clazz.newInstance();
169: //
170: // if ( clazz == null )
171: // clazz = classInstance.getClass();
172: // }
173: // else if ( page!= null ) {
174: // clazz = page.getClass();
175: // classInstance = page;
176: // }
177: // }
178: //
179: // // Find and invoke the method
180: // Method theMethod = clazz.getMethod( methodName, params );
181: // XMethodReference methodRef = new XMethodReference ( clazz, classInstance, theMethod, args );
182: // methodValue = methodRef.method.invoke( methodRef.instance, methodRef.args );
183: // }
184: // }
185: // catch ( Exception ex ) {
186: // if ( BuildProperties.DEBUG )
187: // DebugLogger.logWarning( "Unable to evaluate attribute with the method call(?): " + methodSpec );
188: // }
189: // return methodValue;
190: }
191:
192: /**
193: * Get the page that this evaluator is operating upon
194: * @return the page or null if none was set
195: */
196: public PageSupport getPage() {
197: return page;
198: }
199:
200: /**
201: * Set the page upon which this component operates
202: * @param p the page
203: */
204: public void setPage(PageSupport p) {
205: page = p;
206: }
207:
208: /**
209: * Lookup a reference
210: * @param reference a stripped reference e.g. values - which would have been
211: * specified as ${values}
212: * @return the reference object(s) or null
213: */
214: protected Object lookupReference(String reference) {
215: Object retValue = null;
216: int pos = 0;
217: if ((pos = reference.indexOf("values")) >= 0) {
218: if (pos == 0)
219: retValue = sourceAttribute.split(",");
220: else
221: retValue = reference.substring(0, pos)
222: + sourceAttribute
223: + reference.substring(pos + 6).split(",");
224: } else if ((pos = reference.indexOf("value")) >= 0) {
225: if (pos == 0)
226: retValue = sourceAttribute;
227: else
228: retValue = reference.substring(0, pos)
229: + sourceAttribute
230: + reference.substring(pos + 5);
231: } else if (reference.equals("comp")) {
232: retValue = sourceComp;
233: // params[ i ] = Component.class;
234: } else {
235: // Check for other attributes of the node e.g. ${attribName}
236: String[] names = reference.split(",");
237: String[] values = new String[names.length];
238: // Do not use method calls - they are not attribute names
239: for (int j = 0; j < names.length; j++) {
240: if (names[j].indexOf('(') < 0)
241: values[j] = sourceNode.getAttribute(names[j]);
242: }
243:
244: if (values != null)
245: retValue = values;
246: else {
247: retValue = reference;
248: }
249: }
250:
251: return retValue;
252: }
253: }
|