Source Code Cross Referenced for BeanMoulder.java in  » J2EE » Jaffa » org » jaffa » beans » moulding » mapping » 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 » J2EE » Jaffa » org.jaffa.beans.moulding.mapping 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * ====================================================================
0003:         * JAFFA - Java Application Framework For All
0004:         *
0005:         * Copyright (C) 2002 JAFFA Development Group
0006:         *
0007:         *     This library is free software; you can redistribute it and/or
0008:         *     modify it under the terms of the GNU Lesser General Public
0009:         *     License as published by the Free Software Foundation; either
0010:         *     version 2.1 of the License, or (at your option) any later version.
0011:         *
0012:         *     This library is distributed in the hope that it will be useful,
0013:         *     but WITHOUT ANY WARRANTY; without even the implied warranty of
0014:         *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0015:         *     Lesser General Public License for more details.
0016:         *
0017:         *     You should have received a copy of the GNU Lesser General Public
0018:         *     License along with this library; if not, write to the Free Software
0019:         *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
0020:         *
0021:         * Redistribution and use of this software and associated documentation ("Software"),
0022:         * with or without modification, are permitted provided that the following conditions are met:
0023:         * 1.	Redistributions of source code must retain copyright statements and notices.
0024:         *         Redistributions must also contain a copy of this document.
0025:         * 2.	Redistributions in binary form must reproduce the above copyright notice,
0026:         * 	this list of conditions and the following disclaimer in the documentation
0027:         * 	and/or other materials provided with the distribution.
0028:         * 3.	The name "JAFFA" must not be used to endorse or promote products derived from
0029:         * 	this Software without prior written permission. For written permission,
0030:         * 	please contact mail to: jaffagroup@yahoo.com.
0031:         * 4.	Products derived from this Software may not be called "JAFFA" nor may "JAFFA"
0032:         * 	appear in their names without prior written permission.
0033:         * 5.	Due credit should be given to the JAFFA Project (http://jaffa.sourceforge.net).
0034:         *
0035:         * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
0036:         * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0037:         * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
0038:         * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
0039:         * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0040:         * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0041:         * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
0042:         * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
0043:         * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
0044:         * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
0045:         * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
0046:         * SUCH DAMAGE.
0047:         * ====================================================================
0048:         */
0049:
0050:        /*
0051:         * BeanMolder.java
0052:         *
0053:         * Created on February 12, 2004, 4:00 PM
0054:         */
0055:
0056:        package org.jaffa.beans.moulding.mapping;
0057:
0058:        import java.beans.BeanInfo;
0059:        import java.beans.IntrospectionException;
0060:        import java.beans.Introspector;
0061:        import java.beans.PropertyDescriptor;
0062:        import java.lang.reflect.Array;
0063:        import java.lang.reflect.Constructor;
0064:        import java.lang.reflect.InvocationTargetException;
0065:        import java.lang.reflect.Method;
0066:        import java.util.ArrayList;
0067:        import java.util.HashMap;
0068:        import java.util.Iterator;
0069:        import java.util.LinkedHashMap;
0070:        import java.util.List;
0071:        import java.util.Map;
0072:        import java.util.Set;
0073:        import org.apache.log4j.Logger;
0074:        import org.jaffa.beans.moulding.data.domain.DomainDAO;
0075:        import org.jaffa.beans.moulding.mapping.GraphMapping;
0076:        import org.jaffa.beans.moulding.mapping.MappingFilter;
0077:        import org.jaffa.exceptions.ApplicationException;
0078:        import org.jaffa.exceptions.ApplicationExceptions;
0079:        import org.jaffa.exceptions.DomainObjectNotFoundException;
0080:        import org.jaffa.exceptions.FrameworkException;
0081:        import org.jaffa.exceptions.MultipleDomainObjectsFoundException;
0082:        import org.jaffa.persistence.Criteria;
0083:        import org.jaffa.persistence.IPersistent;
0084:        import org.jaffa.persistence.Persistent;
0085:        import org.jaffa.persistence.UOW;
0086:        import org.jaffa.persistence.util.PersistentHelper;
0087:        import org.jaffa.util.StringHelper;
0088:
0089:        /** Bean Moudler is used to mapp data between two Java Beans via a mapping file.
0090:         * It has been specifcially coded to map between benas that extend/implement
0091:         * DomainDAO and IPersistent for marshalling data to and from the database.
0092:         *
0093:         * @author  PaulE
0094:         * @version 1.0
0095:         */
0096:        public class BeanMoulder {
0097:
0098:            private static Logger log = Logger.getLogger(BeanMoulder.class);
0099:
0100:            /**
0101:             * Display the properties of this JavaBean. If this bean has properties that implement
0102:             * either DomainDAO or DomainDAO[], then also print this objects too.
0103:             * @param source Javabean who's contents should be printed
0104:             * @return multi-line string of this beans properties and their values
0105:             */
0106:            public static String printBean(Object source) {
0107:                return printBean(source, null);
0108:            }
0109:
0110:            /**
0111:             * Same as printBean(Object source), except the objectStack lists all the parent
0112:             * objects its printed, and if this is one of them, it stops. This allows detection
0113:             * of possible infinite recusion.
0114:             * @param source Javabean who's contents should be printed
0115:             * @param objectStack List of objects already traversed
0116:             * @return multi-line string of this beans properties and their values
0117:             */
0118:            public static String printBean(Object source, List objectStack) {
0119:                if (source == null)
0120:                    return null;
0121:
0122:                // Prevent infinite object recursion
0123:                if (objectStack != null)
0124:                    if (objectStack.contains(source))
0125:                        return "Object Already Used. "
0126:                                + source.getClass().getName() + "@"
0127:                                + source.hashCode();
0128:                    else
0129:                        objectStack.add(source);
0130:                else {
0131:                    objectStack = new ArrayList();
0132:                    objectStack.add(source);
0133:                }
0134:
0135:                StringBuffer out = new StringBuffer();
0136:                out.append(source.getClass().getName());
0137:                out.append("\n");
0138:
0139:                try {
0140:                    BeanInfo sInfo = Introspector
0141:                            .getBeanInfo(source.getClass());
0142:                    PropertyDescriptor[] sDescriptors = sInfo
0143:                            .getPropertyDescriptors();
0144:                    if (sDescriptors != null && sDescriptors.length != 0)
0145:                        for (int i = 0; i < sDescriptors.length; i++) {
0146:                            PropertyDescriptor sDesc = sDescriptors[i];
0147:                            Method sm = sDesc.getReadMethod();
0148:                            if (sm != null && sDesc.getWriteMethod() != null) {
0149:                                if (!sm.isAccessible())
0150:                                    sm.setAccessible(true);
0151:                                Object sValue = sm.invoke(source, null);
0152:
0153:                                out.append("  ");
0154:                                out.append(sDesc.getName());
0155:                                if (source instanceof  DomainDAO) {
0156:                                    if (((DomainDAO) source).hasChanged(sDesc
0157:                                            .getName()))
0158:                                        out.append("*");
0159:                                }
0160:                                out.append("=");
0161:                                if (sValue == null)
0162:                                    out.append("<--NULL-->\n");
0163:                                else if (sm.getReturnType().isArray()) {
0164:                                    StringBuffer out2 = new StringBuffer();
0165:                                    out2.append("Array of ");
0166:                                    out2.append(sm.getReturnType()
0167:                                            .getComponentType().getName());
0168:                                    out2.append("\n");
0169:                                    // Loop through array
0170:                                    Object[] a = (Object[]) sValue;
0171:                                    for (int j = 0; j < a.length; j++) {
0172:                                        out2.append("[");
0173:                                        out2.append(j);
0174:                                        out2.append("] ");
0175:                                        if (a[j] == null)
0176:                                            out2.append("<--NULL-->");
0177:                                        else if (DomainDAO.class
0178:                                                .isAssignableFrom(a[j]
0179:                                                        .getClass()))
0180:                                            out2.append(((DomainDAO) a[j])
0181:                                                    .toString(objectStack));
0182:                                        else
0183:                                            //out2.append(StringHelper.linePad(a[j].toString(), 4, " ",true));
0184:                                            out2.append(a[j].toString());
0185:                                    }
0186:                                    out.append(StringHelper.linePad(out2
0187:                                            .toString(), 4, " ", true));
0188:                                } else {
0189:                                    if (DomainDAO.class.isAssignableFrom(sValue
0190:                                            .getClass()))
0191:                                        out.append(StringHelper.linePad(
0192:                                                ((DomainDAO) sValue)
0193:                                                        .toString(objectStack),
0194:                                                4, " ", true));
0195:                                    else {
0196:                                        out.append(StringHelper.linePad(sValue
0197:                                                .toString(), 4, " ", true));
0198:                                        out.append("\n");
0199:                                    }
0200:
0201:                                }
0202:                            }
0203:                        }
0204:                } catch (IllegalAccessException e) {
0205:                    MouldException me = new MouldException(
0206:                            MouldException.ACCESS_ERROR, "???", e.getMessage());
0207:                    log.error(me.getLocalizedMessage(), e);
0208:                    //throw me;
0209:                } catch (InvocationTargetException e) {
0210:                    MouldException me = new MouldException(
0211:                            MouldException.INVOCATION_ERROR, "???", e);
0212:                    log.error(me.getLocalizedMessage(), me.getCause());
0213:                    //throw me;
0214:                } catch (IntrospectionException e) {
0215:                    MouldException me = new MouldException(
0216:                            MouldException.INTROSPECT_ERROR, "???", e
0217:                                    .getMessage());
0218:                    log.error(me.getLocalizedMessage(), e);
0219:                    //throw me;
0220:                }
0221:                return out.toString();
0222:            }
0223:
0224:            /**
0225:             * Mould data from domain object and its related objects into a new JavaBean based
0226:             * domain object graph, based on the defined mapping rules.
0227:             *<p>
0228:             * Same as {@link moldFromDomain(Object source, Object target, GraphMapping graph, MappingFilter filter, String objectPath, boolean includeKeys}
0229:             * except the graph is derived from the target object, a default MappingFilter (that
0230:             * just returns fields from the root object) and includeKeys is false.
0231:             * The objectPath is also null, assuming this is the first object in the domain
0232:             * object graph.
0233:             *<p>
0234:             * @param source Source object to mould data from, typically extends Persistent
0235:             * @param target Target object to mould data to, typically extends DomainDAO
0236:             * @throws ApplicationExceptions Thrown if one or more application logic errors are generated during moulding
0237:             * @throws FrameworkException Thrown if any runtime moulding error has occured.
0238:             */
0239:            public static void moldFromDomain(Object source, Object target)
0240:                    throws ApplicationExceptions, FrameworkException {
0241:                moldFromDomain(source, target, null, null, null, false);
0242:            }
0243:
0244:            /**
0245:             * Mould data from domain object and its related objects into a new JavaBean based
0246:             * domain object graph, based on the defined mapping rules.
0247:             *<p>
0248:             * Same as {@link moldFromDomain(Object source, Object target, GraphMapping graph, MappingFilter filter, String objectPath, boolean includeKeys}
0249:             * except the graph is derived from the target object, and includeKeys is false.
0250:             *<p>
0251:             * @param source Source object to mould data from, typically extends Persistent
0252:             * @param target Target object to mould data to, typically extends DomainDAO
0253:             * @param filter Filter object that it is used to control what fields are populated or the target objects
0254:             * @param objectPath  The path of this object being processed. This identifies possible parent
0255:             * and/or indexed entries where this object is contained.
0256:             * @throws ApplicationExceptions Thrown if one or more application logic errors are generated during moulding
0257:             * @throws FrameworkException Thrown if any runtime moulding error has occured.
0258:             */
0259:            public static void moldFromDomain(Object source, Object target,
0260:                    MappingFilter filter, String objectPath)
0261:                    throws ApplicationExceptions, FrameworkException {
0262:                moldFromDomain(source, target, null, filter, objectPath, false);
0263:            }
0264:
0265:            /**
0266:             * Mould data from domain object and its related objects into a new JavaBean based
0267:             * domain object graph, based on the defined mapping rules.
0268:             * @param source Source object to mould data from, typically extends Persistent
0269:             * @param target Target object to mould data to, typically extends DomainDAO
0270:             * @param graph The mapping class with the rules of how to map this source object
0271:             * @param filter Filter object that it is used to control what fields are populated or the target objects
0272:             * @param objectPath  The path of this object being processed. This identifies possible parent
0273:             * and/or indexed entries where this object is contained.
0274:             * @param includeKeys true if key fields should be included in results regardless of the filters
0275:             * @throws ApplicationExceptions Thrown if one or more application logic errors are generated during moulding
0276:             * @throws FrameworkException Thrown if any runtime moulding error has occured.
0277:             */
0278:            public static void moldFromDomain(Object source, Object target,
0279:                    GraphMapping graph, MappingFilter filter,
0280:                    String objectPath, boolean includeKeys)
0281:                    throws ApplicationExceptions, FrameworkException {
0282:                if (graph == null)
0283:                    graph = MappingFactory.getInstance(target);
0284:                //throw new InstantiationException("A GraphMapping must be supplied");
0285:                if (filter == null)
0286:                    filter = new MappingFilter(graph);
0287:
0288:                try {
0289:                    // get list of target fileds to populate
0290:                    String[] tFields = graph.getDataFieldNames();
0291:                    if (tFields != null && tFields.length != 0)
0292:                        for (int i = 0; i < tFields.length; i++) {
0293:                            // Try to map a source to a target
0294:                            String tName = tFields[i];
0295:                            String fullName = tName;
0296:                            if (objectPath != null)
0297:                                fullName = objectPath + "." + fullName;
0298:
0299:                            if (filter == null
0300:                                    || filter.isFieldIncluded(fullName)
0301:                                    || (includeKeys && graph.isKeyField(tName))) {
0302:                                String sName = graph.getDomainFieldName(tName);
0303:                                PropertyDescriptor tDesc = graph
0304:                                        .getDataFieldDescriptor(tName);
0305:                                PropertyDescriptor sDesc = graph
0306:                                        .getDomainFieldDescriptor(tName);
0307:                                // Based on validation in GraphMapping, that there is a
0308:                                // DAO descriptor with a setter, and a DO descriptor with a getter
0309:                                if (sDesc == null)
0310:                                    log.error("No Getter for " + tName
0311:                                            + " in path " + fullName);
0312:
0313:                                // incase getter is not public, make it available
0314:                                Method sm = sDesc.getReadMethod();
0315:                                if (!sm.isAccessible())
0316:                                    sm.setAccessible(true);
0317:
0318:                                // get the setter, and make is available if needed
0319:                                Method tm = tDesc.getWriteMethod();
0320:                                if (!tm.isAccessible())
0321:                                    tm.setAccessible(true);
0322:
0323:                                // Set the value if the source and target are the same datatype
0324:                                Class tClass = tDesc.getPropertyType();
0325:                                Class sClass = sDesc.getPropertyType();
0326:                                if (tClass.isAssignableFrom(sClass)) {
0327:                                    // Get the value being copied
0328:                                    Object sValue = sm.invoke(source, null);
0329:                                    if (sValue != null) {
0330:                                        tm.invoke(target,
0331:                                                new Object[] { sValue });
0332:                                        log.debug("Set " + tName + " = "
0333:                                                + sValue);
0334:                                    } else
0335:                                        log
0336:                                                .debug(tName
0337:                                                        + " no set, NULL value");
0338:
0339:                                    // See if there is a datatype mapper for these classes
0340:                                } else if (DataTypeMapping.isMappable(sClass,
0341:                                        tClass)) {
0342:                                    // Get the value being copied
0343:                                    Object sValue = sm.invoke(source, null);
0344:                                    if (sValue != null) {
0345:                                        sValue = DataTypeMapping.map(sValue,
0346:                                                tClass);
0347:                                        tm.invoke(target,
0348:                                                new Object[] { sValue });
0349:                                        log.debug("Set " + tName + " = "
0350:                                                + sValue);
0351:                                    } else
0352:                                        log
0353:                                                .debug(tName
0354:                                                        + " no set, NULL value");
0355:
0356:                                    // See if target is a DAO, this could be a foreign object or one-to-one relationship...
0357:                                } else if (DomainDAO.class
0358:                                        .isAssignableFrom(tClass)
0359:                                        && IPersistent.class
0360:                                                .isAssignableFrom(sClass)) {
0361:                                    // Get the mapper for the related DAO, if it has keys, it must be a foriegn object
0362:                                    if (graph.isForeignField(tName)) {
0363:                                        // look at foreign key fields, and make sure they are not null
0364:                                        List foreignKeys = graph
0365:                                                .getForeignKeys(tName);
0366:                                        List foreignKeyValues = new ArrayList();
0367:                                        boolean nullKey = false;
0368:                                        for (Iterator k = foreignKeys
0369:                                                .iterator(); k.hasNext();) {
0370:                                            String doProp = (String) k.next();
0371:                                            Object value = null;
0372:                                            PropertyDescriptor doPd = graph
0373:                                                    .getRealDomainFieldDescriptor(doProp);
0374:                                            if (doPd != null
0375:                                                    && doPd.getReadMethod() != null) {
0376:                                                Method m = doPd.getReadMethod();
0377:                                                if (!m.isAccessible())
0378:                                                    m.setAccessible(true);
0379:                                                value = m.invoke(source,
0380:                                                        new Object[] {});
0381:                                                if (value == null)
0382:                                                    nullKey = true;
0383:                                                foreignKeyValues.add(value);
0384:                                            } else {
0385:                                                throw new MouldException(
0386:                                                        MouldException.INVALID_FK_MAPPING,
0387:                                                        objectPath,
0388:                                                        doProp,
0389:                                                        graph
0390:                                                                .getDomainClassShortName());
0391:                                            }
0392:                                        }
0393:                                        if (nullKey) {
0394:                                            log
0395:                                                    .debug("Did not create skeleton object '"
0396:                                                            + tClass.getName()
0397:                                                            + "': one or more foreign key values missing.");
0398:                                        } else {
0399:                                            // Create the foreign object
0400:                                            log
0401:                                                    .debug("Creating foreign object - "
0402:                                                            + tClass.getName());
0403:                                            Object newDAO = newDAO(tClass);
0404:                                            // Only retrieve related domain object and introspect if need
0405:                                            if (filter
0406:                                                    .areSubFieldsIncluded(fullName)) {
0407:                                                // read object and introspect all
0408:                                                log
0409:                                                        .debug("Read foreign object '"
0410:                                                                + fullName
0411:                                                                + "' and mold");
0412:                                                Object sValue = sm.invoke(
0413:                                                        source, null);
0414:                                                if (sValue != null) {
0415:                                                    BeanMoulder.moldFromDomain(
0416:                                                            sValue, newDAO,
0417:                                                            null, filter,
0418:                                                            fullName, true);
0419:                                                } else {
0420:                                                    log
0421:                                                            .warn("All foreign keys present, but read on foreign object returned NULL!");
0422:                                                }
0423:                                            } else {
0424:                                                // just set foreign keys from current object
0425:                                                log
0426:                                                        .debug("Set keys on skeleton foreign object only");
0427:                                                GraphMapping graph2 = MappingFactory
0428:                                                        .getInstance(newDAO);
0429:                                                Set keys = graph2
0430:                                                        .getKeyFields();
0431:                                                if (keys == null
0432:                                                        || keys.size() != foreignKeyValues
0433:                                                                .size()) {
0434:                                                    throw new MouldException(
0435:                                                            MouldException.MISMATCH_FK_MAPPING,
0436:                                                            objectPath, target
0437:                                                                    .getClass()
0438:                                                                    .getName(),
0439:                                                            newDAO.getClass()
0440:                                                                    .getName());
0441:                                                }
0442:                                                int k2 = 0;
0443:                                                // Look through al the foreign keys on the skeleton object
0444:                                                for (Iterator k = keys
0445:                                                        .iterator(); k
0446:                                                        .hasNext(); k2++) {
0447:                                                    String keyField = (String) k
0448:                                                            .next();
0449:                                                    Object keyValue = foreignKeyValues
0450:                                                            .get(k2);
0451:                                                    PropertyDescriptor pd = graph2
0452:                                                            .getDataFieldDescriptor(keyField);
0453:                                                    if (pd != null
0454:                                                            && pd
0455:                                                                    .getWriteMethod() != null) {
0456:                                                        Method m = pd
0457:                                                                .getWriteMethod();
0458:                                                        if (!m.isAccessible())
0459:                                                            m
0460:                                                                    .setAccessible(true);
0461:                                                        m
0462:                                                                .invoke(
0463:                                                                        newDAO,
0464:                                                                        new Object[] { keyValue });
0465:                                                    } else {
0466:                                                        throw new MouldException(
0467:                                                                MouldException.CANT_SET_KEY_FIELD,
0468:                                                                objectPath,
0469:                                                                keyField,
0470:                                                                newDAO
0471:                                                                        .getClass()
0472:                                                                        .getName());
0473:                                                    }
0474:                                                }
0475:                                            }
0476:                                            tm.invoke(target,
0477:                                                    new Object[] { newDAO });
0478:                                            log.debug("Set " + tName + " = "
0479:                                                    + newDAO);
0480:                                        }
0481:                                    } else {
0482:                                        // This is not a foreign object, must be a related object
0483:                                        if (filter
0484:                                                .areSubFieldsIncluded(fullName)) {
0485:                                            // Create the related object
0486:                                            log
0487:                                                    .debug("Creating One-To-One object - "
0488:                                                            + tClass.getName());
0489:                                            Object newDAO = newDAO(tClass);
0490:                                            // read object and introspect all
0491:                                            log.debug("Read related object '"
0492:                                                    + fullName + "' and mold");
0493:                                            Object sValue = sm.invoke(source,
0494:                                                    null);
0495:                                            if (sValue != null) {
0496:                                                BeanMoulder.moldFromDomain(
0497:                                                        sValue, newDAO, null,
0498:                                                        filter, fullName, true);
0499:                                            } else {
0500:                                                log
0501:                                                        .debug("Related object '"
0502:                                                                + fullName
0503:                                                                + "' not found. Ignore it!");
0504:                                            }
0505:                                            tm.invoke(target,
0506:                                                    new Object[] { newDAO });
0507:                                            log.debug("Set " + tName + " = "
0508:                                                    + newDAO);
0509:                                        } else
0510:                                            log
0511:                                                    .debug("No subfields for object "
0512:                                                            + fullName
0513:                                                            + " included. Object not retrieved");
0514:                                    }//END-related object
0515:
0516:                                    // See if Target may be an array of DAO's
0517:                                } else if (tClass.isArray()
0518:                                        && DomainDAO.class
0519:                                                .isAssignableFrom(tClass
0520:                                                        .getComponentType())
0521:                                        && filter
0522:                                                .areSubFieldsIncluded(fullName)) {
0523:                                    log.debug("Target is an array of DAO's");
0524:                                    log.debug("Read related objects '"
0525:                                            + fullName + "' and mold");
0526:                                    Object sValue = sm.invoke(source, null);
0527:                                    if (sClass.isArray()
0528:                                            && IPersistent.class
0529:                                                    .isAssignableFrom(sClass
0530:                                                            .getComponentType())) {
0531:                                        log
0532:                                                .debug("Source is an array of Persistent Objects");
0533:                                        Object[] sArray = (Object[]) sValue;
0534:                                        if (sArray.length > 0) {
0535:                                            Object[] tArray = (Object[]) Array
0536:                                                    .newInstance(
0537:                                                            tClass
0538:                                                                    .getComponentType(),
0539:                                                            sArray.length);
0540:                                            log
0541:                                                    .debug("Translate Array of Size "
0542:                                                            + sArray.length);
0543:                                            for (int j = 0; j < sArray.length; j++) {
0544:                                                Object newDAO = newDAO(tClass
0545:                                                        .getComponentType());
0546:                                                BeanMoulder.moldFromDomain(
0547:                                                        sArray[j], newDAO,
0548:                                                        null, filter, fullName,
0549:                                                        false);
0550:                                                tArray[j] = newDAO;
0551:                                                log.debug("Add to array [" + j
0552:                                                        + "] : " + newDAO);
0553:                                            }
0554:                                            tm
0555:                                                    .invoke(
0556:                                                            target,
0557:                                                            new Object[] { (Object) tArray });
0558:                                            log.debug("Set Array " + tName);
0559:                                        } else
0560:                                            log
0561:                                                    .debug("Source Array is empty! Do Nothing");
0562:                                    } // source is DO array
0563:
0564:                                    // Error... No way to map property
0565:                                } else {
0566:                                    String err = "Can't Mold Property "
0567:                                            + fullName + " from "
0568:                                            + sClass.getName() + " to "
0569:                                            + tClass.getName();
0570:                                    log.error(err);
0571:                                    throw new RuntimeException(err);
0572:                                }
0573:                            } // is included in filtered fields
0574:                        }
0575:
0576:                    // Clear changed fields on updated DAO
0577:                    if (target != null && target instanceof  DomainDAO)
0578:                        ((DomainDAO) target).clearChanges();
0579:
0580:                } catch (IllegalAccessException e) {
0581:                    MouldException me = new MouldException(
0582:                            MouldException.ACCESS_ERROR, objectPath, e
0583:                                    .getMessage());
0584:                    log.error(me.getLocalizedMessage(), e);
0585:                    throw me;
0586:                } catch (InvocationTargetException e) {
0587:                    if (e.getCause() != null) {
0588:                        if (e.getCause() instanceof  FrameworkException)
0589:                            throw (FrameworkException) e.getCause();
0590:                        if (e.getCause() instanceof  ApplicationExceptions)
0591:                            throw (ApplicationExceptions) e.getCause();
0592:                        if (e.getCause() instanceof  ApplicationException) {
0593:                            ApplicationExceptions aes = new ApplicationExceptions();
0594:                            aes.add((ApplicationException) e.getCause());
0595:                            throw aes;
0596:                        }
0597:                    }
0598:                    MouldException me = new MouldException(
0599:                            MouldException.INVOCATION_ERROR, objectPath, e);
0600:                    log.error(me.getLocalizedMessage(), me.getCause());
0601:                    throw me;
0602:                } catch (InstantiationException e) {
0603:                    MouldException me = new MouldException(
0604:                            MouldException.INSTANTICATION_ERROR, objectPath, e
0605:                                    .getMessage());
0606:                    log.error(me.getLocalizedMessage(), e);
0607:                    throw me;
0608:                }
0609:            }
0610:
0611:            private static Object newDAO(Class clazz)
0612:                    throws InstantiationException {
0613:                try {
0614:                    Constructor c = clazz.getConstructor(new Class[] {});
0615:                    if (c == null)
0616:                        throw new InstantiationException(
0617:                                "No zero argument construtor found");
0618:                    Object dao = c.newInstance((Object[]) null);
0619:                    log.debug("Created Object : " + dao);
0620:                    return dao;
0621:                } catch (InstantiationException e) {
0622:                    throw e;
0623:                } catch (Exception e) {
0624:                    log.error("Can't create DAO object - " + e.getMessage(), e);
0625:                    throw new InstantiationException(e.getMessage());
0626:                }
0627:            }
0628:
0629:            /**
0630:             * Take a source object and try and mold it back it its domain object
0631:             * @param path The path of this object being processed. This identifies possible parent
0632:             * and/or indexed entries where this object is contained.
0633:             * @param source Source object to mould from, typically a DomainDAO
0634:             * @param uow Transaction handle all creates/update will be performed within.
0635:             * Throws an exception if null.
0636:             * @param handler Possible bean handler to be used when processing this source object graph
0637:             * @throws ApplicationExceptions Thrown if one or more application logic errors are generated during moulding
0638:             * @throws FrameworkException Thrown if any runtime moulding error has occured.
0639:             */
0640:            public static void updateBean(String path, DomainDAO source,
0641:                    UOW uow, MouldHandler handler)
0642:                    throws ApplicationExceptions, FrameworkException {
0643:                log.debug("Update Bean " + path);
0644:                // Call custom validation code in the DAO
0645:                source.validate();
0646:                ApplicationExceptions aes = new ApplicationExceptions();
0647:                if (uow == null) {
0648:                    String err = "UOW Required";
0649:                    log.error(err);
0650:                    throw new RuntimeException(err);
0651:                }
0652:
0653:                try {
0654:                    IPersistent domainObject = null;
0655:                    GraphMapping mapping = MappingFactory.getInstance(source);
0656:                    Map keys = new LinkedHashMap();
0657:                    Class doClass = mapping.getDomainClass();
0658:
0659:                    // Get the key fields used in the domain object
0660:                    boolean gotKeys = fillInKeys(path, source, mapping, keys);
0661:
0662:                    // read DO based on key
0663:                    if (gotKeys) {
0664:                        // get the method on the DO to read via PK
0665:                        Method[] ma = doClass.getMethods();
0666:                        Method findByPK = null;
0667:                        for (int i = 0; i < ma.length; i++) {
0668:                            if (ma[i].getName().equals("findByPK")) {
0669:                                if (ma[i].getParameterTypes().length == (keys
0670:                                        .size() + 1)
0671:                                        && (ma[i].getParameterTypes())[0] == UOW.class) {
0672:                                    // Found with name and correct no. of input params
0673:                                    findByPK = ma[i];
0674:                                    break;
0675:                                }
0676:                            }
0677:                        }
0678:                        if (findByPK == null) {
0679:                            aes.add(new DomainObjectNotFoundException(doClass
0680:                                    .getName()
0681:                                    + " @ " + path));
0682:                            throw aes;
0683:                        }
0684:
0685:                        // Build input array
0686:                        Object[] inputs = new Object[keys.size() + 1];
0687:                        {
0688:                            inputs[0] = uow;
0689:                            int i = 1;
0690:                            for (Iterator it = keys.values().iterator(); it
0691:                                    .hasNext(); i++) {
0692:                                inputs[i] = it.next();
0693:                            }
0694:                        }
0695:
0696:                        // Find Object based on key
0697:                        domainObject = (IPersistent) findByPK.invoke(null,
0698:                                inputs);
0699:
0700:                    } else
0701:                        log
0702:                                .debug("Object "
0703:                                        + path
0704:                                        + " has either missing or null key values - Assume Create is needed");
0705:
0706:                    // Create object if not found
0707:                    if (domainObject == null) {
0708:                        // NEW OBJECT, create and reflect keys
0709:                        log.debug("DO '" + mapping.getDomainClassShortName()
0710:                                + "' not found with key, create a new one...");
0711:                        domainObject = (IPersistent) doClass.newInstance();
0712:                        // set the key fields
0713:                        for (Iterator it = keys.keySet().iterator(); it
0714:                                .hasNext();) {
0715:                            String keyField = (String) it.next();
0716:                            Object value = keys.get(keyField);
0717:                            updateProperty(mapping
0718:                                    .getDomainFieldDescriptor(keyField), value,
0719:                                    domainObject);
0720:                        }
0721:                    } else {
0722:                        log.debug("Found DO '"
0723:                                + mapping.getDomainClassShortName()
0724:                                + "' with key,");
0725:                    }
0726:
0727:                    // Now update all domain fields
0728:                    updateBeanData(path, source, uow, handler, mapping,
0729:                            domainObject);
0730:
0731:                } catch (IllegalAccessException e) {
0732:                    MouldException me = new MouldException(
0733:                            MouldException.ACCESS_ERROR, path, e.getMessage());
0734:                    log.error(me.getLocalizedMessage(), e);
0735:                    throw me;
0736:                } catch (InvocationTargetException e) {
0737:                    if (e.getCause() != null) {
0738:                        if (e.getCause() instanceof  FrameworkException)
0739:                            throw (FrameworkException) e.getCause();
0740:                        if (e.getCause() instanceof  ApplicationExceptions)
0741:                            throw (ApplicationExceptions) e.getCause();
0742:                        if (e.getCause() instanceof  ApplicationException) {
0743:                            aes.add((ApplicationException) e.getCause());
0744:                            throw aes;
0745:                        }
0746:                    }
0747:                    MouldException me = new MouldException(
0748:                            MouldException.INVOCATION_ERROR, path, e);
0749:                    log.error(me.getLocalizedMessage(), me.getCause());
0750:                    throw me;
0751:                } catch (InstantiationException e) {
0752:                    MouldException me = new MouldException(
0753:                            MouldException.INSTANTICATION_ERROR, path, e
0754:                                    .getMessage());
0755:                    log.error(me.getLocalizedMessage(), e);
0756:                    throw me;
0757:                }
0758:            }
0759:
0760:            /**
0761:             * Take a source object and delete it or delete is children if it has any
0762:             * @param path The path of this object being processed. This identifies possible parent
0763:             * and/or indexed entries where this object is contained.
0764:             * @param source Source object to mould from, typically a DomainDAO
0765:             * @param uow Transaction handle all creates/update will be performed within.
0766:             * Throws an exception if null.
0767:             * @param handler Possible bean handler to be used when processing this source object graph
0768:             * @throws ApplicationExceptions Thrown if one or more application logic errors are generated during moulding
0769:             * @throws FrameworkException Thrown if any runtime moulding error has occured.
0770:             */
0771:            public static void deleteBean(String path, DomainDAO source,
0772:                    UOW uow, MouldHandler handler)
0773:                    throws ApplicationExceptions, FrameworkException {
0774:                log.debug("Delete Bean " + path);
0775:                // Call custom validation code in the DAO
0776:                source.validate();
0777:                ApplicationExceptions aes = new ApplicationExceptions();
0778:                if (uow == null) {
0779:                    String err = "UOW Required";
0780:                    log.error(err);
0781:                    throw new RuntimeException(err);
0782:                }
0783:
0784:                try {
0785:                    IPersistent domainObject = null;
0786:                    GraphMapping mapping = MappingFactory.getInstance(source);
0787:                    Map keys = new LinkedHashMap();
0788:                    Class doClass = mapping.getDomainClass();
0789:
0790:                    // Get the key fields used in the domain object
0791:                    boolean gotKeys = fillInKeys(path, source, mapping, keys);
0792:
0793:                    //----------------------------------------------------------------
0794:                    // read DO based on key
0795:                    if (gotKeys) {
0796:                        // get the method on the DO to read via PK
0797:                        Method[] ma = doClass.getMethods();
0798:                        Method findByPK = null;
0799:                        for (int i = 0; i < ma.length; i++) {
0800:                            if (ma[i].getName().equals("findByPK")) {
0801:                                if (ma[i].getParameterTypes().length == (keys
0802:                                        .size() + 1)
0803:                                        && (ma[i].getParameterTypes())[0] == UOW.class) {
0804:                                    // Found with name and correct no. of input params
0805:                                    findByPK = ma[i];
0806:                                    break;
0807:                                }
0808:                            }
0809:                        }
0810:                        if (findByPK == null) {
0811:                            aes.add(new DomainObjectNotFoundException(doClass
0812:                                    .getName()));
0813:                            throw aes;
0814:                        }
0815:
0816:                        // Build input array
0817:                        Object[] inputs = new Object[keys.size() + 1];
0818:                        {
0819:                            inputs[0] = uow;
0820:                            int i = 1;
0821:                            for (Iterator it = keys.values().iterator(); it
0822:                                    .hasNext(); i++) {
0823:                                inputs[i] = it.next();
0824:                            }
0825:                        }
0826:
0827:                        // Find Object based on key
0828:                        domainObject = (IPersistent) findByPK.invoke(null,
0829:                                inputs);
0830:
0831:                    } else
0832:                        log
0833:                                .debug("Object "
0834:                                        + path
0835:                                        + " has either missing or null key values - Assume Create is needed");
0836:                    // Error if DO not found
0837:                    if (domainObject == null) {
0838:                        String label = doClass.getName();
0839:                        // Try and use meta data to get domain objects label
0840:                        try {
0841:                            label = PersistentHelper.getLabelToken(doClass
0842:                                    .getName());
0843:                        } catch (Exception e) {
0844:                            // ignore any problem trying to get the label!
0845:                        }
0846:                        aes.add(new DomainObjectNotFoundException(label
0847:                                + " (path=" + path + ")"));
0848:                        throw aes;
0849:                    }
0850:
0851:                    // Process the delete, either on this DO, or a related DO if there is one
0852:                    deleteBeanData(path, source, uow, handler, mapping,
0853:                            domainObject);
0854:
0855:                } catch (IllegalAccessException e) {
0856:                    MouldException me = new MouldException(
0857:                            MouldException.ACCESS_ERROR, path, e.getMessage());
0858:                    log.error(me.getLocalizedMessage(), e);
0859:                    throw me;
0860:                } catch (InvocationTargetException e) {
0861:                    if (e.getCause() != null) {
0862:                        if (e.getCause() instanceof  FrameworkException)
0863:                            throw (FrameworkException) e.getCause();
0864:                        if (e.getCause() instanceof  ApplicationExceptions)
0865:                            throw (ApplicationExceptions) e.getCause();
0866:                        if (e.getCause() instanceof  ApplicationException) {
0867:                            aes.add((ApplicationException) e.getCause());
0868:                            throw aes;
0869:                        }
0870:                    }
0871:                    MouldException me = new MouldException(
0872:                            MouldException.INVOCATION_ERROR, path, e);
0873:                    log.error(me.getLocalizedMessage(), me.getCause());
0874:                    throw me;
0875:                } catch (InstantiationException e) {
0876:                    MouldException me = new MouldException(
0877:                            MouldException.INSTANTICATION_ERROR, path, e
0878:                                    .getMessage());
0879:                    log.error(me.getLocalizedMessage(), e);
0880:                    throw me;
0881:                }
0882:                //        } catch (Exception e) {
0883:                //            throw handleException(e,aes);
0884:                //        }
0885:            }
0886:
0887:            /** Pass in an emty map and it fills it with Key = Value for the source
0888:             * object. It returns false if one or more key values are null, or if this
0889:             * object has no keys defined
0890:             */
0891:            private static boolean fillInKeys(String path, DomainDAO source,
0892:                    GraphMapping mapping, Map map)
0893:                    throws InvocationTargetException, MouldException {
0894:                try {
0895:                    Set keys = mapping.getKeyFields();
0896:                    boolean nullKey = false;
0897:                    if (keys == null || keys.size() == 0) {
0898:                        log.debug("Object Has No KEYS! - "
0899:                                + source.getClass().getName());
0900:                        return false;
0901:                    }
0902:                    // Loop through all the keys get het the values
0903:                    for (Iterator k = keys.iterator(); k.hasNext();) {
0904:                        String keyField = (String) k.next();
0905:                        PropertyDescriptor pd = mapping
0906:                                .getDataFieldDescriptor(keyField);
0907:                        if (pd != null && pd.getReadMethod() != null) {
0908:                            Method m = pd.getReadMethod();
0909:                            if (!m.isAccessible())
0910:                                m.setAccessible(true);
0911:                            Object value = m.invoke(source, new Object[] {});
0912:                            map.put(keyField, value);
0913:                            log.debug("Key " + keyField + "='" + value
0914:                                    + "' on object '"
0915:                                    + source.getClass().getName() + "'");
0916:                            if (value == null) {
0917:                                nullKey = true;
0918:                            }
0919:                        } else {
0920:                            MouldException me = new MouldException(
0921:                                    MouldException.NO_KEY_ON_OBJECT, path,
0922:                                    keyField, source.getClass().getName());
0923:                            log.error(me.getLocalizedMessage());
0924:                            throw me;
0925:                        }
0926:                    }
0927:                    return !nullKey;
0928:                } catch (IllegalAccessException e) {
0929:                    MouldException me = new MouldException(
0930:                            MouldException.ACCESS_ERROR, path, e.getMessage());
0931:                    log.error(me.getLocalizedMessage(), e);
0932:                    throw me;
0933:                    //        } catch (InvocationTargetException e) {
0934:                    //            MouldException me = new MouldException(MouldException.INVOCATION_ERROR, path, e );
0935:                    //            log.error(me.getLocalizedMessage(),me.getCause());
0936:                    //            throw me;
0937:                }
0938:            }
0939:
0940:            private static void updateBeanData(String path, DomainDAO source,
0941:                    UOW uow, MouldHandler handler, GraphMapping mapping,
0942:                    IPersistent domainObject) throws InstantiationException,
0943:                    IllegalAccessException, InvocationTargetException,
0944:                    ApplicationExceptions, FrameworkException {
0945:
0946:                try {
0947:                    //----------------------------------------------------------------
0948:                    // Fire 'startBean' handler
0949:                    if (handler != null)
0950:                        handler.startBean(path, source, domainObject);
0951:
0952:                    //----------------------------------------------------------------
0953:                    // Reflect all normal fields
0954:                    for (Iterator it = mapping.getFields().iterator(); it
0955:                            .hasNext();) {
0956:                        String field = (String) it.next();
0957:                        if (source.hasChanged(field)) {
0958:                            Object value = getProperty(mapping
0959:                                    .getDataFieldDescriptor(field), source);
0960:                            //if(value!=null)
0961:                            updateProperty(mapping
0962:                                    .getDomainFieldDescriptor(field), value,
0963:                                    domainObject);
0964:                        }
0965:                    }
0966:
0967:                    //----------------------------------------------------------------
0968:                    // Reflect any foreign keys
0969:                    for (Iterator it = mapping.getForeignFields().iterator(); it
0970:                            .hasNext();) {
0971:                        String field = (String) it.next();
0972:                        if (source.hasChanged(field)) {
0973:                            Object value = getProperty(mapping
0974:                                    .getDataFieldDescriptor(field), source);
0975:                            if (value != null) {
0976:                                // need to map foreign keys back
0977:                                List targetKeys = mapping.getForeignKeys(field);
0978:                                GraphMapping fMapping = MappingFactory
0979:                                        .getInstance(mapping
0980:                                                .getDataFieldDescriptor(field)
0981:                                                .getPropertyType());
0982:                                Set sourceKeys = fMapping.getKeyFields();
0983:                                int i = 0;
0984:                                for (Iterator i2 = sourceKeys.iterator(); i2
0985:                                        .hasNext(); i++) {
0986:                                    String sourceFld = (String) i2.next();
0987:                                    String targetFld = (String) targetKeys
0988:                                            .get(i);
0989:                                    log.debug("Copy Foreign Key Field from "
0990:                                            + sourceFld + " to " + targetFld);
0991:                                    Object value2 = getProperty(fMapping
0992:                                            .getDataFieldDescriptor(sourceFld),
0993:                                            value);
0994:                                    updateProperty(
0995:                                            mapping
0996:                                                    .getRealDomainFieldDescriptor(targetFld),
0997:                                            value2, domainObject);
0998:                                }
0999:                            }
1000:                        }
1001:                    }
1002:
1003:                    //----------------------------------------------------------------
1004:                    // Store Record
1005:                    if (domainObject.isDatabaseOccurence()) {
1006:                        log.debug("UOW.Update Domain Object");
1007:                        //----------------------------------------------------------------
1008:                        // Fire 'startBeanUpdate' handler
1009:                        if (handler != null)
1010:                            handler.startBeanUpdate(path, source, domainObject);
1011:                        uow.update(domainObject);
1012:                        //----------------------------------------------------------------
1013:                        // Fire 'endBeanUpdate' handler
1014:                        if (handler != null)
1015:                            handler.endBeanUpdate(path, source, domainObject);
1016:                    } else {
1017:                        log.debug("UOW.Add Domain Object");
1018:                        //----------------------------------------------------------------
1019:                        // Fire 'startBeanAdd' handler
1020:                        if (handler != null)
1021:                            handler.startBeanAdd(path, source, domainObject);
1022:                        uow.add(domainObject);
1023:                        //----------------------------------------------------------------
1024:                        // Fire 'endBeanAdd' handler
1025:                        if (handler != null)
1026:                            handler.endBeanAdd(path, source, domainObject);
1027:                    }
1028:
1029:                    //----------------------------------------------------------------
1030:                    // Reflect any related objects
1031:                    for (Iterator it = mapping.getRelatedFields().iterator(); it
1032:                            .hasNext();) {
1033:                        String field = (String) it.next();
1034:                        if (source.hasChanged(field)) {
1035:                            // Only do the update if the source object was updated!
1036:                            Object value = getProperty(mapping
1037:                                    .getDataFieldDescriptor(field), source);
1038:                            if (value != null) {
1039:                                if (value.getClass().isArray()) {
1040:                                    // The related field is an array of objects (one-to-many)
1041:                                    Object[] values = (Object[]) value;
1042:                                    for (int i = 0; i < values.length; i++) {
1043:                                        DomainDAO dao = (DomainDAO) values[i]; // Assumes its a DAO....what else could it be?
1044:                                        if (dao != null) {
1045:                                            updateChildBean(path + "." + field
1046:                                                    + "[" + i + "]", dao, uow,
1047:                                                    handler, domainObject,
1048:                                                    mapping, field);
1049:                                        }
1050:                                    }
1051:                                } else {
1052:                                    // Or a single Object (one-to-one)
1053:                                    DomainDAO dao = (DomainDAO) value; // Assumes its a DAO....what else could it be?
1054:                                    updateChildBean(path + "." + field, dao,
1055:                                            uow, handler, domainObject,
1056:                                            mapping, field);
1057:                                }
1058:                            }
1059:                        }
1060:                    }
1061:
1062:                    //----------------------------------------------------------------
1063:                    // Fire 'endBean' handler
1064:                    if (handler != null)
1065:                        handler.endBean(path, source, domainObject);
1066:
1067:                } catch (ApplicationException e) {
1068:                    ApplicationExceptions aes = new ApplicationExceptions();
1069:                    aes.add(e);
1070:                    throw aes;
1071:                }
1072:            }
1073:
1074:            /**  Take a source object and try and mold it back it its domain object.
1075:             *  This is the same as updateParent, except from the way it retrieved the
1076:             *  record, and the way it creates a new record.
1077:             */
1078:            private static void updateChildBean(String path, DomainDAO source,
1079:                    UOW uow, MouldHandler handler, IPersistent parentDomain,
1080:                    GraphMapping parentMapping, String parentField)
1081:                    throws ApplicationExceptions, FrameworkException {
1082:
1083:                log.debug("Update Child Bean " + path);
1084:                // Call custom validation code in the DAO
1085:                source.validate();
1086:                ApplicationExceptions aes = new ApplicationExceptions();
1087:                if (uow == null) {
1088:                    String err = "UOW Required";
1089:                    log.error(err);
1090:                    throw new RuntimeException(err);
1091:                }
1092:
1093:                String relationshipName = parentMapping
1094:                        .getDomainFieldName(parentField);
1095:                if (relationshipName.endsWith("Array"))
1096:                    relationshipName = relationshipName.substring(0,
1097:                            relationshipName.length() - 5);
1098:                if (relationshipName.endsWith("Object"))
1099:                    relationshipName = relationshipName.substring(0,
1100:                            relationshipName.length() - 6);
1101:
1102:                try {
1103:
1104:                    IPersistent domainObject = null;
1105:                    GraphMapping mapping = MappingFactory.getInstance(source);
1106:                    Map keys = new LinkedHashMap();
1107:                    Class doClass = mapping.getDomainClass();
1108:                    boolean gotKeys = false;
1109:
1110:                    if (mapping.getKeyFields() == null
1111:                            || mapping.getKeyFields().size() == 0) {
1112:                        // No keys, must be one-to-one
1113:                        log.debug("Find 'one-to-one' object - " + path);
1114:
1115:                        // Just use the getXxxObject method to get the related domain object,
1116:                        // if there is one...
1117:                        domainObject = (IPersistent) getProperty(parentMapping
1118:                                .getDomainFieldDescriptor(parentField),
1119:                                parentDomain);
1120:                        if (domainObject == null)
1121:                            log.debug("Not Found - " + path);
1122:                    } else {
1123:                        // Get the key fields used in the domain object. Use the findXxxxxCriteria() method,
1124:                        // then add the extra fields to the criteria object, to get the unique record.
1125:                        gotKeys = fillInKeys(path, source, mapping, keys);
1126:
1127:                        // read DO based on key
1128:                        if (gotKeys) {
1129:
1130:                            // get the method to get the PK criteria (i.e. public Criteria findVendorSiteCriteria(); )
1131:                            Method findCriteria = null;
1132:                            String methodName = "find"
1133:                                    + StringHelper.getUpper1(relationshipName)
1134:                                    + "Criteria";
1135:                            try {
1136:                                findCriteria = parentDomain.getClass()
1137:                                        .getMethod(methodName, new Class[] {});
1138:                            } catch (NoSuchMethodException e) {
1139:                                log.error("Find method '" + methodName
1140:                                        + "' not found!");
1141:                            }
1142:                            if (findCriteria == null) {
1143:                                throw new MouldException(
1144:                                        MouldException.METHOD_NOT_FOUND, path,
1145:                                        methodName);
1146:                            }
1147:
1148:                            // Find Criteria For Related Object
1149:                            Criteria criteria = (Criteria) findCriteria.invoke(
1150:                                    parentDomain, new Object[] {});
1151:                            // Add extra key info...
1152:                            for (Iterator it = keys.keySet().iterator(); it
1153:                                    .hasNext();) {
1154:                                String keyField = (String) it.next();
1155:                                Object value = keys.get(keyField);
1156:                                keyField = StringHelper.getUpper1(mapping
1157:                                        .getDomainFieldName(keyField));
1158:                                criteria.addCriteria(keyField, value);
1159:                                log.debug(path + "- Add to criteria:"
1160:                                        + keyField + "=" + value);
1161:                            }
1162:                            // See if we get an object :-)
1163:                            Iterator itr = uow.query(criteria).iterator();
1164:                            if (itr.hasNext())
1165:                                domainObject = (IPersistent) itr.next();
1166:                            if (itr.hasNext()) {
1167:                                // Error, multiple objects found
1168:                                MultipleDomainObjectsFoundException m = new MultipleDomainObjectsFoundException(
1169:                                        criteria.getTable() + " @ " + path);
1170:                                aes.add(m);
1171:                                throw aes;
1172:                            }
1173:
1174:                        } else {
1175:                            log
1176:                                    .debug("Object "
1177:                                            + path
1178:                                            + " has either missing or null key values - Assume Create is needed");
1179:                        }
1180:                    }
1181:
1182:                    // Create object if not found
1183:                    if (domainObject == null) {
1184:                        // NEW OBJECT, create and reflect keys
1185:                        log.debug("DO '" + mapping.getDomainClassShortName()
1186:                                + "' not found with key, create a new one...");
1187:                        // find method on parent used to create object
1188:                        Method newObject = null;
1189:                        String methodName = "new"
1190:                                + StringHelper.getUpper1(relationshipName)
1191:                                + "Object";
1192:                        try {
1193:                            newObject = parentDomain.getClass().getMethod(
1194:                                    methodName, new Class[] {});
1195:                        } catch (NoSuchMethodException e) {
1196:                            log.error("Method '" + methodName
1197:                                    + "()' not found!");
1198:                        }
1199:                        if (newObject == null)
1200:                            throw new MouldException(
1201:                                    MouldException.METHOD_NOT_FOUND, path,
1202:                                    methodName);
1203:
1204:                        // Call method to create object
1205:                        domainObject = (IPersistent) newObject.invoke(
1206:                                parentDomain, new Object[] {});
1207:
1208:                        // Set the key fields
1209:                        for (Iterator it = keys.keySet().iterator(); it
1210:                                .hasNext();) {
1211:                            String keyField = (String) it.next();
1212:                            Object value = keys.get(keyField);
1213:                            updateProperty(mapping
1214:                                    .getDomainFieldDescriptor(keyField), value,
1215:                                    domainObject);
1216:                        }
1217:                    } else {
1218:                        log.debug("Found DO '"
1219:                                + mapping.getDomainClassShortName()
1220:                                + "' with key,");
1221:                    }
1222:
1223:                    // Now update all domain fields
1224:                    updateBeanData(path, source, uow, handler, mapping,
1225:                            domainObject);
1226:
1227:                } catch (IllegalAccessException e) {
1228:                    MouldException me = new MouldException(
1229:                            MouldException.ACCESS_ERROR, path, e.getMessage());
1230:                    log.error(me.getLocalizedMessage(), e);
1231:                    throw me;
1232:                } catch (InvocationTargetException e) {
1233:                    if (e.getCause() != null) {
1234:                        if (e.getCause() instanceof  FrameworkException)
1235:                            throw (FrameworkException) e.getCause();
1236:                        if (e.getCause() instanceof  ApplicationExceptions)
1237:                            throw (ApplicationExceptions) e.getCause();
1238:                        if (e.getCause() instanceof  ApplicationException) {
1239:                            aes.add((ApplicationException) e.getCause());
1240:                            throw aes;
1241:                        }
1242:                    }
1243:                    MouldException me = new MouldException(
1244:                            MouldException.INVOCATION_ERROR, path, e);
1245:                    log.error(me.getLocalizedMessage(), me.getCause());
1246:                    throw me;
1247:                } catch (InstantiationException e) {
1248:                    MouldException me = new MouldException(
1249:                            MouldException.INSTANTICATION_ERROR, path, e
1250:                                    .getMessage());
1251:                    log.error(me.getLocalizedMessage(), e);
1252:                    throw me;
1253:                }
1254:            }
1255:
1256:            /**  Take a source object and try and mold it back it its domain object.
1257:             *  This is the same as updateParent, except from the way it retrieved the
1258:             *  record, and the way it creates a new record.
1259:             */
1260:            private static void deleteChildBean(String path, DomainDAO source,
1261:                    UOW uow, MouldHandler handler, IPersistent parentDomain,
1262:                    GraphMapping parentMapping, String parentField)
1263:                    throws ApplicationExceptions, FrameworkException {
1264:
1265:                log.debug("Delete Child Bean " + path);
1266:                // Call custom validation code in the DAO
1267:                source.validate();
1268:                ApplicationExceptions aes = new ApplicationExceptions();
1269:                if (uow == null) {
1270:                    String err = "UOW Required";
1271:                    log.error(err);
1272:                    throw new RuntimeException(err);
1273:                }
1274:
1275:                String relationshipName = parentMapping
1276:                        .getDomainFieldName(parentField);
1277:                if (relationshipName.endsWith("Array"))
1278:                    relationshipName = relationshipName.substring(0,
1279:                            relationshipName.length() - 5);
1280:                if (relationshipName.endsWith("Object"))
1281:                    relationshipName = relationshipName.substring(0,
1282:                            relationshipName.length() - 6);
1283:
1284:                try {
1285:
1286:                    IPersistent domainObject = null;
1287:                    GraphMapping mapping = MappingFactory.getInstance(source);
1288:                    Map keys = new LinkedHashMap();
1289:                    Class doClass = mapping.getDomainClass();
1290:                    boolean gotKeys = false;
1291:
1292:                    if (mapping.getKeyFields() == null
1293:                            || mapping.getKeyFields().size() == 0) {
1294:                        // No keys, must be one-to-one
1295:                        log.debug("Find 'one-to-one' object - " + path);
1296:
1297:                        // Just use the getXxxObject method to get the related domain object,
1298:                        // if there is one...
1299:                        domainObject = (IPersistent) getProperty(parentMapping
1300:                                .getDomainFieldDescriptor(parentField),
1301:                                parentDomain);
1302:                        if (domainObject == null)
1303:                            log.debug("Not Found - " + path);
1304:                    } else {
1305:                        // Get the key fields used in the domain object. Use the findXxxxxCriteria() method,
1306:                        // then add the extra fields to the criteria object, to get the unique record.
1307:                        gotKeys = fillInKeys(path, source, mapping, keys);
1308:
1309:                        // read DO based on key
1310:                        if (gotKeys) {
1311:                            // get the method to get the PK criteria (i.e. public Criteria findVendorSiteCriteria(); )
1312:                            Method findCriteria = null;
1313:                            String methodName = "find"
1314:                                    + StringHelper.getUpper1(relationshipName)
1315:                                    + "Criteria";
1316:                            try {
1317:                                findCriteria = parentDomain.getClass()
1318:                                        .getMethod(methodName, new Class[] {});
1319:                            } catch (NoSuchMethodException e) {
1320:                                log.error("Find method '" + methodName
1321:                                        + "' not found!");
1322:                            }
1323:                            if (findCriteria == null)
1324:                                throw new MouldException(
1325:                                        MouldException.METHOD_NOT_FOUND, path,
1326:                                        methodName);
1327:
1328:                            // Find Criteria For Related Object
1329:                            Criteria criteria = (Criteria) findCriteria.invoke(
1330:                                    parentDomain, new Object[] {});
1331:                            // Add extra key info...
1332:                            for (Iterator it = keys.keySet().iterator(); it
1333:                                    .hasNext();) {
1334:                                String keyField = (String) it.next();
1335:                                Object value = keys.get(keyField);
1336:                                keyField = StringHelper.getUpper1(mapping
1337:                                        .getDomainFieldName(keyField));
1338:                                criteria.addCriteria(keyField, value);
1339:                                log.debug(path + "- Add to criteria:"
1340:                                        + keyField + "=" + value);
1341:                            }
1342:                            // See if we get an object :-)
1343:                            Iterator itr = uow.query(criteria).iterator();
1344:                            if (itr.hasNext())
1345:                                domainObject = (IPersistent) itr.next();
1346:                            if (itr.hasNext()) {
1347:                                // Error, multiple objects found
1348:                                MultipleDomainObjectsFoundException m = new MultipleDomainObjectsFoundException(
1349:                                        criteria.getTable() + " @ " + path);
1350:                                aes.add(m);
1351:                                throw aes;
1352:                            }
1353:                        }
1354:
1355:                    }
1356:                    // Error if DO not found
1357:                    if (domainObject == null) {
1358:                        aes.add(new DomainObjectNotFoundException(doClass
1359:                                .getName()
1360:                                + " @ " + path));
1361:                        throw aes;
1362:                    }
1363:
1364:                    // Process the delete, either on this DO, or a related DO if there is one
1365:                    deleteBeanData(path, source, uow, handler, mapping,
1366:                            domainObject);
1367:
1368:                } catch (IllegalAccessException e) {
1369:                    MouldException me = new MouldException(
1370:                            MouldException.ACCESS_ERROR, path, e.getMessage());
1371:                    log.error(me.getLocalizedMessage(), e);
1372:                    throw me;
1373:                } catch (InvocationTargetException e) {
1374:                    if (e.getCause() != null) {
1375:                        if (e.getCause() instanceof  FrameworkException)
1376:                            throw (FrameworkException) e.getCause();
1377:                        if (e.getCause() instanceof  ApplicationExceptions)
1378:                            throw (ApplicationExceptions) e.getCause();
1379:                        if (e.getCause() instanceof  ApplicationException) {
1380:                            aes.add((ApplicationException) e.getCause());
1381:                            throw aes;
1382:                        }
1383:                    }
1384:                    MouldException me = new MouldException(
1385:                            MouldException.INVOCATION_ERROR, path, e);
1386:                    log.error(me.getLocalizedMessage(), me.getCause());
1387:                    throw me;
1388:                } catch (InstantiationException e) {
1389:                    MouldException me = new MouldException(
1390:                            MouldException.INSTANTICATION_ERROR, path, e
1391:                                    .getMessage());
1392:                    log.error(me.getLocalizedMessage(), e);
1393:                    throw me;
1394:                }
1395:            }
1396:
1397:            private static void deleteBeanData(String path, DomainDAO source,
1398:                    UOW uow, MouldHandler handler, GraphMapping mapping,
1399:                    IPersistent domainObject) throws InstantiationException,
1400:                    IllegalAccessException, InvocationTargetException,
1401:                    ApplicationExceptions, FrameworkException {
1402:                try {
1403:
1404:                    //----------------------------------------------------------------
1405:                    // Fire 'startBean' handler
1406:                    if (handler != null)
1407:                        handler.startBean(path, source, domainObject);
1408:
1409:                    //----------------------------------------------------------------
1410:                    // Now loop through children, if there is one, delete it, and leave parent alone
1411:                    boolean deleteChild = false;
1412:
1413:                    // Reflect any related objects
1414:                    for (Iterator it = mapping.getRelatedFields().iterator(); it
1415:                            .hasNext();) {
1416:                        String field = (String) it.next();
1417:                        if (source.hasChanged(field)) {
1418:                            Object value = getProperty(mapping
1419:                                    .getDataFieldDescriptor(field), source);
1420:                            if (value != null) {
1421:                                if (value.getClass().isArray()) {
1422:                                    // The related field is an array of objects (one-to-many)
1423:                                    Object[] values = (Object[]) value;
1424:                                    for (int i = 0; i < values.length; i++) {
1425:                                        DomainDAO dao = (DomainDAO) values[i]; // Assumes its a DAO....what else could it be?
1426:                                        if (dao != null) {
1427:                                            deleteChild = true;
1428:                                            deleteChildBean(path + "." + field
1429:                                                    + "[" + i + "]", dao, uow,
1430:                                                    handler, domainObject,
1431:                                                    mapping, field);
1432:                                        }
1433:                                    }
1434:                                } else {
1435:                                    // The related field is a single object (one-to-many)
1436:                                    DomainDAO dao = (DomainDAO) value; // Assumes its a DAO....what else could it be?
1437:                                    deleteChild = true;
1438:                                    deleteChildBean(path + "." + field, dao,
1439:                                            uow, handler, domainObject,
1440:                                            mapping, field);
1441:                                }
1442:                            }
1443:                        }
1444:                    }
1445:
1446:                    //----------------------------------------------------------------
1447:                    // Delete this record, as it had no children
1448:                    if (!deleteChild) {
1449:                        log.debug("UOW.Delete Domain Object");
1450:                        // Fire 'startBeanDelete' handler
1451:                        if (handler != null)
1452:                            handler.startBeanDelete(path, source, domainObject);
1453:
1454:                        uow.delete(domainObject);
1455:
1456:                        // Fire 'endBeanDelete' handler
1457:                        if (handler != null)
1458:                            handler.endBeanDelete(path, source, domainObject);
1459:                    }
1460:
1461:                    //----------------------------------------------------------------
1462:                    // Fire 'endBean' handler
1463:                    if (handler != null)
1464:                        handler.endBean(path, source, domainObject);
1465:
1466:                } catch (ApplicationException e) {
1467:                    ApplicationExceptions aes = new ApplicationExceptions();
1468:                    aes.add(e);
1469:                    throw aes;
1470:                }
1471:            }
1472:
1473:            private static void setProperty(PropertyDescriptor pd,
1474:                    Object value, Object source) throws IllegalAccessException,
1475:                    InvocationTargetException, MouldException {
1476:                if (pd != null && pd.getWriteMethod() != null) {
1477:                    Method m = pd.getWriteMethod();
1478:                    if (!m.isAccessible())
1479:                        m.setAccessible(true);
1480:                    Class tClass = m.getParameterTypes()[0];
1481:                    if (value == null
1482:                            || tClass.isAssignableFrom(value.getClass())) {
1483:                        m.invoke(source, new Object[] { value });
1484:                        log.debug("Set property '" + pd.getName() + "=" + value
1485:                                + "' on object '" + source.getClass().getName()
1486:                                + "'");
1487:                    } else if (DataTypeMapping.isMappable(value.getClass(),
1488:                            tClass)) {
1489:                        // See if there is a datatype mapper for these classes
1490:                        value = DataTypeMapping.map(value, tClass);
1491:                        m.invoke(source, new Object[] { value });
1492:                        log.debug("Translate+Set property '" + pd.getName()
1493:                                + "=" + value + "' on object '"
1494:                                + source.getClass().getName() + "'");
1495:                    } else {
1496:                        // Data type mismatch
1497:                        throw new MouldException(
1498:                                MouldException.DATATYPE_MISMATCH, source
1499:                                        .getClass().getName()
1500:                                        + "." + m.getName(), tClass.getName(),
1501:                                value.getClass().getName());
1502:                    }
1503:                } else {
1504:                    MouldException me = new MouldException(
1505:                            MouldException.NO_SETTER, null, pd == null ? "???"
1506:                                    : pd.getName(), source.getClass().getName());
1507:                    log.error(me.getLocalizedMessage());
1508:                    throw me;
1509:                }
1510:            }
1511:
1512:            private static Object getProperty(PropertyDescriptor pd,
1513:                    Object source) throws IllegalAccessException,
1514:                    InvocationTargetException, MouldException {
1515:                if (pd != null && pd.getReadMethod() != null) {
1516:                    Method m = pd.getReadMethod();
1517:                    if (!m.isAccessible())
1518:                        m.setAccessible(true);
1519:                    Object value = m.invoke(source, new Object[] {});
1520:                    log.debug("Get property '" + pd.getName() + "=" + value
1521:                            + "' on object '" + source.getClass().getName()
1522:                            + "'");
1523:                    return value;
1524:                } else {
1525:                    MouldException me = new MouldException(
1526:                            MouldException.NO_GETTER, null, pd == null ? "???"
1527:                                    : pd.getName(), source.getClass().getName());
1528:                    log.error(me.getLocalizedMessage());
1529:                    throw me;
1530:                }
1531:            }
1532:
1533:            /** Set a value on a Bean, if its a persistent bean, try to use an update method first
1534:             * (for v1.0 domain objects), otherwise use the setter (for v1.1 and above).
1535:             */
1536:            private static void updateProperty(PropertyDescriptor pd,
1537:                    Object value, Object source) throws IllegalAccessException,
1538:                    InvocationTargetException, MouldException {
1539:                if (source instanceof  Persistent) {
1540:                    if (pd != null && pd.getWriteMethod() != null) {
1541:                        try {
1542:                            Method m = source.getClass().getMethod(
1543:                                    "update"
1544:                                            + StringHelper.getUpper1(pd
1545:                                                    .getName()),
1546:                                    pd.getWriteMethod().getParameterTypes());
1547:                            if (!m.isAccessible())
1548:                                m.setAccessible(true);
1549:                            Class tClass = m.getParameterTypes()[0];
1550:                            if (value == null
1551:                                    || tClass
1552:                                            .isAssignableFrom(value.getClass())) {
1553:                                m.invoke(source, new Object[] { value });
1554:                                log.debug("Update property '" + pd.getName()
1555:                                        + "=" + value + "' on object '"
1556:                                        + source.getClass().getName() + "'");
1557:                                // See if there is a datatype mapper for these classes
1558:                            } else if (DataTypeMapping.isMappable(value
1559:                                    .getClass(), tClass)) {
1560:                                value = DataTypeMapping.map(value, tClass);
1561:                                m.invoke(source, new Object[] { value });
1562:                                log.debug("Translate+Update property '"
1563:                                        + pd.getName() + "=" + value
1564:                                        + "' on object '"
1565:                                        + source.getClass().getName() + "'");
1566:                            } else {
1567:                                // Data type mismatch
1568:                                throw new MouldException(
1569:                                        MouldException.DATATYPE_MISMATCH,
1570:                                        source.getClass().getName() + "."
1571:                                                + m.getName(),
1572:                                        tClass.getName(), value.getClass()
1573:                                                .getName());
1574:                            }
1575:                        } catch (NoSuchMethodException e) {
1576:                            log
1577:                                    .debug("No Updator, try Setter for DO property '"
1578:                                            + pd.getName()
1579:                                            + "' on object '"
1580:                                            + source.getClass().getName() + "'");
1581:                            // try to use the setter if there is no update method
1582:                            setProperty(pd, value, source);
1583:                        }
1584:                    } else {
1585:                        MouldException me = new MouldException(
1586:                                MouldException.NO_SETTER, null,
1587:                                pd == null ? "???" : pd.getName(), source
1588:                                        .getClass().getName());
1589:                        log.error(me.getLocalizedMessage());
1590:                        throw me;
1591:                    }
1592:                } else
1593:                    setProperty(pd, value, source);
1594:            }
1595:
1596:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.