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: package org.mandarax.kernel.meta;
019:
020: import java.lang.reflect.Method;
021: import org.mandarax.kernel.*;
022:
023: /**
024: * Abstract super class for JFunction and JPredicate.
025: * <br>
026: * In version 3.2, session support has been added. The last parameter (found in the wrapoped method)
027: * is treated separately if its type is Session (or a subclass of session). Then this parameter is used
028: * to pass a session reference at query time to the function or predicate!
029: * @see org.mandarax.kernel.Session
030: * @author <A href="http://www-ist.massey.ac.nz/JBDietrich" target="_top">Jens Dietrich</A>
031: * @version 3.4 <7 March 05>
032: * @since 1.0
033: */
034: public abstract class JConstructor extends org.mandarax.kernel.LObject
035: implements org.mandarax.kernel.Constructor {
036:
037: protected transient Method method = null;
038: protected Class[] structure = null;
039: protected String name = null;
040: protected boolean isSessionParameterSupported = false;
041:
042: /**
043: * Default constructor.
044: */
045: JConstructor() {
046: super ();
047: }
048:
049: /**
050: * Constructor.
051: * @param aMethod the method used
052: */
053: public JConstructor(java.lang.reflect.Method aMethod) {
054: super ();
055: setMethod(aMethod);
056: }
057:
058: /**
059: * Constructor.
060: * @param aMethod the method used
061: * @param aString the name of the object
062: */
063: public JConstructor(java.lang.reflect.Method aMethod, String aName) {
064: super ();
065: setMethod(aMethod);
066: setName(aName);
067: }
068:
069: /**
070: * Convert a type. This is used to convert
071: * primitive types to their respective wrapper types.
072: * @return the wrapper class
073: * @param aType the primitive type
074: */
075: protected Class convertType(Class aType) {
076: if (aType.isPrimitive()) {
077: if (aType == Integer.TYPE) {
078: return Integer.class;
079: }
080: if (aType == Double.TYPE) {
081: return Double.class;
082: }
083: if (aType == Float.TYPE) {
084: return Float.class;
085: }
086: if (aType == Byte.TYPE) {
087: return Byte.class;
088: }
089: if (aType == Long.TYPE) {
090: return Long.class;
091: }
092: if (aType == Short.TYPE) {
093: return Short.class;
094: }
095: if (aType == Boolean.TYPE) {
096: return Boolean.class;
097: }
098: }
099:
100: return aType;
101: }
102:
103: /**
104: * Get the method.
105: * @return the wrapped method
106: */
107: public Method getMethod() {
108: return method;
109: }
110:
111: /**
112: * Set the method.
113: * @param m a method
114: */
115: public void setMethod(Method m) {
116: method = m;
117: // force initialization of structure
118: structure = null;
119: }
120:
121: /**
122: * Get the name.
123: * @return the name
124: */
125: public String getName() {
126: return (name == null) ? ((method == null) ? "?" : method
127: .getName()) : name;
128: }
129:
130: /**
131: * Set the name.
132: * @param n a name
133: */
134: public void setName(String n) {
135: name = n;
136: }
137:
138: /**
139: * Get the structure, i.e. the parameter types.
140: * The first element is the declaring class of the method!
141: * Note that the last parameter is treated separately if its type
142: * is Session (or a subclass of session). Then this parameter is used
143: * to pass a session reference at query time to the function or predicate!
144: * @see org.mandarax.kernel.Session
145: * @return the structure of this object
146: */
147: public java.lang.Class[] getStructure() {
148: if (structure == null) {
149: Class[] p = method.getParameterTypes();
150: isSessionParameterSupported = p != null && p.length > 0
151: && Session.class.isAssignableFrom(p[p.length - 1]);
152: int size = isSessionParameterSupported ? p.length
153: : p.length + 1;
154: structure = new Class[size];
155: structure[0] = method.getDeclaringClass();
156: for (int i = 1; i < size; i++) {
157: structure[i] = convertType(p[i - 1]);
158: }
159: }
160: return structure;
161: }
162:
163: /**
164: * Indicates whether a session parameter is supported.
165: * This is the case iff the last parameter type is "Session".
166: * @see org.mandarax.kernel.Session
167: * @return a boolean
168: */
169: public boolean isSessionParameterSupported() {
170: return isSessionParameterSupported;
171: }
172:
173: /**
174: * Get the hash code.
175: * @return the hash value
176: */
177: public int hashCode() {
178: return getName().hashCode();
179: }
180:
181: /**
182: * Perform the function or predicate using an array of terms as parameters.
183: * @return the result of the perform
184: * @param parameter an array of terms
185: * @param session a session object
186: * @throws java.lang.UnsupportedOperationException
187: * @throws java.lang.IllegalArgumentException
188: */
189: public Object perform(Term[] parameter, Session session)
190: throws IllegalArgumentException,
191: UnsupportedOperationException {
192: Object target = null;
193: int paramSize = isSessionParameterSupported ? parameter.length
194: : parameter.length - 1;
195: Object[] objects = new Object[paramSize];
196: Term t;
197:
198: for (int i = 0; i < parameter.length; i++) {
199: t = parameter[i];
200: if (t != null) {
201: if (i == 0) {
202: target = t.resolve(session);
203: } else {
204: objects[i - 1] = t.resolve(session);
205: }
206: } else {
207: throw new IllegalArgumentException();
208: }
209: }
210:
211: // if the session parameter is supported, pass session
212: if (isSessionParameterSupported)
213: objects[paramSize - 1] = session;
214:
215: try {
216: return method.invoke(target, objects);
217: } catch (Throwable x) {
218: throw new UnsupportedOperationException(
219: "Perform failed for " + this + " with method "
220: + method);
221: }
222: }
223:
224: /**
225: * Indicates whether the object (usually a term or a clause set) can be performed
226: * using the java semantics.
227: * @return true
228: */
229: public boolean isExecutable() {
230: return true;
231: }
232:
233: /**
234: * Get the string representation of the object.
235: * @return the string representation of this object
236: */
237: public String toString() {
238: return getName();
239: }
240: }
|