001: /*
002: * ====================================================================
003: * JAFFA - Java Application Framework For All
004: *
005: * Copyright (C) 2002 JAFFA Development Group
006: *
007: * This library is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU Lesser General Public
009: * License as published by the Free Software Foundation; either
010: * version 2.1 of the License, or (at your option) any later version.
011: *
012: * This library is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this library; if not, write to the Free Software
019: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020: *
021: * Redistribution and use of this software and associated documentation ("Software"),
022: * with or without modification, are permitted provided that the following conditions are met:
023: * 1. Redistributions of source code must retain copyright statements and notices.
024: * Redistributions must also contain a copy of this document.
025: * 2. Redistributions in binary form must reproduce the above copyright notice,
026: * this list of conditions and the following disclaimer in the documentation
027: * and/or other materials provided with the distribution.
028: * 3. The name "JAFFA" must not be used to endorse or promote products derived from
029: * this Software without prior written permission. For written permission,
030: * please contact mail to: jaffagroup@yahoo.com.
031: * 4. Products derived from this Software may not be called "JAFFA" nor may "JAFFA"
032: * appear in their names without prior written permission.
033: * 5. Due credit should be given to the JAFFA Project (http://jaffa.sourceforge.net).
034: *
035: * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
036: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
037: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
038: * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
039: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
040: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
041: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
042: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
043: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
044: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
045: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
046: * SUCH DAMAGE.
047: * ====================================================================
048: */
049:
050: package org.jaffa.persistence.util;
051:
052: import java.beans.IntrospectionException;
053: import java.lang.reflect.InvocationTargetException;
054: import java.lang.reflect.Method;
055: import java.lang.reflect.Modifier;
056: import java.util.*;
057: import org.apache.log4j.Logger;
058: import org.jaffa.datatypes.exceptions.MandatoryFieldException;
059: import org.jaffa.exceptions.ApplicationExceptions;
060: import org.jaffa.exceptions.FrameworkException;
061: import org.jaffa.metadata.FieldMetaData;
062: import org.jaffa.persistence.IPersistent;
063: import org.jaffa.persistence.UOW;
064: import org.jaffa.persistence.exceptions.DomainObjectValidationException;
065: import org.jaffa.util.BeanHelper;
066: import org.jaffa.util.StringHelper;
067:
068: /** Helper methods for persistent objects.
069: */
070: public class PersistentHelper {
071:
072: private static final Logger log = Logger
073: .getLogger(PersistentHelper.class);
074: private static final String META_CLASS_SUFFIX = "Meta";
075:
076: /** This returns the corresponding meta class for the input persistent class.
077: * It assumes the name of the meta class by appending 'Meta' to the input persistent class.
078: * @param persistentClassName The persistent class.
079: * @return the meta class.
080: * @throws ClassNotFoundException if the Meta class for the input persistent class is not found.
081: */
082: public static Class getMetaClass(String persistentClassName)
083: throws ClassNotFoundException {
084: return Class.forName(persistentClassName + META_CLASS_SUFFIX);
085: }
086:
087: /** This returns an array of meta information for all the key fields of the persistent class.
088: * @param persistentClassName The name of the persistent class.
089: * @throws ClassNotFoundException if the Meta class for the input persistent class is not found.
090: * @throws NoSuchMethodException if the Meta class does not have the 'public static FieldMetaData[] getKeyFields()' method.
091: * @throws IllegalAccessException if the 'public static FieldMetaData[] getKeyFields()' method of the Meta class enforces Java language access control and the underlying method is inaccessible.
092: * @throws InvocationTargetException if the 'public static FieldMetaData[] getKeyFields()' method of the Meta class throws an exception.
093: */
094: public static FieldMetaData[] getKeyFields(
095: String persistentClassName) throws ClassNotFoundException,
096: NoSuchMethodException, IllegalAccessException,
097: InvocationTargetException {
098: // Get the meta class
099: Class metaClass = getMetaClass(persistentClassName);
100:
101: // Get a handle on the method for retrieving the FieldMetaData from the meta class
102: Method m = metaClass.getMethod("getKeyFields", null);
103:
104: // Ensure that the method is static and that the method returns FieldMetaData[]
105: if (Modifier.isStatic(m.getModifiers())
106: && m.getReturnType() == FieldMetaData[].class) {
107: // Now invoke the method to get the FieldMetaData objects
108: return (FieldMetaData[]) m.invoke(null, null);
109: } else {
110: String str = "The getKeyFields() method in the meta class for the persistent class "
111: + persistentClassName
112: + " should be static and return an array of the FieldMetaData instances";
113: if (log.isDebugEnabled())
114: log.debug(str);
115: throw new NoSuchMethodException(str);
116: }
117: }
118:
119: /** This returns an array of meta information for all the mandatory fields of the persistent class.
120: * @param persistentClassName The name of the persistent class.
121: * @throws ClassNotFoundException if the Meta class for the input persistent class is not found.
122: * @throws NoSuchMethodException if the Meta class does not have the 'public static FieldMetaData[] getMandatoryFields()' method.
123: * @throws IllegalAccessException if the 'public static FieldMetaData[] getMandatoryFields()' method of the Meta class enforces Java language access control and the underlying method is inaccessible.
124: * @throws InvocationTargetException if the 'public static FieldMetaData[] getMandatoryFields()' method of the Meta class throws an exception.
125: */
126: public static FieldMetaData[] getMandatoryFields(
127: String persistentClassName) throws ClassNotFoundException,
128: NoSuchMethodException, IllegalAccessException,
129: InvocationTargetException {
130: // Get the meta class
131: Class metaClass = getMetaClass(persistentClassName);
132:
133: // Get a handle on the method for retrieving the FieldMetaData from the meta class
134: Method m = metaClass.getMethod("getMandatoryFields", null);
135:
136: // Ensure that the method is static and that the method returns FieldMetaData[]
137: if (Modifier.isStatic(m.getModifiers())
138: && m.getReturnType() == FieldMetaData[].class) {
139: // Now invoke the method to get the FieldMetaData objects
140: return (FieldMetaData[]) m.invoke(null, null);
141: } else {
142: String str = "The getMandatoryFields() method in the meta class for the persistent class "
143: + persistentClassName
144: + " should be static and return an array of the FieldMetaData instances";
145: if (log.isDebugEnabled())
146: log.debug(str);
147: throw new NoSuchMethodException(str);
148: }
149: }
150:
151: /** This returns an array of meta information for all the fields of the persistent class.
152: * @param persistentClassName The name of the persistent class.
153: * @throws ClassNotFoundException if the Meta class for the input persistent class is not found.
154: * @throws NoSuchMethodException if the Meta class does not have the 'public static FieldMetaData[] getFieldMetaData()' method.
155: * @throws IllegalAccessException if the 'public static FieldMetaData[] getFieldMetaData()' method of the Meta class enforces Java language access control and the underlying method is inaccessible.
156: * @throws InvocationTargetException if the 'public static FieldMetaData[] getFieldMetaData()' method of the Meta class throws an exception.
157: */
158: public static FieldMetaData[] getFieldMetaData(
159: String persistentClassName) throws ClassNotFoundException,
160: NoSuchMethodException, IllegalAccessException,
161: InvocationTargetException {
162: // Get the meta class
163: Class metaClass = getMetaClass(persistentClassName);
164:
165: // Get a handle on the method for retrieving the FieldMetaData from the meta class
166: Method m = metaClass.getMethod("getFieldMetaData", null);
167:
168: // Ensure that the method is static and that the method returns FieldMetaData[]
169: if (Modifier.isStatic(m.getModifiers())
170: && m.getReturnType() == FieldMetaData[].class) {
171: // Now invoke the method to get the FieldMetaData objects
172: return (FieldMetaData[]) m.invoke(null, null);
173: } else {
174: String str = "The getFieldMetaData() method in the meta class for the persistent class "
175: + persistentClassName
176: + " should be static and return an array of the FieldMetaData instances";
177: if (log.isDebugEnabled())
178: log.debug(str);
179: throw new NoSuchMethodException(str);
180: }
181: }
182:
183: /** Returns the FieldMetaData object from the meta class for the input persistent class for the input field.
184: * @param persistentClassName The name of the persistent class.
185: * @param fieldName the field name.
186: * @throws ClassNotFoundException if the Meta class for the input persistent class is not found.
187: * @throws NoSuchMethodException if the Meta class does not have the 'public static FieldMetaData[] getFieldMetaData(String fieldName)' method.
188: * @throws IllegalAccessException if the 'public static FieldMetaData[] getFieldMetaData(String fieldName)' method of the Meta class enforces Java language access control and the underlying method is inaccessible.
189: * @throws InvocationTargetException if the 'public static FieldMetaData[] getFieldMetaData(String fieldName)' method of the Meta class throws an exception.
190: */
191: public static FieldMetaData getFieldMetaData(
192: String persistentClassName, String fieldName)
193: throws ClassNotFoundException, NoSuchMethodException,
194: IllegalAccessException, InvocationTargetException {
195: // Get the meta class
196: Class metaClass = getMetaClass(persistentClassName);
197:
198: // Get a handle on the method for retrieving the FieldMetaData from the meta class
199: Method m = metaClass.getMethod("getFieldMetaData",
200: new Class[] { String.class });
201:
202: // Ensure that the method is static and that the method returns FieldMetaData
203: if (Modifier.isStatic(m.getModifiers())
204: && m.getReturnType() == FieldMetaData.class) {
205: // Now invoke the method to get the FieldMetaData object
206: return (FieldMetaData) m.invoke(null,
207: new Object[] { fieldName });
208: } else {
209: String str = "The getFieldMetaData() method in the meta class for the persistent class "
210: + persistentClassName
211: + " should be static and return an instance of the FieldMetaData class";
212: if (log.isDebugEnabled())
213: log.debug(str);
214: throw new NoSuchMethodException(str);
215: }
216: }
217:
218: /** This returns the labelToken for a persistent class. It will look for the persistent meta class and invoke its getLabelToken method to determine the value to return.
219: * @param persistentClassName The persistent class.
220: * @throws ClassNotFoundException If the persistent meta class is not found.
221: * @throws NoSuchMethodException If there is no 'public static String getLabelToken()' method in the persistent meta class.
222: * @throws IllegalAccessException if the method is inaccessible.
223: * @throws InvocationTargetException if the method throws an exception.
224: * @return the labelToken for a persistent class.
225: */
226: public static String getLabelToken(String persistentClassName)
227: throws ClassNotFoundException, NoSuchMethodException,
228: IllegalAccessException, InvocationTargetException {
229: // Get the meta class
230: Class metaClass = getMetaClass(persistentClassName);
231:
232: // Get a handle on the method for retrieving the labelToken from the meta class
233: Method m = metaClass.getMethod("getLabelToken", null);
234:
235: // Ensure that the method is static and that the method returns String
236: if (Modifier.isStatic(m.getModifiers())
237: && m.getReturnType() == String.class) {
238: // Now invoke the method to return the labelToken
239: return (String) m.invoke(null, null);
240: } else {
241: String str = "The getLabelToken() method in the meta class for the persistent class "
242: + persistentClassName
243: + " should be static and return a String object";
244: if (log.isDebugEnabled())
245: log.debug(str);
246: throw new NoSuchMethodException(str);
247: }
248: }
249:
250: /** This returns the labelToken for a field in a persistent class. It will look for the persistent meta class and invoke its getFieldMetaData method to determine the appropriate FieldMetaData object. It will finally return the labelToken as specified in the FieldMetaData object.
251: * @param persistentClassName The persistent class.
252: * @param fieldName The field name.
253: * @throws ClassNotFoundException If the persistent meta class is not found.
254: * @throws NoSuchMethodException If there is no 'public static FieldMetaData getFieldMetaData(String fieldName)' method in the persistent meta class.
255: * @throws IllegalAccessException if the method is inaccessible.
256: * @throws InvocationTargetException if the method throws an exception.
257: * @return the labelToken for a field in a domain class.
258: */
259: public static String getLabelToken(String persistentClassName,
260: String fieldName) throws ClassNotFoundException,
261: NoSuchMethodException, IllegalAccessException,
262: InvocationTargetException {
263: FieldMetaData fieldMetaData = getFieldMetaData(
264: persistentClassName, fieldName);
265: return fieldMetaData == null ? null : fieldMetaData
266: .getLabelToken();
267: }
268:
269: /** This will check all the mandatory fields of the persistent object.
270: * It utilises the corresponding Meta class for determining the mandatory fields.
271: * @param object The persistent object.
272: * @throws ApplicationExceptions Will contain a collection of MandatoryFieldExceptions for the all the mandatory fields which do not have values.
273: * @throws FrameworkException If any framework error occurs.
274: */
275: public static void checkMandatoryFields(IPersistent object)
276: throws ApplicationExceptions, FrameworkException {
277: try {
278: FieldMetaData[] fields = getMandatoryFields(object
279: .getClass().getName());
280: if (fields != null && fields.length > 0) {
281: ApplicationExceptions appExps = new ApplicationExceptions();
282: for (int i = 0; i < fields.length; i++) {
283: FieldMetaData fieldMetaData = fields[i];
284: Object fieldValue = BeanHelper.getField(object,
285: fieldMetaData.getName());
286: if (fieldValue == null
287: || (fieldValue instanceof String && ((String) fieldValue)
288: .length() == 0)) {
289: if (log.isDebugEnabled())
290: log
291: .debug("Mandatory validation failed for the field "
292: + fieldMetaData.getName());
293: appExps.add(new MandatoryFieldException(
294: fieldMetaData.getLabelToken()));
295: }
296: }
297: if (appExps.size() > 0)
298: throw appExps;
299: }
300: } catch (ClassNotFoundException e) {
301: String str = "Exception thrown while validating the domain object "
302: + object;
303: log.error(str, e);
304: throw new DomainObjectValidationException(null, e);
305: } catch (NoSuchMethodException e) {
306: String str = "Exception thrown while validating the domain object "
307: + object;
308: log.error(str, e);
309: throw new DomainObjectValidationException(null, e);
310: } catch (IllegalAccessException e) {
311: String str = "Exception thrown while validating the domain object "
312: + object;
313: log.error(str, e);
314: throw new DomainObjectValidationException(null, e);
315: } catch (InvocationTargetException e) {
316: String str = "Exception thrown while validating the domain object "
317: + object;
318: log.error(str, e);
319: throw new DomainObjectValidationException(null, e);
320: }
321: }
322:
323: /** This will query the database to see if the primary-key of the input persistent object is already in use.
324: * It'll invoke the exists() method of the persistent class perform the check.
325: * Note: This method will determine the key fields by looking up the getKeyFields method in the corresponding meta class for the input persistent object.
326: * @param uow The UOW object. If null, then a UOW will be created implicitly by the exists() method to load the persistent object.
327: * @param object The persistent object.
328: * @throws ClassNotFoundException if the Meta class for the input persistent class is not found.
329: * @throws NoSuchMethodException if the Meta class does not have the 'public static FieldMetaData[] getKeyFields()' method.
330: * @throws IllegalAccessException if the 'public static FieldMetaData[] getKeyFields()' method of the Meta class enforces Java language access control and the underlying method is inaccessible.
331: * @throws InvocationTargetException if the 'public static FieldMetaData[] getKeyFields()' method of the Meta class throws an exception.
332: * @throws IllegalArgumentException if the input persistent class does not have any key-fields
333: * @throws FrameworkException if the exists() method of the persistent class fails.
334: * @return true if the primary-key is already in use. A false will be returned if the key is not in use or if any of the key fields is null.
335: */
336: public static boolean exists(UOW uow, IPersistent object)
337: throws ClassNotFoundException, NoSuchMethodException,
338: IllegalAccessException, InvocationTargetException,
339: IllegalArgumentException, FrameworkException {
340: Class persistentClass = object.getClass();
341:
342: // Create an argument List to be passed to the exists() method of the persistent class
343: List arguments = new LinkedList();
344: arguments.add(uow);
345:
346: FieldMetaData[] keyFields = getKeyFields(persistentClass
347: .getName());
348: if (keyFields != null && keyFields.length > 0) {
349: for (int i = 0; i < keyFields.length; i++) {
350: String keyFieldName = keyFields[i].getName();
351: Object keyFieldValue = BeanHelper.getField(object,
352: keyFieldName);
353: if (keyFieldValue != null) {
354: arguments.add(keyFieldValue);
355: } else {
356: // Return a false if any of the key-fields is null
357: return false;
358: }
359: }
360:
361: // Get a handle on the exists method of the persistent class
362: Class[] argumentsClassArray = new Class[arguments.size()];
363: argumentsClassArray[0] = UOW.class;
364: for (int i = 1; i < arguments.size(); i++)
365: argumentsClassArray[i] = arguments.get(i).getClass();
366: Method m = persistentClass.getMethod("exists",
367: argumentsClassArray);
368: try {
369: Boolean result = (Boolean) m.invoke(null, arguments
370: .toArray());
371: return result != null ? result.booleanValue() : false;
372: } catch (InvocationTargetException e) {
373: if (e.getCause() != null
374: && e.getCause() instanceof FrameworkException)
375: throw (FrameworkException) e.getCause();
376: else
377: throw e;
378: }
379: } else {
380: String str = "Exists check cannot be performed. The input persistent object does not have any key fields defined in its meta class: "
381: + object.getClass().getName();
382: log.error(str);
383: throw new IllegalArgumentException(str);
384: }
385: }
386:
387: /** This will generate a unique string for the input persistent object, based on the persistent class name and its key values.
388: * The format of the generated key will be: package.classname;key1value;key2value;key3value
389: * For eg:
390: * For a Person persistent object having a primary key PersonId, the serialized key could be "org.example.Person;P0021"
391: * For an EventEntry persistent object having a composite primary key of EventId and PersonId primary, the serialized key could be "org.example.EventEntry;E01;P0021"
392: * The back-slash '\' will be the escape character.
393: * Hence, if the key-value contains a '\', then it'll be replaced by '\\'
394: * If the key value contains a semi-colon, then it'll be replaced by '\;'
395: *
396: * Note: This method will determine the key fields by looking up the getKeyFields method in the corresponding meta class for the input persistent object.
397: *
398: * @param object The persistent object.
399: * @throws ClassNotFoundException if the Meta class for the input persistent class is not found.
400: * @throws NoSuchMethodException if the Meta class does not have the 'public static FieldMetaData[] getKeyFields()' method.
401: * @throws IllegalAccessException if the 'public static FieldMetaData[] getKeyFields()' method of the Meta class enforces Java language access control and the underlying method is inaccessible.
402: * @throws InvocationTargetException if the 'public static FieldMetaData[] getKeyFields()' method of the Meta class throws an exception.
403: * @throws IllegalArgumentException if the input persistent class does not have any key-fields or if any of the key-fields is null.
404: * @return a unique String for identifying the persistent object.
405: */
406: public static String generateSerializedKey(IPersistent object)
407: throws ClassNotFoundException, NoSuchMethodException,
408: IllegalAccessException, InvocationTargetException,
409: IllegalArgumentException {
410: StringBuffer buf = new StringBuffer(object.getClass().getName());
411: FieldMetaData[] keyFields = getKeyFields(object.getClass()
412: .getName());
413: if (keyFields != null && keyFields.length > 0) {
414: for (int i = 0; i < keyFields.length; i++) {
415: String keyFieldName = keyFields[i].getName();
416: Object keyFieldValue = BeanHelper.getField(object,
417: keyFieldName);
418: if (keyFieldValue != null) {
419: buf.append(';').append(
420: quoteSerializedKeyValue(keyFieldValue
421: .toString()));
422: } else {
423: String str = "SerializedKey cannot be generated. The input persistent object has a null value for its key-field "
424: + object + ':' + keyFieldName;
425: log.error(str);
426: throw new IllegalArgumentException(str);
427: }
428: }
429: } else {
430: String str = "SerializedKey cannot be generated. The input persistent object does not have any key fields defined in its meta class: "
431: + object.getClass().getName();
432: log.error(str);
433: throw new IllegalArgumentException(str);
434: }
435: return buf.toString();
436: }
437:
438: /** This will load the persistent object from the input serialized key, by invoking the findByPK() method of the persistent class encoded in the input String.
439: * @param uow The UOW object. If null, then a UOW will be created implicitly by the findByPK method to load the persistent object.
440: * @param serializedKey The serialized key which will have the right information to load the persistent object.
441: * @throws ClassNotFoundException if the Persistent class or its Meta class are not found.
442: * @throws NoSuchMethodException if the Persistent class does not have the 'public static IPersistent findByPK(UOW uow, KeyField1...)' method or the Meta class does not have the 'public static FieldMetaData[] getKeyFields()' method.
443: * @throws IllegalAccessException if the 'public static FieldMetaData[] getKeyFields()' method of the Meta class enforces Java language access control and the underlying method is inaccessible.
444: * @throws InvocationTargetException if the 'public static FieldMetaData[] getKeyFields()' method of the Meta class throws an exception.
445: * @throws IllegalArgumentException if the input persistent class does not have any key-fields or if any of the key-fields is null.
446: * @throws IntrospectionException if an exception occurs during introspection.
447: * @throws FrameworkException if the findByPK() method of the persistent class fails.
448: * @return a Persistent object.
449: */
450: public static IPersistent loadFromSerializedKey(UOW uow,
451: String serializedKey) throws ClassNotFoundException,
452: NoSuchMethodException, IllegalAccessException,
453: InvocationTargetException, IllegalArgumentException,
454: IntrospectionException, FrameworkException {
455: // Determine the persistent class name
456: int beginIndex = 0;
457: int endIndex = serializedKey.indexOf(';');
458: if (endIndex <= 0) {
459: String str = "Persistent object cannot be loaded. The input serialized key does not have the Persistent class name "
460: + serializedKey;
461: log.error(str);
462: throw new IllegalArgumentException(str);
463: }
464: String persistentClassName = serializedKey.substring(
465: beginIndex, endIndex);
466: if (log.isDebugEnabled())
467: log.debug("Found persistent class " + persistentClassName);
468: Class persistentClass = Class.forName(persistentClassName);
469:
470: // Create an argument List to be passed to the findByPK method of the persistent class
471: List arguments = new LinkedList();
472: arguments.add(uow);
473:
474: // Get the key fields for the persistent class from its meta class
475: FieldMetaData[] keyFields = getKeyFields(persistentClassName);
476: if (keyFields != null && keyFields.length > 0) {
477: for (int i = 0; i < keyFields.length; i++) {
478: // Determine the value for a keyfield
479: String keyFieldName = keyFields[i].getName();
480: String keyFieldValue = null;
481: beginIndex = endIndex + 1;
482: endIndex = beginIndex + 1;
483: if (beginIndex < serializedKey.length()) {
484: if (endIndex >= serializedKey.length()) {
485: // We are currently on the last character of the input serializedkey
486: keyFieldValue = serializedKey
487: .substring(beginIndex);
488: } else {
489: // Search for the next ';', making sure that its not quoted
490: while (true) {
491: endIndex = serializedKey.indexOf(';',
492: endIndex);
493: if (endIndex < 0) {
494: // No more ';'
495: keyFieldValue = serializedKey
496: .substring(beginIndex);
497: break;
498: } else if (serializedKey
499: .charAt(endIndex - 1) != '\\') {
500: // The ';' is not quoted
501: keyFieldValue = serializedKey
502: .substring(beginIndex, endIndex);
503: break;
504: } else {
505: // We've reached a quoted ';'. Go past it
506: ++endIndex;
507: if (endIndex >= serializedKey.length()) {
508: // No more search possible
509: keyFieldValue = serializedKey
510: .substring(beginIndex);
511: break;
512: }
513: }
514: }
515: }
516: }
517: // Unquote the keyvalue
518: keyFieldValue = unquoteSerializedKeyValue(keyFieldValue);
519:
520: // Throw an exception if the input serializedkey does not have a value for the keyfield
521: if (keyFieldValue == null
522: || keyFieldValue.length() == 0) {
523: String str = "Persistent object cannot be loaded. The input serialized key does not have a value for the key field "
524: + keyFieldName;
525: log.error(str);
526: throw new IllegalArgumentException(str);
527: }
528:
529: if (log.isDebugEnabled())
530: log.debug("Found " + keyFieldName + '='
531: + keyFieldValue);
532:
533: // Convert the keyFieldValue to the appropriate datatype
534: Object convertedKeyFieldValue = BeanHelper
535: .convertDataType(persistentClass, keyFieldName,
536: keyFieldValue);
537: if (convertedKeyFieldValue == null) {
538: String str = "Persistent object cannot be loaded. The keyField "
539: + keyFieldName
540: + " having the value "
541: + keyFieldValue
542: + " could not be converted to the appropriate datatype";
543: log.error(str);
544: throw new IllegalArgumentException(str);
545: }
546:
547: arguments.add(convertedKeyFieldValue);
548: }
549:
550: // Get a handle on the findByPK method of the persistent class
551: Class[] argumentsClassArray = new Class[arguments.size()];
552: argumentsClassArray[0] = UOW.class;
553: for (int i = 1; i < arguments.size(); i++)
554: argumentsClassArray[i] = arguments.get(i).getClass();
555: Method m = persistentClass.getMethod("findByPK",
556: argumentsClassArray);
557: try {
558: return (IPersistent) m
559: .invoke(null, arguments.toArray());
560: } catch (InvocationTargetException e) {
561: if (e.getCause() != null
562: && e.getCause() instanceof FrameworkException)
563: throw (FrameworkException) e.getCause();
564: else
565: throw e;
566: }
567: } else {
568: String str = "Persistent object cannot be loaded. The persistent class specified in the input serialzedKey does not have any key fields defined in its meta class: "
569: + persistentClassName;
570: log.error(str);
571: throw new IllegalArgumentException(str);
572: }
573: }
574:
575: /** This will quote the semi-colon characters in the input string.
576: * The back-slash '\' will be the escape character.
577: * Hence, if the key-value contains a '\', then it'll be replaced by '\\'
578: * If the key value contains a semi-colon, then it'll be replaced by '\;'
579: */
580: private static String quoteSerializedKeyValue(String input) {
581: // replace '\' with '\\' and then replace ';' with '\;'
582: return StringHelper.replace(StringHelper.replace(input, "\\",
583: "\\\\"), ";", "\\;");
584: }
585:
586: /** This will unquote the semi-colon characters in the input string.
587: * The back-slash '\' will be the escape character.
588: * Hence, if the key-value contains a '\;', then it'll be replaced by ';'
589: * If the key value contains a '\\', then it'll be replaced by '\'
590: */
591: private static String unquoteSerializedKeyValue(String input) {
592: // replace '\;' with ';' and then replace '\\' with '\'
593: return StringHelper.replace(StringHelper.replace(input, "\\;",
594: ";"), "\\\\", "\\");
595: }
596:
597: }
|