Source Code Cross Referenced for AbstractMappingLoader.java in  » Database-ORM » castor » org » exolab » castor » mapping » loader » 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 » Database ORM » castor » org.exolab.castor.mapping.loader 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Redistribution and use of this software and associated documentation
0003:         * ("Software"), with or without modification, are permitted provided
0004:         * that the following conditions are met:
0005:         *
0006:         * 1. Redistributions of source code must retain copyright
0007:         *    statements and notices.  Redistributions must also contain a
0008:         *    copy of this document.
0009:         *
0010:         * 2. Redistributions in binary form must reproduce the
0011:         *    above copyright notice, this list of conditions and the
0012:         *    following disclaimer in the documentation and/or other
0013:         *    materials provided with the distribution.
0014:         *
0015:         * 3. The name "Exolab" must not be used to endorse or promote
0016:         *    products derived from this Software without prior written
0017:         *    permission of Intalio, Inc.  For written permission,
0018:         *    please contact info@exolab.org.
0019:         *
0020:         * 4. Products derived from this Software may not be called "Exolab"
0021:         *    nor may "Exolab" appear in their names without prior written
0022:         *    permission of Intalio, Inc. Exolab is a registered
0023:         *    trademark of Intalio, Inc.
0024:         *
0025:         * 5. Due credit should be given to the Exolab Project
0026:         *    (http://www.exolab.org/).
0027:         *
0028:         * THIS SOFTWARE IS PROVIDED BY INTALIO, INC. AND CONTRIBUTORS
0029:         * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
0030:         * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
0031:         * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
0032:         * INTALIO, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
0033:         * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
0034:         * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
0035:         * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
0036:         * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
0037:         * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0038:         * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
0039:         * OF THE POSSIBILITY OF SUCH DAMAGE.
0040:         *
0041:         * Copyright 1999-2003 (C) Intalio, Inc. All Rights Reserved.
0042:         *
0043:         * Portions of this file developed by Keith Visco after Jan 19 2005 are
0044:         * Copyright (C) 2005 Keith Visco. All Rights Reserverd.
0045:         *
0046:         * $Id: AbstractMappingLoader.java 6784 2007-01-29 03:29:17Z ekuns $
0047:         */
0048:        package org.exolab.castor.mapping.loader;
0049:
0050:        import java.io.Serializable;
0051:        import java.lang.reflect.Array;
0052:        import java.lang.reflect.Constructor;
0053:        import java.lang.reflect.Field;
0054:        import java.lang.reflect.Method;
0055:        import java.lang.reflect.Modifier;
0056:        import java.util.ArrayList;
0057:        import java.util.Iterator;
0058:        import java.util.List;
0059:        import java.util.Enumeration;
0060:
0061:        import org.exolab.castor.mapping.ClassDescriptor;
0062:        import org.exolab.castor.mapping.CollectionHandler;
0063:        import org.exolab.castor.mapping.ExtendedFieldHandler;
0064:        import org.exolab.castor.mapping.FieldDescriptor;
0065:        import org.exolab.castor.mapping.FieldHandler;
0066:        import org.exolab.castor.mapping.GeneralizedFieldHandler;
0067:        import org.exolab.castor.mapping.MapItem;
0068:        import org.exolab.castor.mapping.MappingException;
0069:        import org.exolab.castor.mapping.handlers.EnumFieldHandler;
0070:        import org.exolab.castor.mapping.handlers.TransientFieldHandler;
0071:        import org.exolab.castor.mapping.xml.ClassChoice;
0072:        import org.exolab.castor.mapping.xml.MappingRoot;
0073:        import org.exolab.castor.mapping.xml.ClassMapping;
0074:        import org.exolab.castor.mapping.xml.FieldMapping;
0075:
0076:        /**
0077:         * Assists in the construction of descriptors. Can be used as a mapping
0078:         * resolver to the engine. Engines will implement their own mapping
0079:         * scheme typically by extending this class.
0080:         *
0081:         * @author <a href="arkin@intalio.com">Assaf Arkin</a>
0082:         * @author <a href="keith AT kvisco DOT com">Keith Visco</a>
0083:         * @version $Revision: 6784 $ $Date: 2006-04-10 16:39:24 -0600 (Mon, 10 Apr 2006) $
0084:         */
0085:        public abstract class AbstractMappingLoader extends
0086:                AbstractMappingLoader2 {
0087:            //--------------------------------------------------------------------------
0088:
0089:            /** The prefix for the "add" method. */
0090:            private static final String ADD_METHOD_PREFIX = "add";
0091:
0092:            /** The prefix for an enumeration method. */
0093:            private static final String ENUM_METHOD_PREFIX = "enum";
0094:
0095:            /** The prefix for an enumeration method. */
0096:            private static final String ITER_METHOD_PREFIX = "iterate";
0097:
0098:            /** The standard prefix for the getter method. */
0099:            private static final String GET_METHOD_PREFIX = "get";
0100:
0101:            /** The prefix for the "is" method for booleans. */
0102:            private static final String IS_METHOD_PREFIX = "is";
0103:
0104:            /** The standard prefix for the setter method. */
0105:            private static final String SET_METHOD_PREFIX = "set";
0106:
0107:            /** The prefix for the "create" method. */
0108:            private static final String CREATE_METHOD_PREFIX = "create";
0109:
0110:            /** The prefix for the "has" method. */
0111:            private static final String HAS_METHOD_PREFIX = "has";
0112:
0113:            /** The prefix for the "delete" method. */
0114:            private static final String DELETE_METHOD_PREFIX = "delete";
0115:
0116:            /** Empty array of class types used for reflection. */
0117:            protected static final Class[] EMPTY_ARGS = new Class[0];
0118:
0119:            /** The string argument for the valueOf method, used for introspection when searching for
0120:             *  type-safe enumeration style classes. */
0121:            protected static final Class[] STRING_ARG = { String.class };
0122:
0123:            /** Factory method name for type-safe enumerations. */
0124:            protected static final String VALUE_OF = "valueOf";
0125:
0126:            //--------------------------------------------------------------------------
0127:
0128:            /**
0129:             * Constructs a new mapping helper. This constructor is used by a derived class.
0130:             *
0131:             * @param loader The class loader to use, null for the default
0132:             */
0133:            protected AbstractMappingLoader(final ClassLoader loader) {
0134:                super (loader);
0135:            }
0136:
0137:            //--------------------------------------------------------------------------
0138:
0139:            /**
0140:             * {@inheritDoc}
0141:             */
0142:            public final String getSourceType() {
0143:                return "CastorXmlMapping";
0144:            }
0145:
0146:            //--------------------------------------------------------------------------
0147:
0148:            /**
0149:             * Loads the mapping from the specified mapping object if not loaded previously.
0150:             *
0151:             * @param mapping The mapping information.
0152:             * @param param Arbitrary parameter that can be used by subclasses.
0153:             * @throws MappingException The mapping file is invalid.
0154:             */
0155:            public abstract void loadMapping(final MappingRoot mapping,
0156:                    final Object param) throws MappingException;
0157:
0158:            protected final void createClassDescriptors(
0159:                    final MappingRoot mapping) throws MappingException {
0160:                // Load the mapping for all the classes. This is always returned
0161:                // in the same order as it appeared in the mapping file.
0162:                Enumeration enumeration = mapping.enumerateClassMapping();
0163:
0164:                List retryList = new ArrayList();
0165:                while (enumeration.hasMoreElements()) {
0166:                    ClassMapping clsMap = (ClassMapping) enumeration
0167:                            .nextElement();
0168:                    try {
0169:                        ClassDescriptor clsDesc = createClassDescriptor(clsMap);
0170:                        if (clsDesc != null) {
0171:                            addDescriptor(clsDesc);
0172:                        }
0173:                    } catch (MappingException mx) {
0174:                        // save for later for possible out-of-order mapping files...
0175:                        retryList.add(clsMap);
0176:                        continue;
0177:                    }
0178:                }
0179:
0180:                // handle possible retries, for now we only loop once on the retries, but we
0181:                // should change this to keep looping until we have no more success rate.
0182:                for (Iterator i = retryList.iterator(); i.hasNext();) {
0183:                    ClassMapping clsMap = (ClassMapping) i.next();
0184:                    ClassDescriptor clsDesc = createClassDescriptor(clsMap);
0185:                    if (clsDesc != null) {
0186:                        addDescriptor(clsDesc);
0187:                    }
0188:                }
0189:
0190:                // iterate over all class descriptors and resolve relations between them
0191:                for (Iterator i = descriptorIterator(); i.hasNext();) {
0192:                    resolveRelations((ClassDescriptor) i.next());
0193:                }
0194:            }
0195:
0196:            protected abstract ClassDescriptor createClassDescriptor(
0197:                    final ClassMapping clsMap) throws MappingException;
0198:
0199:            /**
0200:             * Gets the ClassDescriptor the given <code>classMapping</code> extends.
0201:             *
0202:             * @param clsMap The ClassMapping to find the required descriptor for.
0203:             * @param javaClass The name of the class that is checked (this is used for
0204:             *        generating the exception).
0205:             * @return The ClassDescriptor the given ClassMapping extends or
0206:             *         <code>null</code> if the given ClassMapping does not extend
0207:             *         any.
0208:             * @throws MappingException If the given ClassMapping extends another
0209:             *         ClassMapping but its descriptor could not be found.
0210:             */
0211:            protected final ClassDescriptor getExtended(
0212:                    final ClassMapping clsMap, final Class javaClass)
0213:                    throws MappingException {
0214:                if (clsMap.getExtends() == null) {
0215:                    return null;
0216:                }
0217:
0218:                ClassMapping mapping = (ClassMapping) clsMap.getExtends();
0219:                Class type = resolveType(mapping.getName());
0220:                ClassDescriptor result = getDescriptor(type.getName());
0221:
0222:                if (result == null) {
0223:                    throw new MappingException("mapping.extendsMissing",
0224:                            mapping, javaClass.getName());
0225:                }
0226:
0227:                if (!result.getJavaClass().isAssignableFrom(javaClass)) {
0228:                    throw new MappingException("mapping.classDoesNotExtend",
0229:                            javaClass.getName(), result.getJavaClass()
0230:                                    .getName());
0231:                }
0232:
0233:                return result;
0234:            }
0235:
0236:            /**
0237:             * Gets the ClassDescriptor the given <code>classMapping</code> depends
0238:             * on.
0239:             *
0240:             * @param clsMap The ClassMapping to find the required ClassDescriptor for.
0241:             * @param javaClass The name of the class that is checked (this is used for
0242:             *        generating the exception).
0243:             * @return The ClassDescriptor the given ClassMapping depends on or
0244:             *         <code>null</code> if the given ClassMapping does not depend on
0245:             *         any.
0246:             * @throws MappingException If the given ClassMapping depends on another
0247:             *         ClassMapping but its descriptor could not be found.
0248:             */
0249:            protected final ClassDescriptor getDepended(
0250:                    final ClassMapping clsMap, final Class javaClass)
0251:                    throws MappingException {
0252:                if (clsMap.getDepends() == null) {
0253:                    return null;
0254:                }
0255:
0256:                ClassMapping mapping = (ClassMapping) clsMap.getDepends();
0257:                Class type = resolveType(mapping.getName());
0258:                ClassDescriptor result = getDescriptor(type.getName());
0259:
0260:                if (result == null) {
0261:                    throw new MappingException("Depends not found: " + mapping
0262:                            + " " + javaClass.getName());
0263:                }
0264:
0265:                return result;
0266:            }
0267:
0268:            /**
0269:             * Checks all given fields for name equality and throws a MappingException if at
0270:             * least two fields have the same name.
0271:             *
0272:             * @param fields The fields to be checked.
0273:             * @param cls Class that is checked (this is used for generating the exception).
0274:             * @throws MappingException If at least two fields have the same name.
0275:             */
0276:            protected final void checkFieldNameDuplicates(
0277:                    final FieldDescriptor[] fields, final Class cls)
0278:                    throws MappingException {
0279:                for (int i = 0; i < fields.length - 1; i++) {
0280:                    String fieldName = fields[i].getFieldName();
0281:                    for (int j = i + 1; j < fields.length; j++) {
0282:                        if (fieldName.equals(fields[j].getFieldName())) {
0283:                            throw new MappingException("The field " + fieldName
0284:                                    + " appears twice in the descriptor for "
0285:                                    + cls.getName());
0286:                        }
0287:                    }
0288:                }
0289:            }
0290:
0291:            protected abstract void resolveRelations(
0292:                    final ClassDescriptor clsDesc);
0293:
0294:            //--------------------------------------------------------------------------
0295:
0296:            /**
0297:             * Returns the Java class for the named type. The type name can be one of the
0298:             * accepted short names (e.g. <tt>integer</tt>) or the full Java class name (e.g.
0299:             * <tt>java.lang.Integer</tt>). If the short name is used, the primitive type might
0300:             * be returned.
0301:             */
0302:            protected final Class resolveType(final String typeName)
0303:                    throws MappingException {
0304:                try {
0305:                    return Types.typeFromName(getClassLoader(), typeName);
0306:                } catch (ClassNotFoundException ex) {
0307:                    throw new MappingException("mapping.classNotFound",
0308:                            typeName);
0309:                }
0310:            }
0311:
0312:            /**
0313:             * Create field descriptors. The class mapping information is used to create
0314:             * descriptors for all the fields in the class, except for container fields.
0315:             * Implementations may extend this method to create more suitable descriptors, or
0316:             * create descriptors only for a subset of the fields.
0317:             *
0318:             * @param clsMap The class to which the fields belong.
0319:             * @param javaClass The field mappings.
0320:             * @throws MappingException An exception indicating why mapping for the class cannot
0321:             *         be created.
0322:             */
0323:            protected final AbstractFieldDescriptor[] createFieldDescriptors(
0324:                    final ClassMapping clsMap, final Class javaClass)
0325:                    throws MappingException {
0326:                FieldMapping[] fldMap = null;
0327:
0328:                if (clsMap.getClassChoice() != null) {
0329:                    fldMap = clsMap.getClassChoice().getFieldMapping();
0330:                }
0331:
0332:                if ((fldMap == null) || (fldMap.length == 0)) {
0333:                    return new AbstractFieldDescriptor[0];
0334:                }
0335:
0336:                AbstractFieldDescriptor[] fields = new AbstractFieldDescriptor[fldMap.length];
0337:                for (int i = 0; i < fldMap.length; i++) {
0338:                    fields[i] = createFieldDesc(javaClass, fldMap[i]);
0339:
0340:                    // set identity flag
0341:                    fields[i].setIdentity(fldMap[i].getIdentity());
0342:                }
0343:
0344:                return fields;
0345:            }
0346:
0347:            /**
0348:             * Gets the top-most (i.e. without any further 'extends') extends of the given
0349:             * <code>classMapping</code>.
0350:             *
0351:             * @param clsMap The ClassMapping to get the origin for.
0352:             * @return The top-most extends of the given ClassMapping or the ClassMapping itself
0353:             *         if it does not extend any other ClassMapping.
0354:             */
0355:            protected final ClassMapping getOrigin(final ClassMapping clsMap) {
0356:                ClassMapping result = clsMap;
0357:
0358:                while (result.getExtends() != null) {
0359:                    result = (ClassMapping) result.getExtends();
0360:                }
0361:
0362:                return result;
0363:            }
0364:
0365:            protected final FieldDescriptor[] divideFieldDescriptors(
0366:                    final FieldDescriptor[] fields, final String[] ids,
0367:                    final FieldDescriptor[] identities) {
0368:                List fieldList = new ArrayList(fields.length);
0369:
0370:                for (int i = 0; i < fields.length; i++) {
0371:                    FieldDescriptor field = fields[i];
0372:                    final int index = getIdColumnIndex(field, ids);
0373:                    if (index == -1) {
0374:                        // copy non identity field from list of fields.
0375:                        fieldList.add(field);
0376:                    } else {
0377:                        if (field instanceof  FieldDescriptorImpl) {
0378:                            ((FieldDescriptorImpl) field).setRequired(true);
0379:                        }
0380:                        if (field.getHandler() instanceof  FieldHandlerImpl) {
0381:                            ((FieldHandlerImpl) field.getHandler())
0382:                                    .setRequired(true);
0383:                        }
0384:
0385:                        identities[index] = field;
0386:                    }
0387:                }
0388:
0389:                // convert regularFieldList into array
0390:                FieldDescriptor[] result = new FieldDescriptor[fieldList.size()];
0391:                return (FieldDescriptor[]) fieldList.toArray(result);
0392:            }
0393:
0394:            /**
0395:             * Finds the index in the given <code>idColumnNames</code> that has the same name as
0396:             * the given <code>field</code>.
0397:             *
0398:             * @param field The FieldDescriptor to find the column index for.
0399:             * @param ids The id columnNames available.
0400:             * @return The index of the id column name that matches the given field's name or
0401:             *         <code>-1</code> if no such id column name exists.
0402:             */
0403:            protected int getIdColumnIndex(FieldDescriptor field, String[] ids) {
0404:                for (int i = 0; i < ids.length; i++) {
0405:                    if (field.getFieldName().equals(ids[i])) {
0406:                        return i;
0407:                    }
0408:                }
0409:                return -1;
0410:            }
0411:
0412:            /**
0413:             * Creates a single field descriptor. The field mapping is used to create a new stock
0414:             * {@link FieldDescriptor}. Implementations may extend this class to create a more
0415:             * suitable descriptor.
0416:             *
0417:             * @param javaClass The class to which the field belongs.
0418:             * @param fieldMap The field mapping information.
0419:             * @return The field descriptor.
0420:             * @throws MappingException The field or its accessor methods are not
0421:             *         found, not accessible, not of the specified type, etc.
0422:             */
0423:            protected AbstractFieldDescriptor createFieldDesc(
0424:                    final Class javaClass, final FieldMapping fieldMap)
0425:                    throws MappingException {
0426:                String fieldName = fieldMap.getName();
0427:
0428:                // If the field type is supplied, grab it and use it to locate the field/accessor.
0429:                Class fieldType = null;
0430:                if (fieldMap.getType() != null) {
0431:                    fieldType = resolveType(fieldMap.getType());
0432:                }
0433:
0434:                // If the field is declared as a collection, grab the collection type as
0435:                // well and use it to locate the field/accessor.
0436:                CollectionHandler colHandler = null;
0437:                if (fieldMap.getCollection() != null) {
0438:                    String colTypeName = fieldMap.getCollection().toString();
0439:                    Class colType = CollectionHandlers
0440:                            .getCollectionType(colTypeName);
0441:                    colHandler = CollectionHandlers.getHandler(colType);
0442:                }
0443:
0444:                TypeInfo typeInfo = getTypeInfo(fieldType, colHandler, fieldMap);
0445:
0446:                ExtendedFieldHandler exfHandler = null;
0447:                FieldHandler handler = null;
0448:
0449:                // Check for user supplied FieldHandler
0450:                if (fieldMap.getHandler() != null) {
0451:                    Class handlerClass = null;
0452:                    handlerClass = resolveType(fieldMap.getHandler());
0453:
0454:                    if (!FieldHandler.class.isAssignableFrom(handlerClass)) {
0455:                        String err = "The class '" + fieldMap.getHandler()
0456:                                + "' must implement "
0457:                                + FieldHandler.class.getName();
0458:                        throw new MappingException(err);
0459:                    }
0460:
0461:                    // Get default constructor to invoke. We can't use the newInstance method
0462:                    // unfortunately becaue FieldHandler overloads this method
0463:                    try {
0464:                        Constructor constructor = handlerClass
0465:                                .getConstructor(new Class[0]);
0466:                        handler = (FieldHandler) constructor
0467:                                .newInstance(new Object[0]);
0468:                    } catch (Exception ex) {
0469:                        String err = "The class '" + handlerClass.getName()
0470:                                + "' must have a default public constructor.";
0471:                        throw new MappingException(err);
0472:                    }
0473:
0474:                    // ExtendedFieldHandler?
0475:                    if (handler instanceof  ExtendedFieldHandler) {
0476:                        exfHandler = (ExtendedFieldHandler) handler;
0477:                    }
0478:
0479:                    // Fix for CastorJDO from Steve Vaughan, CastorJDO requires FieldHandlerImpl
0480:                    // or a ClassCastException will be thrown... [KV 20030131 - also make sure
0481:                    // this new handler doesn't use it's own CollectionHandler otherwise it'll
0482:                    // cause unwanted calls to the getValue method during unmarshalling]
0483:                    colHandler = typeInfo.getCollectionHandler();
0484:                    typeInfo.setCollectionHandler(null);
0485:                    handler = new FieldHandlerImpl(handler, typeInfo);
0486:                    typeInfo.setCollectionHandler(colHandler);
0487:                    // End Castor JDO fix
0488:                }
0489:
0490:                boolean generalized = (exfHandler instanceof  GeneralizedFieldHandler);
0491:
0492:                // If generalized we need to change the fieldType to whatever is specified in the
0493:                // GeneralizedFieldHandler so that the correct getter/setter methods can be found
0494:                if (generalized) {
0495:                    fieldType = ((GeneralizedFieldHandler) exfHandler)
0496:                            .getFieldType();
0497:                }
0498:
0499:                if (generalized || (handler == null)) {
0500:                    // Create TypeInfoRef to get new TypeInfo from call to createFieldHandler
0501:                    FieldHandler custom = handler;
0502:                    TypeInfoReference typeInfoRef = new TypeInfoReference();
0503:                    typeInfoRef.typeInfo = typeInfo;
0504:                    handler = createFieldHandler(javaClass, fieldType,
0505:                            fieldMap, typeInfoRef);
0506:                    if (custom != null) {
0507:                        ((GeneralizedFieldHandler) exfHandler)
0508:                                .setFieldHandler(handler);
0509:                        handler = custom;
0510:                    } else {
0511:                        boolean isTypeSafeEnum = false;
0512:                        // Check for type-safe enum style classes
0513:                        if ((fieldType != null) && !isPrimitive(fieldType)) {
0514:                            if (!hasPublicDefaultConstructor(fieldType)) {
0515:                                Method method = getStaticValueOfMethod(fieldType);
0516:                                if (method != null) {
0517:                                    handler = new EnumFieldHandler(fieldType,
0518:                                            handler, method);
0519:                                    typeInfo.setImmutable(true);
0520:                                    isTypeSafeEnum = true;
0521:                                }
0522:                            }
0523:                        }
0524:                        // Reset proper TypeInfo
0525:                        if (!isTypeSafeEnum) {
0526:                            typeInfo = typeInfoRef.typeInfo;
0527:                        }
0528:                    }
0529:                }
0530:
0531:                FieldDescriptorImpl fieldDesc = new FieldDescriptorImpl(
0532:                        fieldName, typeInfo, handler, fieldMap.getTransient());
0533:
0534:                fieldDesc.setRequired(fieldMap.getRequired());
0535:
0536:                // If we're using an ExtendedFieldHandler we need to set the FieldDescriptor
0537:                if (exfHandler != null) {
0538:                    ((FieldHandlerFriend) exfHandler)
0539:                            .setFieldDescriptor(fieldDesc);
0540:                }
0541:
0542:                return fieldDesc;
0543:            }
0544:
0545:            /**
0546:             * Does the given class has a public default constructor?
0547:             *
0548:             * @param type Class to check for a public default constructor.
0549:             * @return <code>true</code> if class has a public default constructor.
0550:             */
0551:            private boolean hasPublicDefaultConstructor(final Class type) {
0552:                try {
0553:                    Constructor cons = type.getConstructor(EMPTY_ARGS);
0554:                    return Modifier.isPublic(cons.getModifiers());
0555:                } catch (NoSuchMethodException ex) {
0556:                    return false;
0557:                }
0558:            }
0559:
0560:            /**
0561:             * Get static valueOf(String) factory method of given class.
0562:             *
0563:             * @param type Class to check for a static valueOf(String) factory method.
0564:             * @return Static valueOf(String) factory method or <code>null</code> if none could
0565:             *         be found.
0566:             */
0567:            private Method getStaticValueOfMethod(final Class type) {
0568:                try {
0569:                    Method method = type.getMethod(VALUE_OF, STRING_ARG);
0570:                    Class returnType = method.getReturnType();
0571:                    if (returnType == null) {
0572:                        return null;
0573:                    }
0574:                    if (!type.isAssignableFrom(returnType)) {
0575:                        return null;
0576:                    }
0577:                    if (!Modifier.isStatic(method.getModifiers())) {
0578:                        return null;
0579:                    }
0580:                    return method;
0581:                } catch (NoSuchMethodException ex) {
0582:                    return null;
0583:                }
0584:            }
0585:
0586:            /**
0587:             * Creates the FieldHandler for the given FieldMapping.
0588:             *
0589:             * @param javaClass the class type of the parent of the field.
0590:             * @param fldType the Java class type for the field.
0591:             * @param fldMap the field mapping.
0592:             * @return the newly created FieldHandler.
0593:             */
0594:            protected final FieldHandler createFieldHandler(Class javaClass,
0595:                    Class fldType, final FieldMapping fldMap,
0596:                    final TypeInfoReference typeInfoRef)
0597:                    throws MappingException {
0598:                // Prevent introspection of transient fields
0599:                if (fldMap.getTransient()) {
0600:                    return new TransientFieldHandler();
0601:                }
0602:
0603:                Class colType = null;
0604:                CollectionHandler colHandler = null;
0605:                boolean colRequireGetSet = true;
0606:
0607:                String fieldName = fldMap.getName();
0608:
0609:                // If the field is declared as a collection, grab the collection type as
0610:                // well and use it to locate the field/accessor.
0611:                if (fldMap.getCollection() != null) {
0612:                    String colTypeName = fldMap.getCollection().toString();
0613:                    colType = CollectionHandlers.getCollectionType(colTypeName);
0614:                    colHandler = CollectionHandlers.getHandler(colType);
0615:                    colRequireGetSet = CollectionHandlers
0616:                            .isGetSetCollection(colType);
0617:                    if (colType == Object[].class) {
0618:                        if (fldType == null) {
0619:                            String msg = "'type' is a required attribute for field that are "
0620:                                    + "array collections: " + fieldName;
0621:                            throw new MappingException(msg);
0622:                        }
0623:                        Object obj = Array.newInstance(fldType, 0);
0624:                        colType = obj.getClass();
0625:                    }
0626:                }
0627:
0628:                FieldHandlerImpl handler = null;
0629:
0630:                // If get/set methods not specified, use field names to determine them.
0631:                if (fldMap.getDirect()) {
0632:                    // No accessor, map field directly.
0633:                    Field field = findField(javaClass, fieldName,
0634:                            (colType == null ? fldType : colType));
0635:                    if (field == null) {
0636:                        throw new MappingException(
0637:                                "mapping.fieldNotAccessible", fieldName,
0638:                                javaClass.getName());
0639:                    }
0640:                    if (fldType == null) {
0641:                        fldType = field.getType();
0642:                    }
0643:
0644:                    typeInfoRef.typeInfo = getTypeInfo(fldType, colHandler,
0645:                            fldMap);
0646:
0647:                    handler = new FieldHandlerImpl(field, typeInfoRef.typeInfo);
0648:                } else if ((fldMap.getGetMethod() == null)
0649:                        && (fldMap.getSetMethod() == null)) {
0650:                    // If both methods (get/set) are not specified, determine them automatically
0651:                    if (fieldName == null) {
0652:                        throw new MappingException("mapping.missingFieldName",
0653:                                javaClass.getName());
0654:                    }
0655:
0656:                    List getSequence = new ArrayList();
0657:                    List setSequence = new ArrayList();
0658:                    Method getMethod = null;
0659:                    Method setMethod = null;
0660:
0661:                    // Get method normally starts with "get", but may start with "is"
0662:                    // if it's a boolean.
0663:                    try {
0664:                        // Handle nested fields
0665:                        while (true) {
0666:                            int point = fieldName.indexOf('.');
0667:                            if (point < 0) {
0668:                                break;
0669:                            }
0670:
0671:                            String parentField = fieldName.substring(0, point);
0672:
0673:                            // Getter method for parent field
0674:                            String methodName = GET_METHOD_PREFIX
0675:                                    + capitalize(parentField);
0676:                            Method method = javaClass.getMethod(methodName,
0677:                                    (Class[]) null);
0678:                            if (isAbstractOrStatic(method)) {
0679:                                throw new MappingException(
0680:                                        "mapping.accessorNotAccessible",
0681:                                        methodName, javaClass.getName());
0682:                            }
0683:                            getSequence.add(method);
0684:
0685:                            Class nextClass = method.getReturnType();
0686:
0687:                            // Setter method for parent field
0688:                            try {
0689:                                methodName = SET_METHOD_PREFIX
0690:                                        + capitalize(parentField);
0691:                                Class[] types = new Class[] { nextClass };
0692:                                method = javaClass.getMethod(methodName, types);
0693:                                if (isAbstractOrStatic(method)) {
0694:                                    method = null;
0695:                                }
0696:                            } catch (Exception ex) {
0697:                                method = null;
0698:                            }
0699:                            setSequence.add(method);
0700:
0701:                            javaClass = nextClass;
0702:                            fieldName = fieldName.substring(point + 1);
0703:                        }
0704:
0705:                        // Find getter method for actual field
0706:                        String methodName = GET_METHOD_PREFIX
0707:                                + capitalize(fieldName);
0708:                        Class returnType = (colType == null) ? fldType
0709:                                : colType;
0710:                        getMethod = findAccessor(javaClass, methodName,
0711:                                returnType, true);
0712:
0713:                        // If getMethod is null, check for boolean type method prefix
0714:                        if (getMethod == null) {
0715:                            if ((fldType == Boolean.class)
0716:                                    || (fldType == Boolean.TYPE)) {
0717:                                methodName = IS_METHOD_PREFIX
0718:                                        + capitalize(fieldName);
0719:                                getMethod = findAccessor(javaClass, methodName,
0720:                                        returnType, true);
0721:                            }
0722:                        }
0723:                    } catch (MappingException ex) {
0724:                        throw ex;
0725:                    } catch (Exception ex) {
0726:                        // LOG.warn("Unexpected exception", ex);
0727:                    }
0728:
0729:                    if (getMethod == null) {
0730:                        String getAccessor = GET_METHOD_PREFIX
0731:                                + capitalize(fieldName);
0732:                        String isAccessor = IS_METHOD_PREFIX
0733:                                + capitalize(fieldName);
0734:                        throw new MappingException("mapping.accessorNotFound",
0735:                                getAccessor + "/" + isAccessor,
0736:                                (colType == null ? fldType : colType),
0737:                                javaClass.getName());
0738:                    }
0739:
0740:                    if ((fldType == null) && (colType == null)) {
0741:                        fldType = getMethod.getReturnType();
0742:                    }
0743:
0744:                    // We try to locate a set method anyway but complain only if we need one
0745:                    String methodName = SET_METHOD_PREFIX
0746:                            + capitalize(fieldName);
0747:                    setMethod = findAccessor(javaClass, methodName,
0748:                            (colType == null ? fldType : colType), false);
0749:
0750:                    // If we have a collection that need both set and get but we don't have a
0751:                    // set method, we fail
0752:                    if ((setMethod == null) && (colType != null)
0753:                            && colRequireGetSet) {
0754:                        throw new MappingException("mapping.accessorNotFound",
0755:                                methodName, (colType == null ? fldType
0756:                                        : colType), javaClass.getName());
0757:                    }
0758:
0759:                    typeInfoRef.typeInfo = getTypeInfo(fldType, colHandler,
0760:                            fldMap);
0761:
0762:                    fieldName = fldMap.getName();
0763:                    if (fieldName == null) {
0764:                        if (getMethod == null) {
0765:                            fieldName = setMethod.getName();
0766:                        } else {
0767:                            fieldName = getMethod.getName();
0768:                        }
0769:                    }
0770:
0771:                    // Convert method call sequence for nested fields to arrays
0772:                    Method[] getArray = null;
0773:                    Method[] setArray = null;
0774:                    if (getSequence.size() > 0) {
0775:                        getArray = new Method[getSequence.size()];
0776:                        getArray = (Method[]) getSequence.toArray(getArray);
0777:                        setArray = new Method[setSequence.size()];
0778:                        setArray = (Method[]) setSequence.toArray(setArray);
0779:                    }
0780:
0781:                    // Create handler
0782:                    handler = new FieldHandlerImpl(fieldName, getArray,
0783:                            setArray, getMethod, setMethod,
0784:                            typeInfoRef.typeInfo);
0785:
0786:                    if (setMethod != null) {
0787:                        if (setMethod.getName().startsWith(ADD_METHOD_PREFIX)) {
0788:                            handler.setAddMethod(setMethod);
0789:                        }
0790:                    }
0791:                } else {
0792:                    Method getMethod = null;
0793:                    Method setMethod = null;
0794:
0795:                    // First look up the get accessors
0796:                    if (fldMap.getGetMethod() != null) {
0797:                        Class rtype = fldType;
0798:                        if (colType != null) {
0799:                            String methodName = fldMap.getGetMethod();
0800:                            if (methodName.startsWith(ENUM_METHOD_PREFIX)) {
0801:                                // An enumeration method must really return a enumeration.
0802:                                rtype = Enumeration.class;
0803:                            } else if (methodName
0804:                                    .startsWith(ITER_METHOD_PREFIX)) {
0805:                                // An iterator method must really return a iterator.
0806:                                rtype = Iterator.class;
0807:                            } else {
0808:                                rtype = colType;
0809:                            }
0810:                        }
0811:
0812:                        getMethod = findAccessor(javaClass, fldMap
0813:                                .getGetMethod(), rtype, true);
0814:                        if (getMethod == null) {
0815:                            throw new MappingException(
0816:                                    "mapping.accessorNotFound", fldMap
0817:                                            .getGetMethod(), rtype, javaClass
0818:                                            .getName());
0819:                        }
0820:
0821:                        if ((fldType == null) && (colType == null)) {
0822:                            fldType = getMethod.getReturnType();
0823:                        }
0824:                    }
0825:
0826:                    // Second look up the set/add accessor
0827:                    if (fldMap.getSetMethod() != null) {
0828:                        String methodName = fldMap.getSetMethod();
0829:                        Class type = fldType;
0830:                        if (colType != null) {
0831:                            if (!methodName.startsWith(ADD_METHOD_PREFIX)) {
0832:                                type = colType;
0833:                            }
0834:                        }
0835:
0836:                        // Set via constructor?
0837:                        if (methodName.startsWith("%")) {
0838:                            // Validate index value
0839:                            int index = 0;
0840:
0841:                            String temp = methodName.substring(1);
0842:                            try {
0843:                                index = Integer.parseInt(temp);
0844:                            } catch (NumberFormatException ex) {
0845:                                throw new MappingException(
0846:                                        "mapping.invalidParameterIndex", temp);
0847:                            }
0848:
0849:                            if ((index < 1) || (index > 9)) {
0850:                                throw new MappingException(
0851:                                        "mapping.invalidParameterIndex", temp);
0852:                            }
0853:                        } else {
0854:                            setMethod = findAccessor(javaClass, methodName,
0855:                                    type, false);
0856:                            if (setMethod == null) {
0857:                                throw new MappingException(
0858:                                        "mapping.accessorNotFound", methodName,
0859:                                        type, javaClass.getName());
0860:                            }
0861:
0862:                            if (fldType == null) {
0863:                                fldType = setMethod.getParameterTypes()[0];
0864:                            }
0865:                        }
0866:                    }
0867:
0868:                    typeInfoRef.typeInfo = getTypeInfo(fldType, colHandler,
0869:                            fldMap);
0870:
0871:                    fieldName = fldMap.getName();
0872:                    if (fieldName == null) {
0873:                        if (getMethod == null) {
0874:                            fieldName = setMethod.getName();
0875:                        } else {
0876:                            fieldName = getMethod.getName();
0877:                        }
0878:                    }
0879:
0880:                    // Create handler
0881:                    handler = new FieldHandlerImpl(fieldName, null, null,
0882:                            getMethod, setMethod, typeInfoRef.typeInfo);
0883:
0884:                    if (setMethod != null) {
0885:                        if (setMethod.getName().startsWith(ADD_METHOD_PREFIX)) {
0886:                            handler.setAddMethod(setMethod);
0887:                        }
0888:                    }
0889:                }
0890:
0891:                // If there is a create method, add it to the field handler
0892:                String methodName = fldMap.getCreateMethod();
0893:                if (methodName != null) {
0894:                    try {
0895:                        Method method = javaClass.getMethod(methodName,
0896:                                (Class[]) null);
0897:                        handler.setCreateMethod(method);
0898:                    } catch (Exception ex) {
0899:                        throw new MappingException(
0900:                                "mapping.createMethodNotFound", methodName,
0901:                                javaClass.getName());
0902:                    }
0903:                } else if ((fieldName != null) && !Types.isSimpleType(fldType)) {
0904:                    try {
0905:                        methodName = CREATE_METHOD_PREFIX
0906:                                + capitalize(fieldName);
0907:                        Method method = javaClass.getMethod(methodName,
0908:                                (Class[]) null);
0909:                        handler.setCreateMethod(method);
0910:                    } catch (Exception ex) {
0911:                        // LOG.warn ("Unexpected exception", ex);
0912:                    }
0913:                }
0914:
0915:                // If there is an has/delete method, add them to field handler
0916:                if (fieldName != null) {
0917:                    try {
0918:                        methodName = fldMap.getHasMethod();
0919:                        if (methodName == null) {
0920:                            methodName = HAS_METHOD_PREFIX
0921:                                    + capitalize(fieldName);
0922:                        }
0923:                        Method hasMethod = javaClass.getMethod(methodName,
0924:                                (Class[]) null);
0925:
0926:                        if ((hasMethod.getModifiers() & Modifier.STATIC) != 0) {
0927:                            hasMethod = null;
0928:                        }
0929:
0930:                        Method deleteMethod = null;
0931:                        try {
0932:                            methodName = DELETE_METHOD_PREFIX
0933:                                    + capitalize(fieldName);
0934:                            deleteMethod = javaClass.getMethod(methodName,
0935:                                    (Class[]) null);
0936:                            if ((deleteMethod.getModifiers() & Modifier.STATIC) != 0) {
0937:                                deleteMethod = null;
0938:                            }
0939:                        } catch (Exception ex) {
0940:                            // Purposely Ignore exception we're just seeing if the method exists
0941:                        }
0942:
0943:                        handler.setHasDeleteMethod(hasMethod, deleteMethod);
0944:                    } catch (Exception ex) {
0945:                        // LOG.warn("Unexpected exception", ex);
0946:                    }
0947:                }
0948:
0949:                return handler;
0950:            }
0951:
0952:            private static boolean isAbstract(final Class cls) {
0953:                return ((cls.getModifiers() & Modifier.ABSTRACT) != 0);
0954:            }
0955:
0956:            private static boolean isAbstractOrStatic(final Method method) {
0957:                return ((method.getModifiers() & Modifier.ABSTRACT) != 0)
0958:                        || ((method.getModifiers() & Modifier.STATIC) != 0);
0959:            }
0960:
0961:            protected TypeInfo getTypeInfo(final Class fieldType,
0962:                    final CollectionHandler colHandler,
0963:                    final FieldMapping fieldMap) throws MappingException {
0964:                return new TypeInfo(Types.typeFromPrimitive(fieldType), null,
0965:                        null, null, fieldMap.getRequired(), null, colHandler,
0966:                        false);
0967:            }
0968:
0969:            /**
0970:             * Returns the named field. Uses reflection to return the named field and check the
0971:             * field type, if specified.
0972:             *
0973:             * @param javaClass The class to which the field belongs.
0974:             * @param fieldName The name of the field.
0975:             * @param fieldType The type of the field if known, or null.
0976:             * @return The field, null if not found.
0977:             * @throws MappingException The field is not accessible or is not of the
0978:             *         specified type.
0979:             */
0980:            private final Field findField(final Class javaClass,
0981:                    final String fieldName, Class fieldType)
0982:                    throws MappingException {
0983:                try {
0984:                    // Look up the field based on its name, make sure it's only modifier
0985:                    // is public. If a type was specified, match the field type.
0986:                    Field field = javaClass.getField(fieldName);
0987:                    if ((field.getModifiers() != Modifier.PUBLIC)
0988:                            && (field.getModifiers() != (Modifier.PUBLIC | Modifier.VOLATILE))) {
0989:                        throw new MappingException(
0990:                                "mapping.fieldNotAccessible", fieldName,
0991:                                javaClass.getName());
0992:                    }
0993:
0994:                    if (fieldType == null) {
0995:                        fieldType = Types.typeFromPrimitive(field.getType());
0996:                    } else {
0997:                        Class ft1 = Types.typeFromPrimitive(fieldType);
0998:                        Class ft2 = Types.typeFromPrimitive(field.getType());
0999:                        if ((ft1 != ft2) && (fieldType != Serializable.class)) {
1000:                            throw new MappingException(
1001:                                    "mapping.fieldTypeMismatch", field,
1002:                                    fieldType.getName());
1003:                        }
1004:                    }
1005:                    return field;
1006:                } catch (NoSuchFieldException ex) {
1007:                    return null;
1008:                } catch (SecurityException ex) {
1009:                    return null;
1010:                }
1011:            }
1012:
1013:            /**
1014:             * Returns the named accessor. Uses reflection to return the named accessor and
1015:             * check the return value or parameter type, if specified.
1016:             *
1017:             * @param javaClass The class to which the field belongs.
1018:             * @param methodName The name of the accessor method.
1019:             * @param fieldType The type of the field if known, or null.
1020:             * @param getMethod True if get method, false if set method.
1021:             * @return The method, null if not found.
1022:             * @throws MappingException The method is not accessible or is not of the
1023:             *         specified type.
1024:             */
1025:            public static final Method findAccessor(final Class javaClass,
1026:                    final String methodName, Class fieldType,
1027:                    final boolean getMethod) throws MappingException {
1028:                try {
1029:                    Method method = null;
1030:
1031:                    if (getMethod) {
1032:                        // Get method: look for the named method or prepend get to the method
1033:                        // name. Look up the field and potentially check the return type.
1034:                        method = javaClass.getMethod(methodName, new Class[0]);
1035:
1036:                        // The MapItem is used to handle the contents of maps. Since the MapItem
1037:                        // has to use Object for its methods we cannot (but also don't have to)
1038:                        // check for correct types.
1039:                        if (javaClass == MapItem.class) {
1040:                            if (methodName.equals("getKey")) {
1041:                                return method;
1042:                            }
1043:                            if (methodName.equals("getValue")) {
1044:                                return method;
1045:                            }
1046:                        }
1047:
1048:                        if (fieldType == null) {
1049:                            fieldType = Types.typeFromPrimitive(method
1050:                                    .getReturnType());
1051:                        } else {
1052:                            fieldType = Types.typeFromPrimitive(fieldType);
1053:                            Class returnType = Types.typeFromPrimitive(method
1054:                                    .getReturnType());
1055:
1056:                            //-- First check against whether the declared type is
1057:                            //-- an interface or abstract class. We also check
1058:                            //-- type as Serializable for CMP 1.1 compatibility.
1059:                            if (fieldType.isInterface()
1060:                                    || ((fieldType.getModifiers() & Modifier.ABSTRACT) != 0)
1061:                                    || (fieldType == java.io.Serializable.class)) {
1062:
1063:                                if (!fieldType.isAssignableFrom(returnType)) {
1064:                                    throw new MappingException(
1065:                                            "mapping.accessorReturnTypeMismatch",
1066:                                            method, fieldType.getName());
1067:                                }
1068:                            } else {
1069:                                if (!returnType.isAssignableFrom(fieldType)) {
1070:                                    throw new MappingException(
1071:                                            "mapping.accessorReturnTypeMismatch",
1072:                                            method, fieldType.getName());
1073:                                }
1074:                            }
1075:                        }
1076:                    } else {
1077:                        // Set method: look for the named method or prepend set to the method
1078:                        // name. If the field type is know, look up a suitable method. If the
1079:                        // field type is unknown, lookup the first method with that name and
1080:                        // one parameter.
1081:                        Class fieldTypePrimitive = null;
1082:                        if (fieldType != null) {
1083:                            fieldTypePrimitive = Types
1084:                                    .typeFromPrimitive(fieldType);
1085:                            try {
1086:                                method = javaClass.getMethod(methodName,
1087:                                        new Class[] { fieldType });
1088:                            } catch (Exception ex) {
1089:                                try {
1090:                                    method = javaClass.getMethod(methodName,
1091:                                            new Class[] { fieldTypePrimitive });
1092:                                } catch (Exception ex2) {
1093:                                    // LOG.warn("Unexpected exception", ex2);
1094:                                }
1095:                            }
1096:                        }
1097:
1098:                        if (method == null) {
1099:                            Method[] methods = javaClass.getMethods();
1100:                            for (int i = 0; i < methods.length; ++i) {
1101:                                if (methods[i].getName().equals(methodName)) {
1102:                                    Class[] paramTypes = methods[i]
1103:                                            .getParameterTypes();
1104:                                    if (paramTypes.length != 1) {
1105:                                        continue;
1106:                                    }
1107:
1108:                                    Class paramType = Types
1109:                                            .typeFromPrimitive(paramTypes[0]);
1110:
1111:                                    if (fieldType == null) {
1112:                                        method = methods[i];
1113:                                        break;
1114:                                    } else if (paramType
1115:                                            .isAssignableFrom(fieldTypePrimitive)) {
1116:                                        method = methods[i];
1117:                                        break;
1118:                                    } else if (fieldType.isInterface()
1119:                                            || isAbstract(fieldType)) {
1120:                                        if (fieldTypePrimitive
1121:                                                .isAssignableFrom(paramType)) {
1122:                                            method = methods[i];
1123:                                            break;
1124:                                        }
1125:                                    }
1126:                                }
1127:                            }
1128:
1129:                            if (method == null) {
1130:                                return null;
1131:                            }
1132:                        }
1133:                    }
1134:
1135:                    // Make sure method is public and not static.
1136:                    // (note: Class.getMethod() returns only public methods).
1137:                    if ((method.getModifiers() & Modifier.STATIC) != 0) {
1138:                        throw new MappingException(
1139:                                "mapping.accessorNotAccessible", methodName,
1140:                                javaClass.getName());
1141:                    }
1142:                    return method;
1143:                } catch (MappingException ex) {
1144:                    throw ex;
1145:                } catch (Exception ex) {
1146:                    return null;
1147:                }
1148:            }
1149:
1150:            private static final String capitalize(final String name) {
1151:                char first = name.charAt(0);
1152:                if (Character.isUpperCase(first)) {
1153:                    return name;
1154:                }
1155:                return Character.toUpperCase(first) + name.substring(1);
1156:            }
1157:
1158:            /**
1159:             * Returns a list of column names that are part of the identity.
1160:             *
1161:             * @param ids Known identity names.
1162:             * @param clsMap Class mapping.
1163:             * @return List of identity column names.
1164:             */
1165:            public static final String[] getIdentityColumnNames(
1166:                    final String[] ids, final ClassMapping clsMap) {
1167:
1168:                String[] idNames = ids;
1169:
1170:                if ((ids == null) || (ids.length == 0)) {
1171:                    ClassChoice classChoice = clsMap.getClassChoice();
1172:                    if (classChoice == null) {
1173:                        classChoice = new ClassChoice();
1174:                    }
1175:
1176:                    FieldMapping[] fieldMappings = classChoice
1177:                            .getFieldMapping();
1178:
1179:                    List idNamesList = new ArrayList();
1180:                    for (int i = 0; i < fieldMappings.length; i++) {
1181:                        if (fieldMappings[i].getIdentity() == true) {
1182:                            idNamesList.add(fieldMappings[i].getName());
1183:                        }
1184:                    }
1185:
1186:                    if (idNamesList.size() > 0) {
1187:                        idNames = new String[idNamesList.size()];
1188:                        idNames = (String[]) idNamesList.toArray(idNames);
1189:                    }
1190:                }
1191:
1192:                return idNames;
1193:            }
1194:
1195:            /**
1196:             * Returns true if the given class should be treated as a primitive
1197:             * type
1198:             * @return true if the given class should be treated as a primitive
1199:             * type
1200:             */
1201:            protected static final boolean isPrimitive(final Class type) {
1202:                if (type.isPrimitive()) {
1203:                    return true;
1204:                }
1205:                if ((type == Boolean.class) || (type == Character.class)) {
1206:                    return true;
1207:                }
1208:                return (type.getSuperclass() == Number.class);
1209:            }
1210:
1211:            /**
1212:             * A class used to by the createFieldHandler method in order to
1213:             * save the reference of the TypeInfo that was used.
1214:             */
1215:            public class TypeInfoReference {
1216:                public TypeInfo typeInfo = null;
1217:            }
1218:
1219:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.