001: /*
002: * Copyright (C) 1999-2004 <A href="http://www-ist.massey.ac.nz/JBDietrich" target="_top">Jens Dietrich</a>
003: *
004: * This library is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License as published by the Free Software Foundation; either
007: * version 2 of the License, or (at your option) any later version.
008: *
009: * This library is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012: * Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public
015: * License along with this library; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
017: */
018:
019: package org.mandarax.kernel.meta;
020:
021: import java.io.IOException;
022: import java.io.ObjectInputStream;
023: import java.io.ObjectOutputStream;
024: import java.lang.reflect.Method;
025: import org.mandarax.kernel.*;
026:
027: /**
028: * An implementation of function similar to JFunction. The difference is that a DynaBeanFunction
029: * works only with methods with one parameter, and these parameter is a string. The value
030: * of this string is fixed (propertyName). This is to support "dynamic beans" that keep the state in
031: * a map or a similar structure (and does not use instance variables for this purpose).
032: * The get methods to retrieve the properties by name (e.g., get() in java.util.Map) can then be wrapped
033: * as functions using this class.
034: * @author <A href="http://www-ist.massey.ac.nz/JBDietrich" target="_top">Jens Dietrich</A>
035: * @version 3.4 <7 March 05>
036: * @since 2.2.1
037: */
038: public final class DynaBeanFunction extends JConstructor implements
039: Function {
040: // save as array for efficiency - see resolve
041: private String[] propertyNameArray = new String[1];
042:
043: /**
044: * Constructor.
045: * @param aMethod the method used
046: */
047: public DynaBeanFunction() {
048: super ();
049: }
050:
051: /**
052: * Constructor.
053: * @param aMethod the method used
054: * param propertyName the name of the property
055: */
056: public DynaBeanFunction(Method aMethod, String propertyName) {
057: super (aMethod);
058: setPropertyName(propertyName);
059: }
060:
061: /**
062: * Constructor.
063: * @param aMethod the method used
064: * @param propertyName the name of the property
065: * @param aName the name of the object
066: */
067: public DynaBeanFunction(Method aMethod, String propertyName,
068: String aName) {
069: super (aMethod, aName);
070: setPropertyName(propertyName);
071: }
072:
073: /**
074: * Indicates whether this function equals the object.
075: * @param obj the object to compare this object with
076: * @return true if the objects are equal, false otherwise
077: */
078: public boolean equals(Object obj) {
079: if (obj instanceof DynaBeanFunction) {
080: DynaBeanFunction f = (DynaBeanFunction) obj;
081: Class[] c1 = f.getStructure();
082: Class[] c2 = getStructure();
083: boolean result = f.getName().equals(getName());
084: result = result
085: && f.propertyNameArray[0]
086: .equals(propertyNameArray[0]);
087: result = result && (c1.length == c2.length);
088: if (!result)
089: return false;
090: for (int i = 0; i < c1.length; i++) {
091: if (c1[i] != c2[i])
092: return false;
093: }
094: return true;
095: }
096:
097: return false;
098: }
099:
100: /**
101: * Get the return type.
102: * @return the return type
103: */
104: public Class getReturnType() {
105: return convertType(method.getReturnType());
106: }
107:
108: /**
109: * Read the object from an object input stream.
110: * @param in an input stream
111: */
112: private void readObject(ObjectInputStream in) throws IOException,
113: ClassNotFoundException {
114: in.defaultReadObject();
115: String methodName = (String) in.readObject();
116: Class declaringClass = (Class) in.readObject();
117: Class[] parTypes = (Class[]) in.readObject();
118:
119: try {
120: Method m = declaringClass.getMethod(methodName, parTypes);
121: method = m;
122: } catch (NoSuchMethodException x) {
123: throw new IOException("Cannot find method " + name);
124: }
125: }
126:
127: /**
128: * Write the object to an object output stream.
129: * @param out an output stream
130: */
131: private void writeObject(ObjectOutputStream out)
132: throws IOException, ClassNotFoundException {
133: out.defaultWriteObject();
134: out.writeObject(method.getName());
135: out.writeObject(method.getDeclaringClass());
136: out.writeObject(method.getParameterTypes());
137: }
138:
139: /**
140: * Returns the propertyName.
141: * @return String
142: */
143: public String getPropertyName() {
144: return propertyNameArray[0];
145: }
146:
147: /**
148: * Sets the propertyName.
149: * @param propertyName The propertyName to set
150: */
151: public void setPropertyName(String propertyName) {
152: propertyNameArray[0] = propertyName;
153: }
154:
155: /**
156: * Perform the function or predicate using an array of terms as parameters.
157: * @return the result of the perform
158: * @param parameter an array of terms
159: * @param session a session object
160: * @throws java.lang.UnsupportedOperationException
161: * @throws java.lang.IllegalArgumentException
162: */
163: public Object perform(Term[] parameter, Session session)
164: throws IllegalArgumentException,
165: UnsupportedOperationException {
166: Object target = parameter[0].resolve(session);
167: try {
168: return method.invoke(target, propertyNameArray);
169: } catch (Throwable x) {
170: throw new UnsupportedOperationException(
171: "Perform failed for DynaBeanFunction with method "
172: + method + " and property "
173: + propertyNameArray[0]);
174: }
175: }
176:
177: /**
178: * Get the structure, i.e. the parameter types.
179: * The first element is the declaring class of the method!
180: * @return the structure of this object
181: */
182: public java.lang.Class[] getStructure() {
183: if (structure == null) {
184: structure = new Class[1];
185: structure[0] = method.getDeclaringClass();
186: }
187:
188: return structure;
189: }
190:
191: /**
192: * Set the method.
193: * @param m a method
194: */
195: public void setMethod(Method m) {
196: if (m != null && m.getParameterTypes().length != 1)
197: throw new IllegalArgumentException(
198: "DynaBeanFunction can wrap only methods with one parameter");
199: if (m != null && m.getParameterTypes()[0] != String.class)
200: throw new IllegalArgumentException(
201: "DynaBeanFunction can wrap only methods with one parameter of the type String");
202: super.setMethod(m);
203: }
204: }
|