Source Code Cross Referenced for ObjectUtils.java in  » ERP-CRM-Financial » Kuali-Financial-System » org » kuali » core » util » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » ERP CRM Financial » Kuali Financial System » org.kuali.core.util 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright 2005-2007 The Kuali Foundation.
0003:         * 
0004:         * Licensed under the Educational Community License, Version 1.0 (the "License");
0005:         * you may not use this file except in compliance with the License.
0006:         * You may obtain a copy of the License at
0007:         * 
0008:         * http://www.opensource.org/licenses/ecl1.php
0009:         * 
0010:         * Unless required by applicable law or agreed to in writing, software
0011:         * distributed under the License is distributed on an "AS IS" BASIS,
0012:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013:         * See the License for the specific language governing permissions and
0014:         * limitations under the License.
0015:         */
0016:        package org.kuali.core.util;
0017:
0018:        import java.beans.PropertyDescriptor;
0019:        import java.io.ByteArrayInputStream;
0020:        import java.io.ByteArrayOutputStream;
0021:        import java.io.IOException;
0022:        import java.io.ObjectInputStream;
0023:        import java.io.ObjectOutputStream;
0024:        import java.io.Serializable;
0025:        import java.lang.reflect.InvocationTargetException;
0026:        import java.security.MessageDigest;
0027:        import java.util.Collection;
0028:        import java.util.Iterator;
0029:        import java.util.List;
0030:        import java.util.Map;
0031:
0032:        import org.apache.commons.beanutils.NestedNullException;
0033:        import org.apache.commons.beanutils.PropertyUtils;
0034:        import org.apache.commons.lang.StringUtils;
0035:        import org.apache.log4j.Logger;
0036:        import org.apache.ojb.broker.core.proxy.ProxyHelper;
0037:        import org.kuali.RiceConstants;
0038:        import org.kuali.core.bo.BusinessObject;
0039:        import org.kuali.core.bo.PersistableBusinessObject;
0040:        import org.kuali.core.bo.PersistableBusinessObjectExtension;
0041:        import org.kuali.core.service.PersistenceStructureService;
0042:        import org.kuali.core.util.cache.CacheException;
0043:        import org.kuali.core.web.format.FormatException;
0044:        import org.kuali.core.web.format.Formatter;
0045:        import org.kuali.core.web.struts.pojo.PojoPropertyUtilsBean;
0046:        import org.kuali.rice.KNSServiceLocator;
0047:
0048:        /**
0049:         * This class contains various Object, Proxy, and serialization utilities.
0050:         */
0051:        public class ObjectUtils {
0052:            private static final Logger LOG = Logger
0053:                    .getLogger(ObjectUtils.class);
0054:
0055:            private ObjectUtils() {
0056:            }
0057:
0058:            /**
0059:             * Uses Serialization mechanism to create a deep copy of the given Object. As a special case, deepCopy of null returns null,
0060:             * just to make using this method simpler. For a detailed discussion see:
0061:             * http://www.javaworld.com/javaworld/javatips/jw-javatip76.html
0062:             * 
0063:             * @param src
0064:             * @return deep copy of the given Serializable
0065:             */
0066:            public static Serializable deepCopy(Serializable src) {
0067:                CopiedObject co = deepCopyForCaching(src);
0068:                return co.getContent();
0069:            }
0070:
0071:            /**
0072:             * Uses Serialization mechanism to create a deep copy of the given Object, and returns a CacheableObject instance containing the
0073:             * deepCopy and its size in bytes. As a special case, deepCopy of null returns a cacheableObject containing null and a size of
0074:             * 0, to make using this method simpler. For a detailed discussion see:
0075:             * http://www.javaworld.com/javaworld/javatips/jw-javatip76.html
0076:             * 
0077:             * @param src
0078:             * @return CopiedObject containing a deep copy of the given Serializable and its size in bytes
0079:             */
0080:            public static CopiedObject deepCopyForCaching(Serializable src) {
0081:                Timer t0 = new Timer("deepCopy");
0082:                CopiedObject co = new CopiedObject();
0083:
0084:                int copySize = 0;
0085:                if (src != null) {
0086:                    ObjectOutputStream oos = null;
0087:                    ObjectInputStream ois = null;
0088:                    try {
0089:                        ByteArrayOutputStream serializer = new ByteArrayOutputStream();
0090:                        oos = new ObjectOutputStream(serializer);
0091:                        oos.writeObject(src);
0092:
0093:                        co.setSize(serializer.size());
0094:
0095:                        ByteArrayInputStream deserializer = new ByteArrayInputStream(
0096:                                serializer.toByteArray());
0097:                        ois = new ObjectInputStream(deserializer);
0098:                        Serializable copy = (Serializable) ois.readObject();
0099:
0100:                        co.setContent(copy);
0101:                    } catch (IOException e) {
0102:                        throw new CacheException(
0103:                                "unable to complete deepCopy from src '"
0104:                                        + src.toString() + "'", e);
0105:                    } catch (ClassNotFoundException e) {
0106:                        throw new CacheException(
0107:                                "unable to complete deepCopy from src '"
0108:                                        + src.toString() + "'", e);
0109:                    } finally {
0110:                        try {
0111:                            if (oos != null) {
0112:                                oos.close();
0113:                            }
0114:                            if (ois != null) {
0115:                                ois.close();
0116:                            }
0117:                        } catch (IOException e) {
0118:                            // ignoring this IOException, since the streams are going to be abandoned now anyway
0119:                        }
0120:                    }
0121:                }
0122:                t0.log();
0123:                return co;
0124:            }
0125:
0126:            /**
0127:             * Converts the object to a byte array using the output stream.
0128:             * 
0129:             * @param object
0130:             * @return byte array of the object
0131:             */
0132:            public static byte[] toByteArray(Object object) throws Exception {
0133:                ObjectOutputStream oos = null;
0134:                try {
0135:                    ByteArrayOutputStream bos = new ByteArrayOutputStream(); // A
0136:                    oos = new ObjectOutputStream(bos); // B
0137:                    // serialize and pass the object
0138:                    oos.writeObject(object); // C
0139:                    // oos.flush(); // D
0140:                    return bos.toByteArray();
0141:                } catch (Exception e) {
0142:                    LOG.warn("Exception in ObjectUtil = " + e);
0143:                    throw (e);
0144:                } finally {
0145:                    if (oos != null) {
0146:                        oos.close();
0147:                    }
0148:                }
0149:            }
0150:
0151:            /**
0152:             * reconsitiutes the object that was converted into a byte array by toByteArray
0153:             * @param bytes
0154:             * @return
0155:             * @throws Exception
0156:             */
0157:            public static Object fromByteArray(byte[] bytes) throws Exception {
0158:                ObjectInputStream ois = null;
0159:                try {
0160:                    ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
0161:                    ois = new ObjectInputStream(bis);
0162:                    Object obj = ois.readObject();
0163:                    return obj;
0164:                } catch (Exception e) {
0165:                    LOG.warn("Exception in ObjectUtil = " + e);
0166:                    throw (e);
0167:                } finally {
0168:                    if (ois != null) {
0169:                        ois.close();
0170:                    }
0171:                }
0172:            }
0173:
0174:            /**
0175:             * use MD5 to create a one way hash of an object
0176:             * 
0177:             * @param object
0178:             * @return
0179:             */
0180:            public static String getMD5Hash(Object object) throws Exception {
0181:                try {
0182:                    MessageDigest md = MessageDigest.getInstance("MD5");
0183:                    md.update(toByteArray(object));
0184:                    return new String(md.digest());
0185:                } catch (Exception e) {
0186:                    LOG.warn(e);
0187:                    throw e;
0188:                }
0189:            }
0190:
0191:            /**
0192:             * Creates a new instance of a given BusinessObject, copying fields specified in template from the given source BO. For example,
0193:             * this can be used to create an AccountChangeDetail based on a particular Account.
0194:             * 
0195:             * @param template a map defining the relationships between the fields of the newly created BO, and the source BO.  For each K (key), V (value)
0196:             * entry, the value of property V on the source BO will be assigned to the K property of the newly created BO
0197:             * 
0198:             * @see org.kuali.core.maintenance.util.MaintenanceUtils
0199:             * 
0200:             * @throws NoSuchMethodException
0201:             * @throws InvocationTargetException
0202:             * @throws IllegalAccessException
0203:             * @throws FormatException
0204:             */
0205:
0206:            public static BusinessObject createHybridBusinessObject(
0207:                    Class businessObjectClass, BusinessObject source,
0208:                    Map<String, String> template) throws FormatException,
0209:                    IllegalAccessException, InvocationTargetException,
0210:                    NoSuchMethodException {
0211:                BusinessObject obj = null;
0212:                try {
0213:                    obj = (BusinessObject) businessObjectClass.newInstance();
0214:                } catch (InstantiationException e) {
0215:                    throw new RuntimeException("Cannot instantiate "
0216:                            + businessObjectClass.getName(), e);
0217:                }
0218:
0219:                for (String name : template.keySet()) {
0220:                    String sourcePropertyName = template.get(name);
0221:                    setObjectProperty(obj, name, easyGetPropertyType(source,
0222:                            sourcePropertyName), getPropertyValue(source,
0223:                            sourcePropertyName));
0224:                }
0225:
0226:                return obj;
0227:            }
0228:
0229:            /**
0230:             * This method simply uses PojoPropertyUtilsBean logic to get the Class of a Class property.
0231:             * This method does not have any of the logic needed to obtain the Class of an element of a Collection specified in the DataDictionary.
0232:             * 
0233:             * @param object An instance of the Class of which we're trying to get the property Class.
0234:             * @param propertyName The name of the property.
0235:
0236:             * @return
0237:             * 
0238:             * @throws IllegalAccessException
0239:             * @throws NoSuchMethodException
0240:             * @throws InvocationTargetException
0241:             */
0242:            static public Class easyGetPropertyType(Object object,
0243:                    String propertyName) throws IllegalAccessException,
0244:                    NoSuchMethodException, InvocationTargetException {
0245:
0246:                // FIXME (laran) This dependence should be inverted. Instead of having a core class
0247:                // depend on PojoPropertyUtilsBean, which is in the web layer, the web layer
0248:                // should depend downward to the core.
0249:                return (new PojoPropertyUtilsBean()).getPropertyType(object,
0250:                        propertyName);
0251:
0252:            }
0253:
0254:            /**
0255:             * Returns the type of the property in the object. This implementation is not smart enough to look through a Collection to get the property type
0256:             * of an attribute of an element in the collection.
0257:             * 
0258:             * NOTE: A patch file attached to https://test.kuali.org/jira/browse/KULRNE-4435 contains a modified version of this method which IS smart enough
0259:             * to look through Collections. This patch is currently under review.
0260:             * 
0261:             * @param object An instance of the Class for which we're trying to get the property type.
0262:             * @param propertyName The name of the property of the Class the Class of which we're trying to get. Dot notation is used to separate properties.
0263:             *                     TODO: The rules about this dot notation needs to be explained in Confluence using examples. 
0264:             * @param persistenceStructureService Needed to get the type of elements in a Collection from OJB. 
0265:             * 
0266:             * @return Object will be null if any parent property for the given property is null.
0267:             */
0268:            public static Class getPropertyType(Object object,
0269:                    String propertyName,
0270:                    PersistenceStructureService persistenceStructureService) {
0271:
0272:                if (object == null || propertyName == null) {
0273:                    throw new RuntimeException(
0274:                            "Business object and property name can not be null");
0275:                }
0276:
0277:                Class propertyType = null;
0278:
0279:                try {
0280:
0281:                    try {
0282:
0283:                        // Try to simply use the default or simple way of getting the property type.
0284:                        propertyType = PropertyUtils.getPropertyType(object,
0285:                                propertyName);
0286:
0287:                    } catch (IllegalArgumentException ex) {
0288:                        // swallow the exception, propertyType stays null
0289:                    } catch (NoSuchMethodException nsme) {
0290:                        // swallow the exception, propertyType stays null
0291:                    }
0292:
0293:                    // if the property type as determined from the object is PersistableBusinessObject,
0294:                    // then this must be an extension attribute -- attempt to get the property type from the
0295:                    // persistence structure service
0296:                    if (propertyType != null
0297:                            && propertyType
0298:                                    .equals(PersistableBusinessObjectExtension.class)) {
0299:                        propertyType = persistenceStructureService
0300:                                .getBusinessObjectAttributeClass(ProxyHelper
0301:                                        .getRealClass(object), propertyName);
0302:                    }
0303:
0304:                    // If the easy way didn't work ...
0305:                    if (null == propertyType && -1 != propertyName.indexOf('.')) {
0306:
0307:                        if (null == persistenceStructureService) {
0308:
0309:                            LOG
0310:                                    .info("PropertyType couldn't be determined simply and no PersistenceStructureService was given. If you pass in a PersistenceStructureService I can look in other places to try to determine the type of the property.");
0311:
0312:                        } else {
0313:
0314:                            String prePeriod = StringUtils.substringBefore(
0315:                                    propertyName, ".");
0316:                            String postPeriod = StringUtils.substringAfter(
0317:                                    propertyName, ".");
0318:
0319:                            Class prePeriodClass = getPropertyType(object,
0320:                                    prePeriod, persistenceStructureService);
0321:                            Object prePeriodClassInstance = prePeriodClass
0322:                                    .newInstance();
0323:                            propertyType = getPropertyType(
0324:                                    prePeriodClassInstance, postPeriod,
0325:                                    persistenceStructureService);
0326:
0327:                        }
0328:
0329:                    } else if (Collection.class.isAssignableFrom(propertyType)) {
0330:
0331:                        Map<String, Class> map = persistenceStructureService
0332:                                .listCollectionObjectTypes(object.getClass());
0333:                        propertyType = map.get(propertyName);
0334:
0335:                    }
0336:
0337:                } catch (Exception e) {
0338:
0339:                    LOG.debug("unable to get property type for " + propertyName
0340:                            + " " + e.getMessage());
0341:                    // continue and return null for propertyType
0342:
0343:                }
0344:
0345:                return propertyType;
0346:            }
0347:
0348:            /**
0349:             * Returns the value of the property in the object.
0350:             * 
0351:             * @param businessObject
0352:             * @param propertyName
0353:             * 
0354:             * @return Object will be null if any parent property for the given property is null.
0355:             */
0356:            public static Object getPropertyValue(Object businessObject,
0357:                    String propertyName) {
0358:                if (businessObject == null || propertyName == null) {
0359:                    throw new RuntimeException(
0360:                            "Business object and property name can not be null");
0361:                }
0362:
0363:                Object propertyValue = null;
0364:                try {
0365:                    propertyValue = PropertyUtils.getProperty(businessObject,
0366:                            propertyName);
0367:                } catch (NestedNullException e) {
0368:                    // continue and return null for propertyValue
0369:                } catch (IllegalAccessException e1) {
0370:                    LOG.error("error getting property value for  "
0371:                            + propertyName + " " + e1.getMessage());
0372:                    throw new RuntimeException(
0373:                            "error getting property value for  " + propertyName
0374:                                    + " " + e1.getMessage());
0375:                } catch (InvocationTargetException e1) {
0376:                    // continue and return null for propertyValue
0377:                } catch (NoSuchMethodException e1) {
0378:                    LOG.error("error getting property value for  "
0379:                            + propertyName + " " + e1.getMessage());
0380:                    throw new RuntimeException(
0381:                            "error getting property value for  " + propertyName
0382:                                    + " " + e1.getMessage());
0383:                }
0384:
0385:                return propertyValue;
0386:            }
0387:
0388:            /**
0389:             * Sets the property of an object with the given value. Converts using the formatter of the type for the property.
0390:             * Note: propertyType does not need passed, is found by util method.
0391:             */
0392:            public static void setObjectProperty(Object bo,
0393:                    String propertyName, Object propertyValue)
0394:                    throws FormatException, IllegalAccessException,
0395:                    InvocationTargetException, NoSuchMethodException {
0396:                Class propertyType = easyGetPropertyType(bo, propertyName);
0397:                setObjectProperty(bo, propertyName, propertyType, propertyValue);
0398:            }
0399:
0400:            /**
0401:             * Sets the property of an object with the given value. Converts using the formatter of the given type if one is found.
0402:             * 
0403:             * @param bo
0404:             * @param propertyName
0405:             * @param propertyType
0406:             * @param propertyValue
0407:             * 
0408:             * @throws NoSuchMethodException
0409:             * @throws InvocationTargetException
0410:             * @throws IllegalAccessException
0411:             */
0412:            public static void setObjectProperty(Object bo,
0413:                    String propertyName, Class propertyType,
0414:                    Object propertyValue) throws FormatException,
0415:                    IllegalAccessException, InvocationTargetException,
0416:                    NoSuchMethodException {
0417:                // reformat propertyValue, if necessary
0418:                boolean reformat = false;
0419:                if (propertyValue != null
0420:                        && propertyType.isAssignableFrom(String.class)) {
0421:                    // always reformat if the destination is a String
0422:                    reformat = true;
0423:                } else if (propertyValue != null
0424:                        && !propertyType.isAssignableFrom(propertyValue
0425:                                .getClass())) {
0426:                    // otherwise, only reformat if the propertyValue can't be assigned into the property
0427:                    reformat = true;
0428:                }
0429:
0430:                // attempting to set boolean fields to null throws an exception, set to false instead
0431:                if (boolean.class.isAssignableFrom(propertyType)
0432:                        && propertyValue == null) {
0433:                    propertyValue = false;
0434:                }
0435:
0436:                if (reformat && Formatter.findFormatter(propertyType) != null) {
0437:                    Formatter formatter = Formatter.getFormatter(propertyType);
0438:                    LOG.debug("reformatting propertyValue using Formatter "
0439:                            + formatter.getClass().getName());
0440:                    propertyValue = formatter
0441:                            .convertFromPresentationFormat(propertyValue);
0442:                }
0443:
0444:                // set property in the object
0445:                (new PojoPropertyUtilsBean()).setNestedProperty(bo,
0446:                        propertyName, propertyValue);
0447:            }
0448:
0449:            /**
0450:             * Sets the property of an object with the given value. Converts using the given formatter, if it isn't null.
0451:             * 
0452:             * @param formatter
0453:             * @param bo
0454:             * @param propertyName
0455:             * @param type
0456:             * @param propertyValue
0457:             * 
0458:             * @throws NoSuchMethodException
0459:             * @throws InvocationTargetException
0460:             * @throws IllegalAccessException
0461:             */
0462:            public static void setObjectProperty(Formatter formatter,
0463:                    Object bo, String propertyName, Class type,
0464:                    Object propertyValue) throws FormatException,
0465:                    IllegalAccessException, InvocationTargetException,
0466:                    NoSuchMethodException {
0467:
0468:                // convert value using formatter for type
0469:                if (formatter != null) {
0470:                    propertyValue = formatter
0471:                            .convertFromPresentationFormat(propertyValue);
0472:                }
0473:
0474:                // set property in the object
0475:                PropertyUtils
0476:                        .setNestedProperty(bo, propertyName, propertyValue);
0477:            }
0478:
0479:            /**
0480:             * Recursive; sets all occurences of the property in the object, its nested objects and its object lists with the given value.
0481:             * 
0482:             * @param bo
0483:             * @param propertyName
0484:             * @param type
0485:             * @param propertyValue
0486:             * 
0487:             * @throws NoSuchMethodException
0488:             * @throws InvocationTargetException
0489:             * @throws IllegalAccessException
0490:             */
0491:            public static void setObjectPropertyDeep(Object bo,
0492:                    String propertyName, Class type, Object propertyValue)
0493:                    throws FormatException, IllegalAccessException,
0494:                    InvocationTargetException, NoSuchMethodException {
0495:
0496:                // Base return cases to avoid null pointers & infinite loops
0497:                if (isNull(bo)
0498:                        || !PropertyUtils.isReadable(bo, propertyName)
0499:                        || (propertyValue != null && propertyValue
0500:                                .equals(getPropertyValue(bo, propertyName)))
0501:                        || (type != null && !type.equals(easyGetPropertyType(
0502:                                bo, propertyName)))) {
0503:                    return;
0504:                }
0505:
0506:                // need to materialize the updateable collections before resetting the property, because it may be used in the retrieval
0507:                materializeUpdateableCollections(bo);
0508:
0509:                // Set the property in the BO
0510:                setObjectProperty(bo, propertyName, type, propertyValue);
0511:
0512:                // Now drill down and check nested BOs and BO lists
0513:                PropertyDescriptor[] propertyDescriptors = PropertyUtils
0514:                        .getPropertyDescriptors(bo.getClass());
0515:                for (int i = 0; i < propertyDescriptors.length; i++) {
0516:
0517:                    PropertyDescriptor propertyDescriptor = propertyDescriptors[i];
0518:
0519:                    // Business Objects
0520:                    if (propertyDescriptor.getPropertyType() != null
0521:                            && (BusinessObject.class)
0522:                                    .isAssignableFrom(propertyDescriptor
0523:                                            .getPropertyType())
0524:                            && PropertyUtils.isReadable(bo, propertyDescriptor
0525:                                    .getName())) {
0526:                        BusinessObject nestedBo = (BusinessObject) getPropertyValue(
0527:                                bo, propertyDescriptor.getName());
0528:                        setObjectPropertyDeep(nestedBo, propertyName, type,
0529:                                propertyValue);
0530:                    }
0531:
0532:                    // Lists
0533:                    else if (propertyDescriptor.getPropertyType() != null
0534:                            && (List.class).isAssignableFrom(propertyDescriptor
0535:                                    .getPropertyType())
0536:                            && getPropertyValue(bo, propertyDescriptor
0537:                                    .getName()) != null) {
0538:
0539:                        List propertyList = (List) getPropertyValue(bo,
0540:                                propertyDescriptor.getName());
0541:                        for (Object listedBo : propertyList) {
0542:                            if (listedBo != null
0543:                                    && listedBo instanceof  BusinessObject) {
0544:                                setObjectPropertyDeep(listedBo, propertyName,
0545:                                        type, propertyValue);
0546:                            }
0547:                        } // end for
0548:                    }
0549:                } // end for
0550:            }
0551:
0552:            /*
0553:             * Recursive up to a given depth; sets all occurences of the property in the object, its nested objects and its object lists with the given value.
0554:             */
0555:            public static void setObjectPropertyDeep(Object bo,
0556:                    String propertyName, Class type, Object propertyValue,
0557:                    int depth) throws FormatException, IllegalAccessException,
0558:                    InvocationTargetException, NoSuchMethodException {
0559:                // Base return cases to avoid null pointers & infinite loops
0560:                if (depth == 0 || isNull(bo)
0561:                        || !PropertyUtils.isReadable(bo, propertyName)) {
0562:                    return;
0563:                }
0564:
0565:                // need to materialize the updateable collections before resetting the property, because it may be used in the retrieval
0566:                materializeUpdateableCollections(bo);
0567:
0568:                // Set the property in the BO
0569:                setObjectProperty(bo, propertyName, type, propertyValue);
0570:
0571:                // Now drill down and check nested BOs and BO lists
0572:                PropertyDescriptor[] propertyDescriptors = PropertyUtils
0573:                        .getPropertyDescriptors(bo.getClass());
0574:                for (int i = 0; i < propertyDescriptors.length; i++) {
0575:                    PropertyDescriptor propertyDescriptor = propertyDescriptors[i];
0576:
0577:                    // Business Objects
0578:                    if (propertyDescriptor.getPropertyType() != null
0579:                            && (BusinessObject.class)
0580:                                    .isAssignableFrom(propertyDescriptor
0581:                                            .getPropertyType())
0582:                            && PropertyUtils.isReadable(bo, propertyDescriptor
0583:                                    .getName())) {
0584:                        BusinessObject nestedBo = (BusinessObject) getPropertyValue(
0585:                                bo, propertyDescriptor.getName());
0586:                        setObjectPropertyDeep(nestedBo, propertyName, type,
0587:                                propertyValue, depth - 1);
0588:                    }
0589:
0590:                    // Lists
0591:                    else if (propertyDescriptor.getPropertyType() != null
0592:                            && (List.class).isAssignableFrom(propertyDescriptor
0593:                                    .getPropertyType())
0594:                            && getPropertyValue(bo, propertyDescriptor
0595:                                    .getName()) != null) {
0596:
0597:                        List propertyList = (List) getPropertyValue(bo,
0598:                                propertyDescriptor.getName());
0599:                        for (Object listedBo : propertyList) {
0600:                            if (listedBo != null
0601:                                    && listedBo instanceof  BusinessObject) {
0602:                                setObjectPropertyDeep(listedBo, propertyName,
0603:                                        type, propertyValue, depth - 1);
0604:                            }
0605:                        } // end for
0606:                    }
0607:                } // end for
0608:            }
0609:
0610:            /**
0611:             * 
0612:             * This method checks for updateable collections on the business object provided and materializes the corresponding collection proxies
0613:             * 
0614:             * @param bo The business object for which you want unpdateable, proxied collections materialized
0615:             * @throws FormatException
0616:             * @throws IllegalAccessException
0617:             * @throws InvocationTargetException
0618:             * @throws NoSuchMethodException
0619:             */
0620:            public static void materializeUpdateableCollections(Object bo)
0621:                    throws FormatException, IllegalAccessException,
0622:                    InvocationTargetException, NoSuchMethodException {
0623:                if (isNotNull(bo)) {
0624:                    PropertyDescriptor[] propertyDescriptors = PropertyUtils
0625:                            .getPropertyDescriptors(bo.getClass());
0626:                    for (int i = 0; i < propertyDescriptors.length; i++) {
0627:                        if (KNSServiceLocator.getPersistenceStructureService()
0628:                                .hasCollection(bo.getClass(),
0629:                                        propertyDescriptors[i].getName())
0630:                                && KNSServiceLocator
0631:                                        .getPersistenceStructureService()
0632:                                        .isCollectionUpdatable(
0633:                                                bo.getClass(),
0634:                                                propertyDescriptors[i]
0635:                                                        .getName())) {
0636:                            Collection updateableCollection = (Collection) getPropertyValue(
0637:                                    bo, propertyDescriptors[i].getName());
0638:                            if ((updateableCollection != null)
0639:                                    && ProxyHelper
0640:                                            .isCollectionProxy(updateableCollection)) {
0641:                                materializeObjects(updateableCollection);
0642:                            }
0643:                        }
0644:                    }
0645:                }
0646:            }
0647:
0648:            /**
0649:             * Removes all query characters from a string.
0650:             * 
0651:             * @param string
0652:             * 
0653:             * @return Cleaned string
0654:             */
0655:            public static String clean(String string) {
0656:                for (int i = 0; i < RiceConstants.QUERY_CHARACTERS.length; i++) {
0657:                    string = StringUtils.replace(string,
0658:                            RiceConstants.QUERY_CHARACTERS[i],
0659:                            RiceConstants.EMPTY_STRING);
0660:                }
0661:                return string;
0662:            }
0663:
0664:            /**
0665:             * Compares two business objects for equality of type and key values.
0666:             * 
0667:             * @param bo1
0668:             * @param bo2
0669:             * 
0670:             * @return boolean indicating whether the two objects are equal.
0671:             */
0672:            public static boolean equalByKeys(BusinessObject bo1,
0673:                    BusinessObject bo2) {
0674:                boolean equal = true;
0675:
0676:                if (bo1 == null && bo2 == null) {
0677:                    equal = true;
0678:                } else if (bo1 == null || bo2 == null) {
0679:                    equal = false;
0680:                } else if (!bo1.getClass().getName().equals(
0681:                        bo2.getClass().getName())) {
0682:                    equal = false;
0683:                } else {
0684:                    Map bo1Keys = KNSServiceLocator.getPersistenceService()
0685:                            .getPrimaryKeyFieldValues(bo1);
0686:                    Map bo2Keys = KNSServiceLocator.getPersistenceService()
0687:                            .getPrimaryKeyFieldValues(bo2);
0688:                    for (Iterator iter = bo1Keys.keySet().iterator(); iter
0689:                            .hasNext();) {
0690:                        String keyName = (String) iter.next();
0691:                        if (bo1Keys.get(keyName) != null
0692:                                && bo2Keys.get(keyName) != null) {
0693:                            if (!bo1Keys.get(keyName).toString().equals(
0694:                                    bo2Keys.get(keyName).toString())) {
0695:                                equal = false;
0696:                            }
0697:                        }
0698:                    }
0699:                }
0700:
0701:                return equal;
0702:            }
0703:
0704:            /**
0705:             * Compares a business object with a List of BOs to determine if an object with the same key as the BO exists in the list.
0706:             * 
0707:             * @param controlList - The list of items to check
0708:             * @param bo - The BO whose keys we are looking for in the controlList
0709:             * 
0710:             * @return boolean
0711:             */
0712:            public static boolean collectionContainsObjectWithIdentitcalKey(
0713:                    Collection controlList, BusinessObject bo) {
0714:                boolean objectExistsInList = false;
0715:
0716:                for (Iterator i = controlList.iterator(); i.hasNext();) {
0717:                    if (equalByKeys((BusinessObject) i.next(), bo)) {
0718:                        return true;
0719:                    }
0720:                }
0721:
0722:                return objectExistsInList;
0723:            }
0724:
0725:            /**
0726:             * Compares a business object with a Collection of BOs to count how many have the same key as the BO.
0727:             * 
0728:             * @param collection - The collection of items to check
0729:             * @param bo - The BO whose keys we are looking for in the collection
0730:             * 
0731:             * @return how many have the same keys
0732:             */
0733:            public static int countObjectsWithIdentitcalKey(
0734:                    Collection<? extends BusinessObject> collection,
0735:                    BusinessObject bo) {
0736:                // todo: genericize collectionContainsObjectWithIdentitcalKey() to leverage this method?
0737:                int n = 0;
0738:                for (BusinessObject item : collection) {
0739:                    if (equalByKeys(item, bo)) {
0740:                        n++;
0741:                    }
0742:                }
0743:                return n;
0744:            }
0745:
0746:            /**
0747:             * Compares a business object with a List of BOs to determine if an object with the same key as the BO exists in the list. If it
0748:             * does, the item is removed from the List. This is functionally similar to List.remove() that operates only on Key values.
0749:             * 
0750:             * @param controlList - The list of items to check
0751:             * @param bo - The BO whose keys we are looking for in the controlList
0752:             */
0753:
0754:            public static void removeObjectWithIdentitcalKey(
0755:                    Collection controlList, BusinessObject bo) {
0756:                for (Iterator i = controlList.iterator(); i.hasNext();) {
0757:                    BusinessObject listBo = (BusinessObject) i.next();
0758:                    if (equalByKeys(listBo, bo)) {
0759:                        i.remove();
0760:                    }
0761:                }
0762:            }
0763:
0764:            /**
0765:             * Compares a business object with a List of BOs to determine if an object with the same key as the BO exists in the list. If it
0766:             * does, the item is returned.
0767:             * 
0768:             * @param controlList - The list of items to check
0769:             * @param bo - The BO whose keys we are looking for in the controlList
0770:             */
0771:
0772:            public static BusinessObject retrieveObjectWithIdentitcalKey(
0773:                    Collection controlList, BusinessObject bo) {
0774:                BusinessObject returnBo = null;
0775:
0776:                for (Iterator i = controlList.iterator(); i.hasNext();) {
0777:                    BusinessObject listBo = (BusinessObject) i.next();
0778:                    if (equalByKeys(listBo, bo)) {
0779:                        returnBo = listBo;
0780:                    }
0781:                }
0782:
0783:                return returnBo;
0784:            }
0785:
0786:            /**
0787:             * Determines if a given string could represent a nested attribute of an object.
0788:             * 
0789:             * @param attributeName
0790:             * 
0791:             * @return true if the attribute is nested
0792:             */
0793:            public static boolean isNestedAttribute(String attributeName) {
0794:                boolean isNested = false;
0795:
0796:                if (StringUtils.contains(attributeName, ".")) {
0797:                    isNested = true;
0798:                }
0799:
0800:                return isNested;
0801:            }
0802:
0803:            /**
0804:             * Returns the prefix of a nested attribute name, or the empty string if the attribute name is not nested.
0805:             * 
0806:             * @param attributeName
0807:             * 
0808:             * @return everything BEFORE the last "." character in attributeName
0809:             */
0810:            public static String getNestedAttributePrefix(String attributeName) {
0811:                String prefix = "";
0812:
0813:                if (StringUtils.contains(attributeName, ".")) {
0814:                    prefix = StringUtils
0815:                            .substringBeforeLast(attributeName, ".");
0816:                }
0817:
0818:                return prefix;
0819:            }
0820:
0821:            /**
0822:             * Returns the primitive part of an attribute name string.
0823:             * 
0824:             * @param attributeName
0825:             * 
0826:             * @return everything AFTER the last "." character in attributeName
0827:             */
0828:            public static String getNestedAttributePrimitive(
0829:                    String attributeName) {
0830:                String primitive = attributeName;
0831:
0832:                if (StringUtils.contains(attributeName, ".")) {
0833:                    primitive = StringUtils.substringAfterLast(attributeName,
0834:                            ".");
0835:                }
0836:
0837:                return primitive;
0838:            }
0839:
0840:            /**
0841:             * This method is a OJB Proxy-safe way to test for null on a proxied object that may or may not be materialized yet. It is safe
0842:             * to use on a proxy (materialized or non-materialized) or on a non-proxy (ie, regular object). Note that this will force a
0843:             * materialization of the proxy if the object is a proxy and unmaterialized.
0844:             * 
0845:             * @param object - any object, proxied or not, materialized or not
0846:             * 
0847:             * @return true if the object (or underlying materialized object) is null, false otherwise
0848:             */
0849:            public static boolean isNull(Object object) {
0850:
0851:                // regardless, if its null, then its null
0852:                if (object == null) {
0853:                    return true;
0854:                }
0855:
0856:                // only try to materialize the object to see if its null if this is a
0857:                // proxy object
0858:                if (ProxyHelper.isProxy(object)
0859:                        || ProxyHelper.isCollectionProxy(object)) {
0860:                    if (ProxyHelper.getRealObject(object) == null) {
0861:                        return true;
0862:                    }
0863:                }
0864:
0865:                return false;
0866:            }
0867:
0868:            /**
0869:             * This method is a OJB Proxy-safe way to test for notNull on a proxied object that may or may not be materialized yet. It is
0870:             * safe to use on a proxy (materialized or non-materialized) or on a non-proxy (ie, regular object). Note that this will force a
0871:             * materialization of the proxy if the object is a proxy and unmaterialized.
0872:             * 
0873:             * @param object - any object, proxied or not, materialized or not
0874:             * 
0875:             * @return true if the object (or underlying materialized object) is not null, true if its null
0876:             */
0877:            public static boolean isNotNull(Object object) {
0878:                return !ObjectUtils.isNull(object);
0879:            }
0880:
0881:            /**
0882:             * This method runs the ObjectUtils.isNotNull() method for each item in a list of BOs. ObjectUtils.isNotNull() will materialize
0883:             * the objects if they are currently OJB proxies.
0884:             * 
0885:             * @param possiblyProxiedObjects - a Collection of objects that may be proxies
0886:             */
0887:            public static void materializeObjects(
0888:                    Collection possiblyProxiedObjects) {
0889:                for (Iterator i = possiblyProxiedObjects.iterator(); i
0890:                        .hasNext();) {
0891:                    ObjectUtils.isNotNull(i.next());
0892:                }
0893:            }
0894:
0895:            /**
0896:             * This method attempts to materialize all of the proxied reference objects (ie, sub-objects) hanging off the passed-in BO
0897:             * object. It will do it down to the specified depth. An IllegalArgumentException will be thrown if the bo object passed in is
0898:             * itself a non-materialized proxy object. If the bo passed in has no proxied sub-objects, then the object will not be modified,
0899:             * and no errors will be thrown. WARNING: Be careful using depth any greater than 2. The number of DB hits, time, and memory
0900:             * consumed grows exponentially with each additional increment to depth. Make sure you really need that depth before doing so.
0901:             * 
0902:             * @param bo A valid, populated BusinessObject containing (possibly) proxied sub-objects. This object will be modified in place.
0903:             * @param depth int Value 0-5 indicating how deep to recurse the materialization. If a zero (0) is passed in, then no work will
0904:             *        be done.
0905:             */
0906:            public static void materializeSubObjectsToDepth(
0907:                    PersistableBusinessObject bo, int depth) {
0908:                if (bo == null) {
0909:                    throw new IllegalArgumentException(
0910:                            "The bo passed in was null.");
0911:                }
0912:                if (depth < 0 || depth > 5) {
0913:                    throw new IllegalArgumentException(
0914:                            "The depth passed in was out of bounds.  Only values "
0915:                                    + "between 0 and 5, inclusively, are allowed.");
0916:                }
0917:
0918:                // if depth is zero, then we're done recursing and can just exit
0919:                if (depth == 0) {
0920:                    return;
0921:                }
0922:
0923:                // deal with the possibility that the bo passed in (ie, the parent object) is an un-materialized proxy
0924:                if (ProxyHelper.isProxy(bo)) {
0925:                    if (!ProxyHelper.isMaterialized(bo)) {
0926:                        throw new IllegalArgumentException(
0927:                                "The bo passed in is an un-materialized proxy, and cannot be used.");
0928:                    }
0929:                }
0930:
0931:                // get the list of reference objects hanging off the parent BO
0932:                Map<String, Class> references = KNSServiceLocator
0933:                        .getPersistenceStructureService()
0934:                        .listReferenceObjectFields(bo);
0935:
0936:                // initialize our in-loop objects
0937:                String referenceName = "";
0938:                Class referenceClass = null;
0939:                Object referenceValue = null;
0940:                Object realReferenceValue = null;
0941:
0942:                // for each reference object on the parent bo
0943:                for (Iterator iter = references.keySet().iterator(); iter
0944:                        .hasNext();) {
0945:                    referenceName = (String) iter.next();
0946:                    referenceClass = references.get(referenceName);
0947:
0948:                    // if its a proxy, replace it with a non-proxy
0949:                    referenceValue = getPropertyValue(bo, referenceName);
0950:                    if (referenceValue != null) {
0951:                        if (ProxyHelper.isProxy(referenceValue)) {
0952:                            realReferenceValue = ProxyHelper
0953:                                    .getRealObject(referenceValue);
0954:                            if (realReferenceValue != null) {
0955:                                try {
0956:                                    setObjectProperty(bo, referenceName,
0957:                                            referenceClass, realReferenceValue);
0958:                                } catch (FormatException e) {
0959:                                    throw new RuntimeException(
0960:                                            "FormatException: could not set the property '"
0961:                                                    + referenceName + "'.", e);
0962:                                } catch (IllegalAccessException e) {
0963:                                    throw new RuntimeException(
0964:                                            "IllegalAccessException: could not set the property '"
0965:                                                    + referenceName + "'.", e);
0966:                                } catch (InvocationTargetException e) {
0967:                                    throw new RuntimeException(
0968:                                            "InvocationTargetException: could not set the property '"
0969:                                                    + referenceName + "'.", e);
0970:                                } catch (NoSuchMethodException e) {
0971:                                    throw new RuntimeException(
0972:                                            "NoSuchMethodException: could not set the property '"
0973:                                                    + referenceName + "'.", e);
0974:                                }
0975:                            }
0976:                        }
0977:
0978:                        // recurse down through this reference object
0979:                        if (realReferenceValue instanceof  PersistableBusinessObject
0980:                                && depth > 1) {
0981:                            materializeSubObjectsToDepth(
0982:                                    (PersistableBusinessObject) realReferenceValue,
0983:                                    depth - 1);
0984:                        }
0985:                    }
0986:
0987:                }
0988:            }
0989:
0990:            /**
0991:             * This method attempts to materialize all of the proxied reference objects (ie, sub-objects) hanging off the passed-in BO
0992:             * object. It will do it just three levels down. In other words, it will only materialize the objects that are direct members of
0993:             * the bo, objects that are direct members of those bos, that one more time, and no further down. An IllegalArgumentException 
0994:             * will be thrown if the bo object passed in is itself a non-materialized proxy object. If the bo passed in has no proxied 
0995:             * sub-objects, then the object will not be modified, and no errors will be thrown.
0996:             * 
0997:             * @param bo A valid, populated BusinessObject containing (possibly) proxied sub-objects. This object will be modified in place.
0998:             */
0999:            public static void materializeAllSubObjects(
1000:                    PersistableBusinessObject bo) {
1001:                materializeSubObjectsToDepth(bo, 3);
1002:            }
1003:
1004:            /**
1005:             * This method safely extracts either simple values OR nested values. For example, if the bo is SubAccount, and the fieldName is
1006:             * a21SubAccount.subAccountTypeCode, this thing makes sure it gets the value off the very end attribute, no matter how deeply
1007:             * nested it is. The code would be slightly simpler if this was done recursively, but this is safer, and consumes a constant
1008:             * amount of memory, no matter how deeply nested it goes.
1009:             * 
1010:             * @param bo
1011:             * @param fieldName
1012:             * 
1013:             * @return The field value if it exists. If it doesnt, and the name is invalid, and
1014:             */
1015:            public static Object getNestedValue(BusinessObject bo,
1016:                    String fieldName) {
1017:
1018:                if (bo == null) {
1019:                    throw new IllegalArgumentException(
1020:                            "The bo passed in was null.");
1021:                }
1022:                if (StringUtils.isBlank(fieldName)) {
1023:                    throw new IllegalArgumentException(
1024:                            "The fieldName passed in was blank.");
1025:                }
1026:
1027:                // okay, this section of code is to handle sub-object values, like
1028:                // SubAccount.a21SubAccount.subAccountTypeCode. it basically walks
1029:                // through the period-delimited list of names, and ends up with the
1030:                // final value.
1031:                String[] fieldNameParts = fieldName.split("\\.");
1032:                Object currentObject = null;
1033:                Object priorObject = bo;
1034:                for (int i = 0; i < fieldNameParts.length; i++) {
1035:                    String fieldNamePart = fieldNameParts[i];
1036:
1037:                    try {
1038:                        if (fieldNamePart.indexOf("]") > 0) {
1039:                            currentObject = PropertyUtils.getIndexedProperty(
1040:                                    priorObject, fieldNamePart);
1041:                        } else {
1042:                            currentObject = PropertyUtils.getSimpleProperty(
1043:                                    priorObject, fieldNamePart);
1044:                        }
1045:                    } catch (IllegalAccessException e) {
1046:                        throw new RuntimeException(
1047:                                "Caller does not have access to the property accessor method.",
1048:                                e);
1049:                    } catch (InvocationTargetException e) {
1050:                        throw new RuntimeException(
1051:                                "Property accessor method threw an exception.",
1052:                                e);
1053:                    } catch (NoSuchMethodException e) {
1054:                        throw new RuntimeException(
1055:                                "The accessor method requested for this property cannot be found.",
1056:                                e);
1057:                    }
1058:
1059:                    // materialize the proxy, if it is a proxy
1060:                    if (ProxyHelper.isProxy(currentObject)) {
1061:                        currentObject = ProxyHelper
1062:                                .getRealObject(currentObject);
1063:                    }
1064:
1065:                    // if a node or the leaf is null, then we're done, there's no need to
1066:                    // continue accessing null things
1067:                    if (currentObject == null) {
1068:                        return currentObject;
1069:                    }
1070:
1071:                    priorObject = currentObject;
1072:                }
1073:                return currentObject;
1074:            }
1075:
1076:            /**
1077:             * Returns the equality of the two given objects, automatically handling when one or both of the objects is null.
1078:             * 
1079:             * @param obj1
1080:             * @param obj2
1081:             * 
1082:             * @return true if both objects are null or both are equal
1083:             */
1084:            public static boolean nullSafeEquals(Object obj1, Object obj2) {
1085:                if (obj1 != null && obj2 != null) {
1086:                    return obj1.equals(obj2);
1087:                } else {
1088:                    return (obj1 == obj2);
1089:                }
1090:            }
1091:
1092:            /**
1093:             * 
1094:             * This method safely creates a object from a class
1095:             * Convenience method to create new object and throw a runtime exception if it cannot
1096:             * 
1097:             * @param boClass
1098:             * 
1099:             * @return a newInstance() of clazz
1100:             */
1101:            public static Object createNewObjectFromClass(Class clazz) {
1102:                Object obj = null;
1103:                try {
1104:                    obj = clazz.newInstance();
1105:                } catch (InstantiationException ite) {
1106:                    LOG.info(ite);
1107:                    throw new RuntimeException(
1108:                            "ObjectUtils had a problem creating a new object of "
1109:                                    + clazz.getName(), ite);
1110:                } catch (IllegalAccessException iae) {
1111:                    LOG.info(iae);
1112:                    throw new RuntimeException(
1113:                            "ObjectUtils had a problem creating a new object of "
1114:                                    + clazz.getName(), iae);
1115:                }
1116:                return obj;
1117:            }
1118:
1119:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.