Source Code Cross Referenced for BaseConfigIntrospector.java in  » EJB-Server-resin-3.1.5 » resin » com » caucho » amber » cfg » 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 » EJB Server resin 3.1.5 » resin » com.caucho.amber.cfg 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
0003:         *
0004:         * This file is part of Resin(R) Open Source
0005:         *
0006:         * Each copy or derived work must preserve the copyright notice and this
0007:         * notice unmodified.
0008:         *
0009:         * Resin Open Source is free software; you can redistribute it and/or modify
0010:         * it under the terms of the GNU General Public License as published by
0011:         * the Free Software Foundation; either version 2 of the License, or
0012:         * (at your option) any later version.
0013:         *
0014:         * Resin Open Source is distributed in the hope that it will be useful,
0015:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
0016:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
0017:         * of NON-INFRINGEMENT.  See the GNU General Public License for more
0018:         * details.
0019:         *
0020:         * You should have received a copy of the GNU General Public License
0021:         * along with Resin Open Source; if not, write to the
0022:         *
0023:         *   Free Software Foundation, Inc.
0024:         *   59 Temple Place, Suite 330
0025:         *   Boston, MA 02111-1307  USA
0026:         *
0027:         * @author Rodrigo Westrupp
0028:         */
0029:
0030:        package com.caucho.amber.cfg;
0031:
0032:        import com.caucho.amber.entity.Listener;
0033:
0034:        import com.caucho.amber.field.*;
0035:        import com.caucho.amber.idgen.IdGenerator;
0036:        import com.caucho.amber.manager.AmberPersistenceUnit;
0037:        import com.caucho.amber.table.Column;
0038:        import com.caucho.amber.table.ForeignColumn;
0039:        import com.caucho.amber.table.LinkColumns;
0040:        import com.caucho.amber.table.Table;
0041:        import com.caucho.amber.type.*;
0042:        import com.caucho.bytecode.*;
0043:        import com.caucho.config.ConfigException;
0044:        import com.caucho.jdbc.JdbcMetaData;
0045:        import com.caucho.util.L10N;
0046:
0047:        import javax.persistence.*;
0048:        import javax.persistence.EmbeddedId;
0049:        import java.sql.SQLException;
0050:        import java.util.ArrayList;
0051:        import java.util.HashMap;
0052:        import java.util.logging.Level;
0053:        import java.util.logging.Logger;
0054:
0055:        /**
0056:         * Base concrete introspector for orm.xml and annotations.
0057:         */
0058:        public class BaseConfigIntrospector extends AbstractConfigIntrospector {
0059:            private static final Logger log = Logger
0060:                    .getLogger(BaseConfigIntrospector.class.getName());
0061:            private static final L10N L = new L10N(BaseConfigIntrospector.class);
0062:
0063:            AmberPersistenceUnit _persistenceUnit;
0064:
0065:            ArrayList<Completion> _linkCompletions = new ArrayList<Completion>();
0066:            ArrayList<Completion> _depCompletions = new ArrayList<Completion>();
0067:
0068:            HashMap<RelatedType, ArrayList<OneToOneCompletion>> _oneToOneCompletions = new HashMap<RelatedType, ArrayList<OneToOneCompletion>>();
0069:
0070:            HashMap<String, EmbeddableConfig> _embeddableConfigMap = new HashMap<String, EmbeddableConfig>();
0071:
0072:            ArrayList<EntityMappingsConfig> _entityMappingsList;
0073:
0074:            // HashMap<String, EntityConfig> _entityConfigMap
0075:            //   = new HashMap<String, EntityConfig>();
0076:            //
0077:            // HashMap<String, MappedSuperclassConfig> _mappedSuperclassConfigMap
0078:            //   = new HashMap<String, MappedSuperclassConfig>();
0079:
0080:            /**
0081:             * Creates the introspector.
0082:             */
0083:            public BaseConfigIntrospector() {
0084:            }
0085:
0086:            /**
0087:             * Creates the introspector.
0088:             */
0089:            public BaseConfigIntrospector(AmberPersistenceUnit persistenceUnit) {
0090:                _persistenceUnit = persistenceUnit;
0091:            }
0092:
0093:            /**
0094:             * Sets the entity mappings list.
0095:             */
0096:            public void setEntityMappingsList(
0097:                    ArrayList<EntityMappingsConfig> entityMappingsList) {
0098:                _entityMappingsList = entityMappingsList;
0099:            }
0100:
0101:            /**
0102:             * Returns the entity config for a class name.
0103:             */
0104:            public EntityConfig getEntityConfig(String className) {
0105:                // jpa/0r41
0106:                if (_entityMappingsList == null)
0107:                    return null;
0108:
0109:                // jpa/0s2l: mapping-file.
0110:
0111:                HashMap<String, EntityConfig> entityMap;
0112:                EntityConfig entityConfig;
0113:
0114:                for (EntityMappingsConfig entityMappings : _entityMappingsList) {
0115:                    entityMap = entityMappings.getEntityMap();
0116:
0117:                    if (entityMap != null) {
0118:                        entityConfig = entityMap.get(className);
0119:
0120:                        if (entityConfig != null)
0121:                            return entityConfig;
0122:                    }
0123:                }
0124:
0125:                return null;
0126:            }
0127:
0128:            /**
0129:             * Returns the mapped superclass config for a class name.
0130:             */
0131:            public MappedSuperclassConfig getMappedSuperclassConfig(
0132:                    String className) {
0133:                if (_entityMappingsList == null)
0134:                    return null;
0135:
0136:                HashMap<String, MappedSuperclassConfig> super classMap;
0137:                MappedSuperclassConfig super classConfig;
0138:
0139:                for (EntityMappingsConfig entityMappings : _entityMappingsList) {
0140:                    super classMap = entityMappings.getMappedSuperclassMap();
0141:
0142:                    if (super classMap != null) {
0143:                        super classConfig = super classMap.get(className);
0144:
0145:                        if (super classConfig != null)
0146:                            return super classConfig;
0147:                    }
0148:                }
0149:
0150:                return null;
0151:            }
0152:
0153:            /**
0154:             * Initializes the persistence unit meta data:
0155:             * default listeners and so on.
0156:             */
0157:            public void initMetaData(
0158:                    ArrayList<EntityMappingsConfig> entityMappingsList,
0159:                    AmberPersistenceUnit persistenceUnit)
0160:                    throws ConfigException {
0161:                PersistenceUnitMetaDataConfig metaData = null;
0162:
0163:                for (EntityMappingsConfig entityMappings : entityMappingsList) {
0164:                    metaData = entityMappings.getPersistenceUnitMetaData();
0165:
0166:                    // It is undefined if this element occurs in multiple mapping
0167:                    // files within the same persistence unit.
0168:                    if (metaData != null)
0169:                        break;
0170:                }
0171:
0172:                if (metaData == null)
0173:                    return;
0174:
0175:                PersistenceUnitDefaultsConfig defaults;
0176:
0177:                defaults = metaData.getPersistenceUnitDefaults();
0178:
0179:                if (defaults == null)
0180:                    return;
0181:
0182:                EntityListenersConfig entityListeners;
0183:                entityListeners = defaults.getEntityListeners();
0184:
0185:                if (entityListeners == null)
0186:                    return;
0187:
0188:                ArrayList<EntityListenerConfig> listeners;
0189:                listeners = entityListeners.getEntityListeners();
0190:
0191:                for (EntityListenerConfig listener : listeners)
0192:                    introspectDefaultListener(listener, persistenceUnit);
0193:            }
0194:
0195:            public void introspectDefaultListener(
0196:                    EntityListenerConfig listener,
0197:                    AmberPersistenceUnit persistenceUnit)
0198:                    throws ConfigException {
0199:                JClassLoader loader = persistenceUnit.getJClassLoader();
0200:
0201:                String className = listener.getClassName();
0202:
0203:                JClass type = loader.forName(className);
0204:
0205:                if (type == null)
0206:                    throw new ConfigException(
0207:                            L
0208:                                    .l(
0209:                                            "'{0}' is an unknown type for <entity-listener> in orm.xml",
0210:                                            className));
0211:
0212:                ListenerType listenerType = persistenceUnit
0213:                        .addDefaultListener(type);
0214:
0215:                introspectListener(type, listenerType);
0216:            }
0217:
0218:            public void introspectEntityListeners(JClass type,
0219:                    RelatedType relatedType,
0220:                    AmberPersistenceUnit persistenceUnit)
0221:                    throws ConfigException {
0222:                getInternalEntityListenersConfig(type, _annotationCfg);
0223:                JAnnotation entityListenersAnn = _annotationCfg.getAnnotation();
0224:                EntityListenersConfig entityListenersCfg = _annotationCfg
0225:                        .getEntityListenersConfig();
0226:
0227:                Object listeners[] = null;
0228:
0229:                // XML mapping takes higher priority than annotations.
0230:                if (entityListenersCfg != null)
0231:                    listeners = entityListenersCfg.getEntityListeners()
0232:                            .toArray();
0233:                else if (entityListenersAnn != null)
0234:                    listeners = (Object[]) entityListenersAnn.get("value");
0235:                else
0236:                    return;
0237:
0238:                String relatedTypeName = relatedType.getBeanClass().getName();
0239:
0240:                for (int i = 0; i < listeners.length; i++) {
0241:
0242:                    JClass cl;
0243:
0244:                    // Introspects annotation or xml.
0245:                    if (listeners[i] instanceof  JClass)
0246:                        cl = (JClass) listeners[i];
0247:                    else {
0248:                        JClassLoader loader = persistenceUnit.getJClassLoader();
0249:
0250:                        EntityListenerConfig listenerConfig = (EntityListenerConfig) listeners[i];
0251:
0252:                        String className = listenerConfig.getClassName();
0253:
0254:                        cl = loader.forName(className);
0255:
0256:                        if (cl == null)
0257:                            throw new ConfigException(
0258:                                    L
0259:                                            .l(
0260:                                                    "'{0}' is an unknown type for <entity-listener> in orm.xml",
0261:                                                    className));
0262:                    }
0263:
0264:                    if (persistenceUnit.getDefaultListener(cl.getName()) != null)
0265:                        continue;
0266:
0267:                    introspectEntityListener(cl, persistenceUnit, relatedType,
0268:                            relatedTypeName);
0269:                }
0270:            }
0271:
0272:            public void introspectEntityListener(JClass type,
0273:                    AmberPersistenceUnit persistenceUnit,
0274:                    RelatedType sourceType, String sourceClassName)
0275:                    throws ConfigException {
0276:                if (type == null) {
0277:                    throw new ConfigException(
0278:                            L
0279:                                    .l(
0280:                                            "'{0}' is an unknown type for @EntityListeners annotated at class '{1}'",
0281:                                            type.getName(), sourceClassName));
0282:                }
0283:
0284:                JClass parentClass = type.getSuperClass();
0285:
0286:                if (parentClass == null) {
0287:                    // java.lang.Object
0288:                    return;
0289:                }
0290:                /*
0291:                else {
0292:                  // XXX: entity listener super-classes in a hierarchy might
0293:                  // not be annotated as entity listeners but they might have
0294:                  // @PreXxx or @PostXxx annotated methods. On the other hand,
0295:                  // needs to filter regular classes out.
0296:
0297:                  introspectEntityListener(parentClass, persistenceUnit,
0298:                                           sourceType, sourceClassName);
0299:                }
0300:                 */
0301:
0302:                // jpa/0r42
0303:                ListenerType listenerType = persistenceUnit
0304:                        .getEntityListener(type.getName());
0305:
0306:                ListenerType newListenerType = persistenceUnit
0307:                        .addEntityListener(sourceClassName, type);
0308:
0309:                if (listenerType == null) {
0310:                    listenerType = newListenerType;
0311:                    introspectListener(type, listenerType);
0312:                }
0313:
0314:                sourceType.addListener(listenerType);
0315:            }
0316:
0317:            public void introspectListener(JClass type,
0318:                    ListenerType listenerType) throws ConfigException {
0319:                listenerType.setInstanceClassName(listenerType.getName()
0320:                        + "__ResinExt");
0321:
0322:                for (JMethod method : type.getMethods()) {
0323:                    introspectCallbacks(listenerType, method);
0324:                }
0325:            }
0326:
0327:            /**
0328:             * Introspects the callbacks.
0329:             */
0330:            public void introspectCallbacks(JClass type, RelatedType entityType)
0331:                    throws ConfigException {
0332:                getInternalExcludeDefaultListenersConfig(type, _annotationCfg);
0333:
0334:                if (!_annotationCfg.isNull())
0335:                    entityType.setExcludeDefaultListeners(true);
0336:
0337:                getInternalExcludeSuperclassListenersConfig(type,
0338:                        _annotationCfg);
0339:
0340:                if (!_annotationCfg.isNull())
0341:                    entityType.setExcludeSuperclassListeners(true);
0342:
0343:                for (JMethod method : type.getMethods()) {
0344:                    introspectCallbacks(entityType, method);
0345:                }
0346:            }
0347:
0348:            /**
0349:             * Introspects the callbacks.
0350:             */
0351:            public void introspectCallbacks(AbstractEnhancedType type,
0352:                    JMethod method) throws ConfigException {
0353:                JClass[] param = method.getParameterTypes();
0354:
0355:                String methodName = method.getName();
0356:                JClass jClass = type.getBeanClass();
0357:
0358:                boolean isListener = type instanceof  ListenerType;
0359:
0360:                int n = ListenerType.CALLBACK_CLASS.length;
0361:
0362:                for (int i = 1; i < n; i++) {
0363:                    getInternalCallbackConfig(i, jClass, method, methodName,
0364:                            _annotationCfg);
0365:
0366:                    if (!_annotationCfg.isNull()) {
0367:                        validateCallback(ListenerType.CALLBACK_CLASS[i]
0368:                                .getName(), method, isListener);
0369:
0370:                        type.addCallback(i, method);
0371:                    }
0372:                }
0373:            }
0374:
0375:            /**
0376:             * Introspects named queries.
0377:             */
0378:            void introspectNamedQueries(JClass type, String typeName) {
0379:                // jpa/0y0-
0380:
0381:                getInternalNamedQueryConfig(type, _annotationCfg);
0382:                JAnnotation namedQueryAnn = _annotationCfg.getAnnotation();
0383:                NamedQueryConfig namedQueryConfig = _annotationCfg
0384:                        .getNamedQueryConfig();
0385:
0386:                // getInternalNamedQueriesConfig(type);
0387:                JAnnotation namedQueriesAnn = type
0388:                        .getAnnotation(NamedQueries.class);
0389:                // NamedQueriesConfig namedQueriesConfig = _annotationCfg.getNamedQueriesConfig();
0390:
0391:                if ((namedQueryAnn == null) && (namedQueriesAnn == null))
0392:                    return;
0393:
0394:                Object namedQueryArray[];
0395:
0396:                if ((namedQueryAnn != null) && (namedQueriesAnn != null)) {
0397:                    throw new ConfigException(
0398:                            L
0399:                                    .l(
0400:                                            "{0} may not have both @NamedQuery and @NamedQueries",
0401:                                            typeName));
0402:                } else if (namedQueriesAnn != null) {
0403:                    namedQueryArray = (Object[]) namedQueriesAnn.get("value");
0404:                } else {
0405:                    namedQueryArray = new Object[] { namedQueryAnn };
0406:                }
0407:
0408:                for (int i = 0; i < namedQueryArray.length; i++) {
0409:                    namedQueryAnn = (JAnnotation) namedQueryArray[i];
0410:                    _persistenceUnit.addNamedQuery(namedQueryAnn
0411:                            .getString("name"), namedQueryAnn
0412:                            .getString("query"));
0413:                }
0414:            }
0415:
0416:            /**
0417:             * Introspects named native queries.
0418:             */
0419:            void introspectNamedNativeQueries(JClass type, String typeName) {
0420:                // jpa/0y2-
0421:
0422:                getInternalNamedNativeQueryConfig(type, _annotationCfg);
0423:                JAnnotation namedNativeQueryAnn = _annotationCfg
0424:                        .getAnnotation();
0425:                NamedNativeQueryConfig namedNativeQueryConfig = _annotationCfg
0426:                        .getNamedNativeQueryConfig();
0427:
0428:                JAnnotation namedNativeQueriesAnn = type
0429:                        .getAnnotation(NamedNativeQueries.class);
0430:
0431:                if ((namedNativeQueryAnn == null)
0432:                        && (namedNativeQueriesAnn == null))
0433:                    return;
0434:
0435:                Object namedNativeQueryArray[];
0436:
0437:                if ((namedNativeQueryAnn != null)
0438:                        && (namedNativeQueriesAnn != null)) {
0439:                    throw new ConfigException(
0440:                            L
0441:                                    .l(
0442:                                            "{0} may not have both @NamedNativeQuery and @NamedNativeQueries",
0443:                                            typeName));
0444:                } else if (namedNativeQueriesAnn != null) {
0445:                    namedNativeQueryArray = (Object[]) namedNativeQueriesAnn
0446:                            .get("value");
0447:                } else {
0448:                    namedNativeQueryArray = new Object[] { namedNativeQueryAnn };
0449:                }
0450:
0451:                for (int i = 0; i < namedNativeQueryArray.length; i++) {
0452:                    namedNativeQueryAnn = (JAnnotation) namedNativeQueryArray[i];
0453:
0454:                    NamedNativeQueryConfig nativeQueryConfig = new NamedNativeQueryConfig();
0455:
0456:                    nativeQueryConfig.setQuery(namedNativeQueryAnn
0457:                            .getString("query"));
0458:                    nativeQueryConfig.setResultClass(namedNativeQueryAnn
0459:                            .getClass("resultClass").getName());
0460:                    nativeQueryConfig.setResultSetMapping(namedNativeQueryAnn
0461:                            .getString("resultSetMapping"));
0462:
0463:                    _persistenceUnit.addNamedNativeQuery(namedNativeQueryAnn
0464:                            .getString("name"), nativeQueryConfig);
0465:                }
0466:            }
0467:
0468:            /**
0469:             * Introspects sql result set mappings.
0470:             */
0471:            void introspectSqlResultSetMappings(JClass type,
0472:                    RelatedType relatedType, String typeName) {
0473:                // jpa/0y1-
0474:
0475:                getInternalSqlResultSetMappingConfig(type, _annotationCfg);
0476:                JAnnotation sqlResultSetMappingAnn = _annotationCfg
0477:                        .getAnnotation();
0478:                SqlResultSetMappingConfig sqlResultSetMappingConfig = _annotationCfg
0479:                        .getSqlResultSetMappingConfig();
0480:
0481:                JAnnotation sqlResultSetMappingsAnn = type
0482:                        .getAnnotation(SqlResultSetMappings.class);
0483:
0484:                if ((sqlResultSetMappingAnn == null)
0485:                        && (sqlResultSetMappingsAnn == null))
0486:                    return;
0487:
0488:                Object sqlResultSetMappingArray[];
0489:
0490:                if ((sqlResultSetMappingAnn != null)
0491:                        && (sqlResultSetMappingsAnn != null)) {
0492:                    throw new ConfigException(
0493:                            L
0494:                                    .l(
0495:                                            "{0} may not have both @SqlResultSetMapping and @SqlResultSetMappings",
0496:                                            typeName));
0497:                } else if (sqlResultSetMappingsAnn != null) {
0498:                    sqlResultSetMappingArray = (Object[]) sqlResultSetMappingsAnn
0499:                            .get("value");
0500:                } else {
0501:                    sqlResultSetMappingArray = new Object[] { sqlResultSetMappingAnn };
0502:                }
0503:
0504:                if (sqlResultSetMappingConfig != null) {
0505:                    _persistenceUnit.addSqlResultSetMapping(
0506:                            sqlResultSetMappingConfig.getName(),
0507:                            sqlResultSetMappingConfig);
0508:                    return;
0509:                }
0510:
0511:                for (int i = 0; i < sqlResultSetMappingArray.length; i++) {
0512:                    sqlResultSetMappingAnn = (JAnnotation) sqlResultSetMappingArray[i];
0513:
0514:                    String name = sqlResultSetMappingAnn.getString("name");
0515:                    Object entities[] = (Object[]) sqlResultSetMappingAnn
0516:                            .get("entities");
0517:                    Object columns[] = (Object[]) sqlResultSetMappingAnn
0518:                            .get("columns");
0519:
0520:                    SqlResultSetMappingCompletion completion = new SqlResultSetMappingCompletion(
0521:                            relatedType, name, entities, columns);
0522:
0523:                    _depCompletions.add(completion);
0524:                }
0525:            }
0526:
0527:            /**
0528:             * Completion callback for sql result set mappings.
0529:             */
0530:            void addSqlResultSetMapping(String resultSetName,
0531:                    Object entities[], Object columns[]) throws ConfigException {
0532:                // jpa/0y1-
0533:
0534:                SqlResultSetMappingConfig sqlResultSetMapping = new SqlResultSetMappingConfig();
0535:
0536:                // Adds @EntityResult.
0537:                for (int i = 0; i < entities.length; i++) {
0538:                    JAnnotation entityResult = (JAnnotation) entities[i];
0539:
0540:                    String className = entityResult.getClass("entityClass")
0541:                            .getName();
0542:
0543:                    EntityType resultType = _persistenceUnit
0544:                            .getEntityType(className);
0545:
0546:                    if (resultType == null)
0547:                        throw new ConfigException(
0548:                                L
0549:                                        .l(
0550:                                                "entityClass '{0}' is not an @Entity bean for @SqlResultSetMapping '{1}'. The entityClass of an @EntityResult must be an @Entity bean.",
0551:                                                className, resultSetName));
0552:
0553:                    EntityResultConfig entityResultConfig = new EntityResultConfig();
0554:
0555:                    entityResultConfig.setEntityClass(className);
0556:
0557:                    // @FieldResult annotations.
0558:                    Object fields[] = (Object[]) entityResult.get("fields");
0559:
0560:                    for (int j = 0; j < fields.length; j++) {
0561:                        JAnnotation fieldResult = (JAnnotation) fields[j];
0562:
0563:                        String fieldName = fieldResult.getString("name");
0564:
0565:                        AmberField field = resultType.getField(fieldName);
0566:
0567:                        if (field == null)
0568:                            throw new ConfigException(
0569:                                    L
0570:                                            .l(
0571:                                                    "@FieldResult with field name '{0}' is not a field for @EntityResult bean '{1}' in @SqlResultSetMapping '{2}'",
0572:                                                    fieldName, className,
0573:                                                    resultSetName));
0574:
0575:                        String columnName = fieldResult.getString("column");
0576:
0577:                        if (columnName == null || columnName.length() == 0)
0578:                            throw new ConfigException(
0579:                                    L
0580:                                            .l(
0581:                                                    "@FieldResult must have a column name defined and it must not be empty for '{0}' in @EntityResult '{1}' @SqlResultSetMapping '{2}'",
0582:                                                    fieldName, className,
0583:                                                    resultSetName));
0584:
0585:                        FieldResultConfig fieldResultConfig = new FieldResultConfig();
0586:
0587:                        fieldResultConfig.setName(fieldName);
0588:                        fieldResultConfig.setColumn(columnName);
0589:
0590:                        entityResultConfig.addFieldResult(fieldResultConfig);
0591:                    }
0592:
0593:                    sqlResultSetMapping.addEntityResult(entityResultConfig);
0594:                }
0595:
0596:                // Adds @ColumnResult.
0597:                for (int i = 0; i < columns.length; i++) {
0598:                    JAnnotation columnResult = (JAnnotation) columns[i];
0599:
0600:                    String columnName = columnResult.getString("name");
0601:
0602:                    if (columnName == null || columnName.length() == 0)
0603:                        throw new ConfigException(
0604:                                L
0605:                                        .l(
0606:                                                "@ColumnResult must have a column name defined and it must not be empty in @SqlResultSetMapping '{0}'",
0607:                                                resultSetName));
0608:
0609:                    ColumnResultConfig columnResultConfig = new ColumnResultConfig();
0610:
0611:                    columnResultConfig.setName(columnName);
0612:
0613:                    sqlResultSetMapping.addColumnResult(columnResultConfig);
0614:                }
0615:
0616:                // Adds a global sql result set mapping to the persistence unit.
0617:                _persistenceUnit.addSqlResultSetMapping(resultSetName,
0618:                        sqlResultSetMapping);
0619:            }
0620:
0621:            /**
0622:             * Completes all partial bean introspection.
0623:             */
0624:            public void configure() throws ConfigException {
0625:                RuntimeException exn = null;
0626:
0627:                while (_depCompletions.size() > 0
0628:                        || _linkCompletions.size() > 0) {
0629:                    while (_linkCompletions.size() > 0) {
0630:                        Completion completion = _linkCompletions.remove(0);
0631:
0632:                        try {
0633:                            completion.complete();
0634:                        } catch (Exception e) {
0635:                            if (e instanceof  ConfigException) {
0636:                                log.warning(e.getMessage());
0637:                                log.log(Level.FINEST, e.toString(), e);
0638:                            } else
0639:                                log.log(Level.WARNING, e.toString(), e);
0640:
0641:                            completion.getRelatedType().setConfigException(e);
0642:
0643:                            if (exn == null)
0644:                                exn = ConfigException.create(e);
0645:                        }
0646:                    }
0647:
0648:                    if (_depCompletions.size() > 0) {
0649:                        Completion completion = _depCompletions.remove(0);
0650:
0651:                        try {
0652:                            completion.complete();
0653:                        } catch (Exception e) {
0654:                            if (e instanceof  ConfigException) {
0655:                                log.warning(e.getMessage());
0656:                                log.log(Level.FINEST, e.toString(), e);
0657:                            } else
0658:                                log.log(Level.WARNING, e.toString(), e);
0659:
0660:                            completion.getRelatedType().setConfigException(e);
0661:
0662:                            if (exn == null)
0663:                                exn = ConfigException.create(e);
0664:                        }
0665:                    }
0666:                }
0667:
0668:                if (exn != null)
0669:                    throw exn;
0670:            }
0671:
0672:            /**
0673:             * Introspects the Inheritance
0674:             */
0675:            void introspectInheritance(AmberPersistenceUnit persistenceUnit,
0676:                    RelatedType entityType, JClass type,
0677:                    JAnnotation inheritanceAnn,
0678:                    InheritanceConfig inheritanceConfig)
0679:                    throws ConfigException, SQLException {
0680:                InheritanceType strategy;
0681:
0682:                if (inheritanceAnn != null)
0683:                    strategy = (InheritanceType) inheritanceAnn.get("strategy");
0684:                else
0685:                    strategy = inheritanceConfig.getStrategy();
0686:
0687:                JAnnotation discValueAnn = type
0688:                        .getAnnotation(DiscriminatorValue.class);
0689:
0690:                String discriminatorValue = null;
0691:
0692:                if (discValueAnn != null)
0693:                    discriminatorValue = discValueAnn.getString("value");
0694:
0695:                if (discriminatorValue == null || discriminatorValue.equals("")) {
0696:                    String name = entityType.getBeanClass().getName();
0697:                    int p = name.lastIndexOf('.');
0698:                    if (p > 0)
0699:                        name = name.substring(p + 1);
0700:
0701:                    discriminatorValue = name;
0702:                }
0703:
0704:                entityType.setDiscriminatorValue(discriminatorValue);
0705:
0706:                if (entityType instanceof  SubEntityType) {
0707:                    SubEntityType subType = (SubEntityType) entityType;
0708:
0709:                    subType.getParentType().addSubClass(subType);
0710:
0711:                    getInternalPrimaryKeyJoinColumnConfig(type, _annotationCfg);
0712:                    JAnnotation joinAnn = _annotationCfg.getAnnotation();
0713:                    PrimaryKeyJoinColumnConfig primaryKeyJoinColumnConfig = _annotationCfg
0714:                            .getPrimaryKeyJoinColumnConfig();
0715:
0716:                    // if (subType.isJoinedSubClass()) {
0717:                    if (strategy == InheritanceType.JOINED) {
0718:                        linkInheritanceTable(subType.getRootType().getTable(),
0719:                                subType.getTable(), joinAnn,
0720:                                primaryKeyJoinColumnConfig);
0721:
0722:                        subType
0723:                                .setId(new SubId(subType, subType.getRootType()));
0724:                    }
0725:
0726:                    return;
0727:                }
0728:
0729:                switch (strategy) {
0730:                case JOINED:
0731:                    entityType.setJoinedSubClass(true);
0732:                    break;
0733:                }
0734:
0735:                getInternalDiscriminatorColumnConfig(type, _annotationCfg);
0736:                JAnnotation discriminatorAnn = _annotationCfg.getAnnotation();
0737:                DiscriminatorColumnConfig discriminatorConfig = _annotationCfg
0738:                        .getDiscriminatorColumnConfig();
0739:
0740:                String columnName = null;
0741:
0742:                if (discriminatorAnn != null)
0743:                    columnName = discriminatorAnn.getString("name");
0744:
0745:                if (columnName == null || columnName.equals(""))
0746:                    columnName = "DTYPE";
0747:
0748:                Type columnType = null;
0749:                DiscriminatorType discType = DiscriminatorType.STRING;
0750:
0751:                if (discriminatorAnn != null)
0752:                    discType = (DiscriminatorType) discriminatorAnn
0753:                            .get("discriminatorType");
0754:
0755:                switch (discType) {
0756:                case STRING:
0757:                    columnType = StringType.create();
0758:                    break;
0759:                case CHAR:
0760:                    columnType = PrimitiveCharType.create();
0761:                    break;
0762:                case INTEGER:
0763:                    columnType = PrimitiveIntType.create();
0764:                    break;
0765:                default:
0766:                    throw new IllegalStateException();
0767:                }
0768:
0769:                Table table = entityType.getTable();
0770:
0771:                // jpa/0gg0
0772:                if (table == null)
0773:                    return;
0774:
0775:                Column column = table.createColumn(columnName, columnType);
0776:
0777:                if (discriminatorAnn != null) {
0778:                    column.setNotNull(!discriminatorAnn.getBoolean("nullable"));
0779:
0780:                    column.setLength(discriminatorAnn.getInt("length"));
0781:
0782:                    if (!"".equals(discriminatorAnn.get("columnDefinition")))
0783:                        column.setSQLType(discriminatorAnn
0784:                                .getString("columnDefinition"));
0785:                } else {
0786:                    column.setNotNull(true);
0787:                    column.setLength(10);
0788:                }
0789:
0790:                entityType.setDiscriminator(column);
0791:            }
0792:
0793:            /**
0794:             * Introspects the fields.
0795:             */
0796:            void introspectIdMethod(AmberPersistenceUnit persistenceUnit,
0797:                    RelatedType entityType, RelatedType parentType,
0798:                    JClass type, JClass idClass, MappedSuperclassConfig config)
0799:                    throws ConfigException, SQLException {
0800:                ArrayList<IdField> keys = new ArrayList<IdField>();
0801:
0802:                IdField idField = null;
0803:
0804:                AttributesConfig attributesConfig = null;
0805:
0806:                if (config != null)
0807:                    attributesConfig = config.getAttributes();
0808:
0809:                for (JMethod method : type.getMethods()) {
0810:                    String methodName = method.getName();
0811:                    JClass[] paramTypes = method.getParameterTypes();
0812:
0813:                    if (method.getDeclaringClass().getName().equals(
0814:                            "java.lang.Object"))
0815:                        continue;
0816:
0817:                    if (!methodName.startsWith("get") || paramTypes.length != 0) {
0818:                        continue;
0819:                    }
0820:
0821:                    String fieldName = toFieldName(methodName.substring(3));
0822:
0823:                    if (containsFieldOrCompletion(parentType, fieldName))
0824:                        continue;
0825:
0826:                    getInternalIdConfig(type, method, fieldName, _annotationCfg);
0827:                    JAnnotation id = _annotationCfg.getAnnotation();
0828:                    IdConfig idConfig = _annotationCfg.getIdConfig();
0829:
0830:                    if (!_annotationCfg.isNull()) {
0831:                        idField = introspectId(persistenceUnit, entityType,
0832:                                method, fieldName, method.getReturnType(),
0833:                                idConfig);
0834:
0835:                        if (idField != null)
0836:                            keys.add(idField);
0837:                    } else {
0838:                        getInternalEmbeddedIdConfig(type, method, fieldName,
0839:                                _annotationCfg);
0840:                        JAnnotation embeddedId = _annotationCfg.getAnnotation();
0841:                        EmbeddedIdConfig embeddedIdConfig = _annotationCfg
0842:                                .getEmbeddedIdConfig();
0843:
0844:                        if (!_annotationCfg.isNull()) {
0845:                            idField = introspectEmbeddedId(persistenceUnit,
0846:                                    entityType, method, fieldName, method
0847:                                            .getReturnType());
0848:                            break;
0849:                        } else {
0850:                            continue;
0851:                        }
0852:                    }
0853:                }
0854:
0855:                if (keys.size() == 0) {
0856:                    if (idField != null) {
0857:                        // @EmbeddedId was used.
0858:                        com.caucho.amber.field.EmbeddedId id = new com.caucho.amber.field.EmbeddedId(
0859:                                entityType, (EmbeddedIdField) idField);
0860:
0861:                        entityType.setId(id);
0862:                    }
0863:                } else if (keys.size() == 1) {
0864:                    entityType.setId(new com.caucho.amber.field.Id(entityType,
0865:                            keys));
0866:                } else if (idClass == null) {
0867:                    throw new ConfigException(
0868:                            L
0869:                                    .l(
0870:                                            "{0} has multiple @Id methods, but no @IdClass.  Compound primary keys require either an @IdClass or exactly one @EmbeddedId field or property.",
0871:                                            entityType.getName()));
0872:                } else {
0873:                    CompositeId id = new CompositeId(entityType, keys);
0874:                    id.setKeyClass(idClass);
0875:
0876:                    entityType.setId(id);
0877:                }
0878:            }
0879:
0880:            /**
0881:             * Introspects the fields.
0882:             */
0883:            void introspectIdField(AmberPersistenceUnit persistenceUnit,
0884:                    RelatedType entityType, RelatedType parentType,
0885:                    JClass type, JClass idClass, MappedSuperclassConfig config)
0886:                    throws ConfigException, SQLException {
0887:                ArrayList<IdField> keys = new ArrayList<IdField>();
0888:
0889:                AttributesConfig attributesConfig = null;
0890:
0891:                if (config != null)
0892:                    attributesConfig = config.getAttributes();
0893:
0894:                for (JField field : type.getFields()) {
0895:                    String fieldName = field.getName();
0896:
0897:                    if (containsFieldOrCompletion(parentType, fieldName))
0898:                        continue;
0899:
0900:                    getInternalIdConfig(type, field, fieldName, _annotationCfg);
0901:                    JAnnotation id = _annotationCfg.getAnnotation();
0902:                    IdConfig idConfig = _annotationCfg.getIdConfig();
0903:
0904:                    if (_annotationCfg.isNull()) {
0905:                        getInternalEmbeddedIdConfig(type, field, fieldName,
0906:                                _annotationCfg);
0907:                        JAnnotation embeddedId = _annotationCfg.getAnnotation();
0908:                        EmbeddedIdConfig embeddedIdConfig = _annotationCfg
0909:                                .getEmbeddedIdConfig();
0910:
0911:                        if (_annotationCfg.isNull())
0912:                            continue;
0913:                    }
0914:
0915:                    IdField idField = introspectId(persistenceUnit, entityType,
0916:                            field, fieldName, field.getType(), idConfig);
0917:
0918:                    if (idField != null)
0919:                        keys.add(idField);
0920:                }
0921:
0922:                if (keys.size() == 0) {
0923:                } else if (keys.size() == 1)
0924:                    entityType.setId(new com.caucho.amber.field.Id(entityType,
0925:                            keys));
0926:                else if (idClass == null) {
0927:                    throw new ConfigException(
0928:                            L
0929:                                    .l(
0930:                                            "{0} has multiple @Id fields, but no @IdClass.  Compound primary keys require an @IdClass.",
0931:                                            entityType.getName()));
0932:                } else {
0933:                    CompositeId id = new CompositeId(entityType, keys);
0934:                    id.setKeyClass(idClass);
0935:
0936:                    entityType.setId(id);
0937:                }
0938:            }
0939:
0940:            /**
0941:             * Check if it's field
0942:             */
0943:            boolean isField(JClass type, AbstractEnhancedConfig typeConfig,
0944:                    boolean isEmbeddable) throws ConfigException {
0945:                if (type == null)
0946:                    return false;
0947:
0948:                if (typeConfig != null) {
0949:                    String access = typeConfig.getAccess();
0950:
0951:                    if (access != null)
0952:                        return access.equals("FIELD");
0953:
0954:                    JClass parentClass = type.getSuperClass();
0955:
0956:                    if (parentClass == null)
0957:                        return false;
0958:                    else {
0959:                        getInternalEntityConfig(parentClass, _annotationCfg);
0960:                        EntityConfig super EntityConfig = _annotationCfg
0961:                                .getEntityConfig();
0962:
0963:                        if (super EntityConfig == null)
0964:                            return false;
0965:
0966:                        return isField(parentClass, super EntityConfig, false);
0967:                    }
0968:                }
0969:
0970:                for (JField field : type.getDeclaredFields()) {
0971:                    JAnnotation id = field
0972:                            .getAnnotation(javax.persistence.Id.class);
0973:
0974:                    if (id != null)
0975:                        return true;
0976:
0977:                    id = field.getAnnotation(EmbeddedId.class);
0978:
0979:                    if (id != null)
0980:                        return true;
0981:                }
0982:
0983:                return isField(type.getSuperClass(), null, false);
0984:            }
0985:
0986:            private IdField introspectId(AmberPersistenceUnit persistenceUnit,
0987:                    RelatedType entityType, JAccessibleObject field,
0988:                    String fieldName, JClass fieldType, IdConfig idConfig)
0989:                    throws ConfigException, SQLException {
0990:                JAnnotation id = field
0991:                        .getAnnotation(javax.persistence.Id.class);
0992:                JAnnotation column = field
0993:                        .getAnnotation(javax.persistence.Column.class);
0994:
0995:                ColumnConfig columnConfig = null;
0996:                GeneratedValueConfig generatedValueConfig = null;
0997:
0998:                if (idConfig != null) {
0999:                    columnConfig = idConfig.getColumn();
1000:                    generatedValueConfig = idConfig.getGeneratedValue();
1001:                }
1002:
1003:                JAnnotation gen = field.getAnnotation(GeneratedValue.class);
1004:
1005:                Type amberType = persistenceUnit.createType(fieldType);
1006:
1007:                KeyPropertyField idField;
1008:
1009:                Column keyColumn = null;
1010:
1011:                if (entityType.getTable() != null) {
1012:                    keyColumn = createColumn(entityType, field, fieldName,
1013:                            column, amberType, columnConfig);
1014:
1015:                    idField = new KeyPropertyField(entityType, fieldName,
1016:                            keyColumn);
1017:                } else {
1018:                    idField = new KeyPropertyField(entityType, fieldName);
1019:                    return idField;
1020:                }
1021:
1022:                if (gen == null) {
1023:                } else {
1024:                    JdbcMetaData metaData = null;
1025:
1026:                    try {
1027:                        metaData = persistenceUnit.getMetaData();
1028:                    } catch (ConfigException e) {
1029:                        throw e;
1030:                    } catch (Exception e) {
1031:                        throw new ConfigException(
1032:                                L
1033:                                        .l("Unable to get meta data for database. Meta data is needed for generated values."),
1034:                                e);
1035:                    }
1036:
1037:                    if (GenerationType.IDENTITY.equals(gen.get("strategy"))) {
1038:                        if (!metaData.supportsIdentity())
1039:                            throw new ConfigException(L.l(
1040:                                    "'{0}' does not support identity.",
1041:                                    metaData.getDatabaseName()));
1042:
1043:                        keyColumn.setGeneratorType("identity");
1044:                        idField.setGenerator("identity");
1045:                    } else if (GenerationType.SEQUENCE.equals(gen
1046:                            .get("strategy"))) {
1047:                        if (!metaData.supportsSequences())
1048:                            throw new ConfigException(L.l(
1049:                                    "'{0}' does not support sequence.",
1050:                                    metaData.getDatabaseName()));
1051:
1052:                        addSequenceIdGenerator(persistenceUnit, idField, gen);
1053:                    } else if (GenerationType.TABLE.equals(gen.get("strategy"))) {
1054:                        addTableIdGenerator(persistenceUnit, idField, id);
1055:                    } else if (GenerationType.AUTO.equals(gen.get("strategy"))) {
1056:                        if (metaData.supportsIdentity()) {
1057:                            keyColumn.setGeneratorType("identity");
1058:                            idField.setGenerator("identity");
1059:                        } else if (metaData.supportsSequences()) {
1060:                            addSequenceIdGenerator(persistenceUnit, idField,
1061:                                    gen);
1062:                        } else {
1063:                            addTableIdGenerator(persistenceUnit, idField, id);
1064:                        }
1065:                    }
1066:                }
1067:
1068:                return idField;
1069:            }
1070:
1071:            private IdField introspectEmbeddedId(
1072:                    AmberPersistenceUnit persistenceUnit,
1073:                    RelatedType ownerType, JAccessibleObject field,
1074:                    String fieldName, JClass fieldType) throws ConfigException,
1075:                    SQLException {
1076:                IdField idField;
1077:
1078:                EmbeddableType embeddableType = persistenceUnit
1079:                        .createEmbeddable(fieldType);
1080:
1081:                idField = new EmbeddedIdField(ownerType, embeddableType,
1082:                        fieldName);
1083:
1084:                return idField;
1085:            }
1086:
1087:            void addSequenceIdGenerator(AmberPersistenceUnit persistenceUnit,
1088:                    KeyPropertyField idField, JAnnotation genAnn)
1089:                    throws ConfigException {
1090:                idField.setGenerator("sequence");
1091:                idField.getColumn().setGeneratorType("sequence");
1092:
1093:                String name = genAnn.getString("generator");
1094:
1095:                if (name == null || "".equals(name))
1096:                    name = idField.getEntitySourceType().getTable().getName()
1097:                            + "_cseq";
1098:
1099:                IdGenerator gen = persistenceUnit.createSequenceGenerator(name,
1100:                        1);
1101:
1102:                idField.getEntitySourceType().setGenerator(idField.getName(),
1103:                        gen);
1104:            }
1105:
1106:            void addTableIdGenerator(AmberPersistenceUnit persistenceUnit,
1107:                    KeyPropertyField idField, JAnnotation idAnn)
1108:                    throws ConfigException {
1109:                idField.setGenerator("table");
1110:                idField.getColumn().setGeneratorType("table");
1111:
1112:                String name = idAnn.getString("generator");
1113:                if (name == null || "".equals(name))
1114:                    name = "caucho";
1115:
1116:                IdGenerator gen = persistenceUnit.getTableGenerator(name);
1117:
1118:                if (gen == null) {
1119:                    String genName = "GEN_TABLE";
1120:
1121:                    GeneratorTableType genTable;
1122:                    genTable = persistenceUnit.createGeneratorTable(genName);
1123:
1124:                    gen = genTable.createGenerator(name);
1125:
1126:                    // jpa/0g60
1127:                    genTable.init();
1128:
1129:                    persistenceUnit.putTableGenerator(name, gen);
1130:                }
1131:
1132:                idField.getEntitySourceType().setGenerator(idField.getName(),
1133:                        gen);
1134:            }
1135:
1136:            /**
1137:             * Links a secondary table.
1138:             */
1139:            void linkSecondaryTable(Table primaryTable, Table secondaryTable,
1140:                    JAnnotation[] joinColumnsAnn) throws ConfigException {
1141:                ArrayList<ForeignColumn> linkColumns = new ArrayList<ForeignColumn>();
1142:                for (Column column : primaryTable.getIdColumns()) {
1143:                    ForeignColumn linkColumn;
1144:
1145:                    JAnnotation joinAnn = getJoinColumn(joinColumnsAnn, column
1146:                            .getName());
1147:                    String name;
1148:
1149:                    if (joinAnn == null)
1150:                        name = column.getName();
1151:                    else
1152:                        name = joinAnn.getString("name");
1153:
1154:                    linkColumn = secondaryTable.createForeignColumn(name,
1155:                            column);
1156:                    linkColumn.setPrimaryKey(true);
1157:
1158:                    secondaryTable.addIdColumn(linkColumn);
1159:
1160:                    linkColumns.add(linkColumn);
1161:                }
1162:
1163:                LinkColumns link = new LinkColumns(secondaryTable,
1164:                        primaryTable, linkColumns);
1165:
1166:                link.setSourceCascadeDelete(true);
1167:
1168:                secondaryTable.setDependentIdLink(link);
1169:            }
1170:
1171:            /**
1172:             * Links a secondary table.
1173:             */
1174:            void linkInheritanceTable(Table primaryTable, Table secondaryTable,
1175:                    JAnnotation joinAnn,
1176:                    PrimaryKeyJoinColumnConfig pkJoinColumnCfg)
1177:                    throws ConfigException {
1178:                JAnnotation joinAnns[] = null;
1179:
1180:                if (joinAnn != null)
1181:                    joinAnns = new JAnnotation[] { joinAnn };
1182:
1183:                linkInheritanceTable(primaryTable, secondaryTable, joinAnns,
1184:                        pkJoinColumnCfg);
1185:            }
1186:
1187:            /**
1188:             * Links a secondary table.
1189:             */
1190:            void linkInheritanceTable(Table primaryTable, Table secondaryTable,
1191:                    JAnnotation[] joinColumnsAnn,
1192:                    PrimaryKeyJoinColumnConfig pkJoinColumnCfg)
1193:                    throws ConfigException {
1194:                ArrayList<ForeignColumn> linkColumns = new ArrayList<ForeignColumn>();
1195:                for (Column column : primaryTable.getIdColumns()) {
1196:                    ForeignColumn linkColumn;
1197:
1198:                    String name;
1199:
1200:                    if (joinColumnsAnn == null) {
1201:
1202:                        if (pkJoinColumnCfg == null)
1203:                            name = column.getName();
1204:                        else
1205:                            name = pkJoinColumnCfg.getName();
1206:                    } else {
1207:                        JAnnotation join;
1208:
1209:                        join = getJoinColumn(joinColumnsAnn, column.getName());
1210:
1211:                        if (join == null)
1212:                            name = column.getName();
1213:                        else
1214:                            name = join.getString("name");
1215:                    }
1216:
1217:                    linkColumn = secondaryTable.createForeignColumn(name,
1218:                            column);
1219:                    linkColumn.setPrimaryKey(true);
1220:
1221:                    secondaryTable.addIdColumn(linkColumn);
1222:
1223:                    linkColumns.add(linkColumn);
1224:                }
1225:
1226:                LinkColumns link = new LinkColumns(secondaryTable,
1227:                        primaryTable, linkColumns);
1228:
1229:                link.setSourceCascadeDelete(true);
1230:
1231:                secondaryTable.setDependentIdLink(link);
1232:
1233:                // jpa/0l48
1234:                //    link = new LinkColumns(primaryTable,
1235:                //                           secondaryTable,
1236:                //                           linkColumns);
1237:                //
1238:                //    link.setSourceCascadeDelete(true);
1239:                //
1240:                //    primaryTable.setDependentIdLink(link);
1241:            }
1242:
1243:            /**
1244:             * Introspects the methods.
1245:             */
1246:            void introspectMethods(AmberPersistenceUnit persistenceUnit,
1247:                    AbstractStatefulType entityType,
1248:                    AbstractStatefulType parentType, JClass type,
1249:                    AbstractEnhancedConfig typeConfig) throws ConfigException {
1250:                for (JMethod method : type.getMethods()) {
1251:                    String methodName = method.getName();
1252:                    JClass[] paramTypes = method.getParameterTypes();
1253:
1254:                    if (method.getDeclaringClass().getName().equals(
1255:                            "java.lang.Object"))
1256:                        continue;
1257:
1258:                    // jpa/0r38
1259:                    // Callbacks are introspected in the main introspect() block.
1260:                    // introspectCallbacks(entityType, method);
1261:
1262:                    String propName;
1263:
1264:                    if (paramTypes.length != 0) {
1265:                        validateNonGetter(method);
1266:                        continue;
1267:                    } else if (methodName.startsWith("get")) {
1268:                        propName = methodName.substring(3);
1269:                    } else if (methodName.startsWith("is")
1270:                            && (method.getReturnType().getName().equals(
1271:                                    "boolean") || method.getReturnType()
1272:                                    .getName().equals("java.lang.Boolean"))) {
1273:                        propName = methodName.substring(2);
1274:                    } else {
1275:                        validateNonGetter(method);
1276:                        continue;
1277:                    }
1278:
1279:                    getInternalVersionConfig(type, method, propName,
1280:                            _annotationCfg);
1281:                    JAnnotation versionAnn = _annotationCfg.getAnnotation();
1282:                    VersionConfig versionConfig = _annotationCfg
1283:                            .getVersionConfig();
1284:
1285:                    if (!_annotationCfg.isNull()) {
1286:                        validateNonGetter(method);
1287:                    } else {
1288:
1289:                        JMethod setter = type.getMethod("set" + propName,
1290:                                new JClass[] { method.getReturnType() });
1291:                        if (method.isPrivate() || (setter == null)
1292:                                || setter.isPrivate()) {
1293:
1294:                            JAnnotation ann = isAnnotatedMethod(method);
1295:
1296:                            if (ann == null) {
1297:                                if (setter != null)
1298:                                    ann = isAnnotatedMethod(setter);
1299:                            } else if (ann.getType().equals(
1300:                                    "javax.persistence.Transient"))
1301:                                continue;
1302:
1303:                            if (ann != null) {
1304:                                throw error(
1305:                                        method,
1306:                                        L
1307:                                                .l(
1308:                                                        "'{0}' is not a valid annotation for {1}.  Only public persistent property getters with matching setters may have property annotations.",
1309:                                                        ann.getType(), method
1310:                                                                .getFullName()));
1311:                            }
1312:
1313:                            continue;
1314:                        }
1315:
1316:                        // ejb/0g03 for private
1317:                        if (method.isStatic()) { // || ! method.isPublic()) {
1318:                            validateNonGetter(method);
1319:                            continue;
1320:                        }
1321:                    }
1322:
1323:                    String fieldName = toFieldName(propName);
1324:
1325:                    if (containsFieldOrCompletion(parentType, fieldName))
1326:                        continue;
1327:
1328:                    JClass fieldType = method.getReturnType();
1329:
1330:                    introspectField(persistenceUnit, entityType, method,
1331:                            fieldName, fieldType, typeConfig);
1332:                }
1333:            }
1334:
1335:            /**
1336:             * Introspects the fields.
1337:             */
1338:            void introspectFields(AmberPersistenceUnit persistenceUnit,
1339:                    AbstractStatefulType entityType,
1340:                    AbstractStatefulType parentType, JClass type,
1341:                    AbstractEnhancedConfig typeConfig, boolean isEmbeddable)
1342:                    throws ConfigException {
1343:                if (!isEmbeddable && ((RelatedType) entityType).getId() == null)
1344:                    throw new IllegalStateException(L.l("{0} has no key",
1345:                            entityType));
1346:
1347:                for (JField field : type.getFields()) {
1348:                    String fieldName = field.getName();
1349:
1350:                    if (containsFieldOrCompletion(parentType, fieldName)) {
1351:                        continue;
1352:                    }
1353:
1354:                    if (field.isStatic() || field.isTransient())
1355:                        continue;
1356:
1357:                    JClass fieldType = field.getType();
1358:                    introspectField(persistenceUnit, entityType, field,
1359:                            fieldName, fieldType, typeConfig);
1360:                }
1361:            }
1362:
1363:            void introspectField(AmberPersistenceUnit persistenceUnit,
1364:                    AbstractStatefulType sourceType, JAccessibleObject field,
1365:                    String fieldName, JClass fieldType,
1366:                    AbstractEnhancedConfig typeConfig) throws ConfigException {
1367:                EmbeddableConfig embeddableConfig = null;
1368:                MappedSuperclassConfig mappedSuperOrEntityConfig = null;
1369:
1370:                if (typeConfig instanceof  EmbeddableConfig)
1371:                    embeddableConfig = (EmbeddableConfig) typeConfig;
1372:                else if (typeConfig instanceof  MappedSuperclassConfig)
1373:                    mappedSuperOrEntityConfig = (MappedSuperclassConfig) typeConfig;
1374:
1375:                // jpa/0r37: interface fields must not be considered.
1376:
1377:                JClass jClass = field.getDeclaringClass();
1378:
1379:                if (jClass.isInterface())
1380:                    return;
1381:
1382:                // jpa/0r37: fields declared in non-entity superclasses
1383:                // must not be considered.
1384:
1385:                AbstractStatefulType declaringType;
1386:
1387:                declaringType = _persistenceUnit
1388:                        .getEntityType(jClass.getName());
1389:
1390:                if (declaringType == null)
1391:                    declaringType = _persistenceUnit.getEmbeddable(jClass
1392:                            .getName());
1393:
1394:                if (declaringType == null)
1395:                    declaringType = _persistenceUnit.getMappedSuperclass(jClass
1396:                            .getName());
1397:
1398:                if (declaringType == null)
1399:                    return;
1400:
1401:                AttributesConfig attributesConfig = null;
1402:                IdConfig idConfig = null;
1403:                BasicConfig basicConfig = null;
1404:                OneToOneConfig oneToOneConfig = null;
1405:                OneToManyConfig oneToManyConfig = null;
1406:                ManyToOneConfig manyToOneConfig = null;
1407:                ManyToManyConfig manyToManyConfig = null;
1408:                VersionConfig versionConfig = null;
1409:
1410:                if (mappedSuperOrEntityConfig != null) {
1411:                    attributesConfig = mappedSuperOrEntityConfig
1412:                            .getAttributes();
1413:
1414:                    if (attributesConfig != null) {
1415:                        idConfig = attributesConfig.getId(fieldName);
1416:
1417:                        basicConfig = attributesConfig.getBasic(fieldName);
1418:
1419:                        oneToOneConfig = attributesConfig
1420:                                .getOneToOne(fieldName);
1421:
1422:                        oneToManyConfig = attributesConfig
1423:                                .getOneToMany(fieldName);
1424:
1425:                        manyToOneConfig = attributesConfig
1426:                                .getManyToOne(fieldName);
1427:
1428:                        manyToManyConfig = attributesConfig
1429:                                .getManyToMany(fieldName);
1430:
1431:                        versionConfig = attributesConfig.getVersion(fieldName);
1432:                    }
1433:                }
1434:
1435:                if ((idConfig != null)
1436:                        || field
1437:                                .isAnnotationPresent(javax.persistence.Id.class)) {
1438:                    validateAnnotations(field, "@Id", _idAnnotations);
1439:
1440:                    if (!_idTypes.contains(fieldType.getName())) {
1441:                        throw error(field, L.l(
1442:                                "{0} is an invalid @Id type for {1}.",
1443:                                fieldType.getName(), field.getName()));
1444:                    }
1445:                } else if ((basicConfig != null)
1446:                        || field
1447:                                .isAnnotationPresent(javax.persistence.Basic.class)) {
1448:                    validateAnnotations(field, "@Basic", _basicAnnotations);
1449:
1450:                    addBasic(sourceType, field, fieldName, fieldType,
1451:                            basicConfig);
1452:                } else if ((versionConfig != null)
1453:                        || field
1454:                                .isAnnotationPresent(javax.persistence.Version.class)) {
1455:                    validateAnnotations(field, "@Version", _versionAnnotations);
1456:
1457:                    addVersion((RelatedType) sourceType, field, fieldName,
1458:                            fieldType, versionConfig);
1459:                } else if ((manyToOneConfig != null)
1460:                        || field
1461:                                .isAnnotationPresent(javax.persistence.ManyToOne.class)) {
1462:                    validateAnnotations(field, "@ManyToOne",
1463:                            _manyToOneAnnotations);
1464:
1465:                    JAnnotation ann = field.getAnnotation(ManyToOne.class);
1466:
1467:                    JClass targetEntity = null;
1468:
1469:                    if (ann != null)
1470:                        targetEntity = ann.getClass("targetEntity");
1471:                    else {
1472:
1473:                        String s = manyToOneConfig.getTargetEntity();
1474:
1475:                        if ((s != null) && (s.length() > 0))
1476:                            targetEntity = _persistenceUnit.getJClassLoader()
1477:                                    .forName(s);
1478:                    }
1479:
1480:                    if (targetEntity == null
1481:                            || targetEntity.getName().equals("void")) {
1482:                        targetEntity = fieldType;
1483:                    }
1484:
1485:                    getInternalEntityConfig(targetEntity, _annotationCfg);
1486:                    JAnnotation targetEntityAnn = _annotationCfg
1487:                            .getAnnotation();
1488:                    EntityConfig targetEntityConfig = _annotationCfg
1489:                            .getEntityConfig();
1490:
1491:                    if (_annotationCfg.isNull()) {
1492:                        throw error(
1493:                                field,
1494:                                L
1495:                                        .l(
1496:                                                "'{0}' is an illegal targetEntity for {1}.  @ManyToOne relations must target a valid @Entity.",
1497:                                                targetEntity.getName(), field
1498:                                                        .getName()));
1499:                    }
1500:
1501:                    if (!fieldType.isAssignableFrom(targetEntity)) {
1502:                        throw error(
1503:                                field,
1504:                                L
1505:                                        .l(
1506:                                                "'{0}' is an illegal targetEntity for {1}.  @ManyToOne targetEntity must be assignable to the field type '{2}'.",
1507:                                                targetEntity.getName(), field
1508:                                                        .getName(), fieldType
1509:                                                        .getName()));
1510:                    }
1511:
1512:                    RelatedType relatedType = (RelatedType) sourceType;
1513:
1514:                    relatedType.setHasDependent(true);
1515:
1516:                    _linkCompletions.add(new ManyToOneCompletion(relatedType,
1517:                            field, fieldName, fieldType));
1518:                } else if ((oneToManyConfig != null)
1519:                        || field
1520:                                .isAnnotationPresent(javax.persistence.OneToMany.class)) {
1521:                    validateAnnotations(field, "@OneToMany",
1522:                            _oneToManyAnnotations);
1523:
1524:                    if (field
1525:                            .isAnnotationPresent(javax.persistence.MapKey.class)) {
1526:                        if (!fieldType.getName().equals("java.util.Map")) {
1527:                            throw error(
1528:                                    field,
1529:                                    L
1530:                                            .l(
1531:                                                    "'{0}' is an illegal @OneToMany/@MapKey type for {1}. @MapKey must be a java.util.Map",
1532:                                                    fieldType.getName(), field
1533:                                                            .getName()));
1534:                        }
1535:                    } else if (!_oneToManyTypes.contains(fieldType.getName())) {
1536:                        throw error(
1537:                                field,
1538:                                L
1539:                                        .l(
1540:                                                "'{0}' is an illegal @OneToMany type for {1}.  @OneToMany must be a java.util.Collection, java.util.List or java.util.Map",
1541:                                                fieldType.getName(), field
1542:                                                        .getName()));
1543:                    }
1544:
1545:                    RelatedType relatedType = (RelatedType) sourceType;
1546:
1547:                    _depCompletions.add(new OneToManyCompletion(relatedType,
1548:                            field, fieldName, fieldType, oneToManyConfig));
1549:                } else if ((oneToOneConfig != null)
1550:                        || field
1551:                                .isAnnotationPresent(javax.persistence.OneToOne.class)) {
1552:                    validateAnnotations(field, "@OneToOne",
1553:                            _oneToOneAnnotations);
1554:
1555:                    RelatedType relatedType = (RelatedType) sourceType;
1556:
1557:                    OneToOneCompletion oneToOne = new OneToOneCompletion(
1558:                            relatedType, field, fieldName, fieldType);
1559:
1560:                    // jpa/0o03 and jpa/0o06 (check also jpa/0o07 with no mappedBy at all)
1561:                    // @OneToOne with mappedBy should be completed first
1562:                    String mappedBy;
1563:
1564:                    if (oneToOneConfig != null)
1565:                        mappedBy = oneToOneConfig.getMappedBy();
1566:                    else {
1567:                        JAnnotation oneToOneAnn = field
1568:                                .getAnnotation(OneToOne.class);
1569:                        mappedBy = oneToOneAnn.getString("mappedBy");
1570:                    }
1571:
1572:                    boolean isOwner = (mappedBy == null || mappedBy.equals(""));
1573:
1574:                    if (isOwner)
1575:                        _depCompletions.add(oneToOne);
1576:                    else {
1577:                        _depCompletions.add(0, oneToOne);
1578:                        relatedType.setHasDependent(true);
1579:                    }
1580:
1581:                    ArrayList<OneToOneCompletion> oneToOneList = _oneToOneCompletions
1582:                            .get(relatedType);
1583:
1584:                    if (oneToOneList == null) {
1585:                        oneToOneList = new ArrayList<OneToOneCompletion>();
1586:                        _oneToOneCompletions.put(relatedType, oneToOneList);
1587:                    }
1588:
1589:                    oneToOneList.add(oneToOne);
1590:                } else if ((manyToManyConfig != null)
1591:                        || field
1592:                                .isAnnotationPresent(javax.persistence.ManyToMany.class)) {
1593:
1594:                    if (field
1595:                            .isAnnotationPresent(javax.persistence.MapKey.class)) {
1596:                        if (!fieldType.getName().equals("java.util.Map")) {
1597:                            throw error(
1598:                                    field,
1599:                                    L
1600:                                            .l(
1601:                                                    "'{0}' is an illegal @ManyToMany/@MapKey type for {1}. @MapKey must be a java.util.Map",
1602:                                                    fieldType.getName(), field
1603:                                                            .getName()));
1604:                        }
1605:                    }
1606:
1607:                    RelatedType relatedType = (RelatedType) sourceType;
1608:
1609:                    Completion completion = new ManyToManyCompletion(
1610:                            relatedType, field, fieldName, fieldType);
1611:
1612:                    JAnnotation ann = field.getAnnotation(ManyToMany.class);
1613:
1614:                    String mappedBy;
1615:
1616:                    if (ann != null)
1617:                        mappedBy = ann.getString("mappedBy");
1618:                    else
1619:                        mappedBy = manyToManyConfig.getMappedBy();
1620:
1621:                    if ("".equals(mappedBy))
1622:                        _linkCompletions.add(completion);
1623:                    else
1624:                        _depCompletions.add(completion);
1625:                } else if (field
1626:                        .isAnnotationPresent(javax.persistence.Embedded.class)) {
1627:                    validateAnnotations(field, "@Embedded",
1628:                            _embeddedAnnotations);
1629:
1630:                    RelatedType relatedType = (RelatedType) sourceType;
1631:
1632:                    relatedType.setHasDependent(true);
1633:
1634:                    _depCompletions.add(new EmbeddedCompletion(relatedType,
1635:                            field, fieldName, fieldType, false));
1636:                } else if (field
1637:                        .isAnnotationPresent(javax.persistence.EmbeddedId.class)) {
1638:                    validateAnnotations(field, "@EmbeddedId",
1639:                            _embeddedIdAnnotations);
1640:
1641:                    _depCompletions.add(new EmbeddedCompletion(
1642:                            (RelatedType) sourceType, field, fieldName,
1643:                            fieldType, true));
1644:                } else if (field
1645:                        .isAnnotationPresent(javax.persistence.Transient.class)) {
1646:                } else {
1647:                    addBasic(sourceType, field, fieldName, fieldType,
1648:                            basicConfig);
1649:                }
1650:            }
1651:
1652:            void addBasic(AbstractStatefulType sourceType,
1653:                    JAccessibleObject field, String fieldName,
1654:                    JClass fieldType, BasicConfig basicConfig)
1655:                    throws ConfigException {
1656:                AmberPersistenceUnit persistenceUnit = sourceType
1657:                        .getPersistenceUnit();
1658:
1659:                JAnnotation basicAnn = field.getAnnotation(Basic.class);
1660:                JAnnotation columnAnn = field
1661:                        .getAnnotation(javax.persistence.Column.class);
1662:                JAnnotation enumeratedAnn = field
1663:                        .getAnnotation(Enumerated.class);
1664:
1665:                ColumnConfig columnConfig = null;
1666:
1667:                if (basicConfig != null)
1668:                    columnConfig = basicConfig.getColumn();
1669:
1670:                if (_basicTypes.contains(fieldType.getName())) {
1671:                } else if (fieldType.isAssignableTo(java.io.Serializable.class)) {
1672:                } else
1673:                    throw error(field, L.l(
1674:                            "{0} is an invalid @Basic type for {1}.", fieldType
1675:                                    .getName(), field.getName()));
1676:
1677:                Type amberType;
1678:
1679:                if (enumeratedAnn == null)
1680:                    amberType = persistenceUnit.createType(fieldType);
1681:                else {
1682:                    com.caucho.amber.type.EnumType enumType;
1683:
1684:                    enumType = persistenceUnit.createEnum(fieldType.getName(),
1685:                            fieldType);
1686:
1687:                    enumType
1688:                            .setOrdinal(enumeratedAnn.get("value") == javax.persistence.EnumType.ORDINAL);
1689:
1690:                    amberType = enumType;
1691:                }
1692:
1693:                Column fieldColumn = null;
1694:
1695:                fieldColumn = createColumn(sourceType, field, fieldName,
1696:                        columnAnn, amberType, columnConfig);
1697:
1698:                PropertyField property = new PropertyField(sourceType,
1699:                        fieldName);
1700:                property.setColumn(fieldColumn);
1701:
1702:                // jpa/0w24
1703:                property.setType(amberType);
1704:
1705:                if (basicAnn != null)
1706:                    property.setLazy(basicAnn.get("fetch") == FetchType.LAZY);
1707:                else if (basicConfig != null)
1708:                    property.setLazy(basicConfig.getFetch() == FetchType.LAZY);
1709:                else
1710:                    property.setLazy(false);
1711:
1712:                /*
1713:                  field.setInsertable(insertable);
1714:                  field.setUpdateable(updateable);
1715:                 */
1716:
1717:                sourceType.addField(property);
1718:            }
1719:
1720:            void addVersion(RelatedType sourceType, JAccessibleObject field,
1721:                    String fieldName, JClass fieldType,
1722:                    VersionConfig versionConfig) throws ConfigException {
1723:                AmberPersistenceUnit persistenceUnit = sourceType
1724:                        .getPersistenceUnit();
1725:
1726:                JAnnotation columnAnn = field
1727:                        .getAnnotation(javax.persistence.Column.class);
1728:
1729:                ColumnConfig columnConfig = null;
1730:
1731:                if (versionConfig != null)
1732:                    columnConfig = versionConfig.getColumn();
1733:
1734:                if (!_versionTypes.contains(fieldType.getName())) {
1735:                    throw error(field, L.l(
1736:                            "{0} is an invalid @Version type for {1}.",
1737:                            fieldType.getName(), field.getName()));
1738:                }
1739:
1740:                Type amberType = persistenceUnit.createType(fieldType);
1741:
1742:                Column fieldColumn = createColumn(sourceType, field, fieldName,
1743:                        columnAnn, amberType, columnConfig);
1744:
1745:                VersionField version = new VersionField(sourceType, fieldName);
1746:                version.setColumn(fieldColumn);
1747:
1748:                sourceType.setVersionField(version);
1749:            }
1750:
1751:            private Column createColumn(AbstractStatefulType beanType,
1752:                    JAccessibleObject field, String fieldName,
1753:                    JAnnotation columnAnn, Type amberType,
1754:                    ColumnConfig columnConfig) throws ConfigException {
1755:                RelatedType entityType = null;
1756:
1757:                if (beanType instanceof  RelatedType)
1758:                    entityType = (RelatedType) beanType;
1759:
1760:                String name;
1761:
1762:                if (columnAnn != null && !columnAnn.get("name").equals(""))
1763:                    name = (String) columnAnn.get("name");
1764:                else if (columnConfig != null
1765:                        && !columnConfig.getName().equals(""))
1766:                    name = columnConfig.getName();
1767:                else
1768:                    name = toSqlName(fieldName);
1769:
1770:                Column column = null;
1771:
1772:                if (entityType == null) { // embeddable
1773:                    column = new Column(null, name, amberType);
1774:                } else if (columnAnn != null
1775:                        && !columnAnn.get("table").equals("")) {
1776:                    String tableName = columnAnn.getString("table");
1777:                    Table table;
1778:
1779:                    table = entityType.getSecondaryTable(tableName);
1780:
1781:                    if (table == null)
1782:                        throw error(
1783:                                field,
1784:                                L
1785:                                        .l(
1786:                                                "{0} @Column(table='{1}') is an unknown secondary table.",
1787:                                                fieldName, tableName));
1788:
1789:                    column = table.createColumn(name, amberType);
1790:                } else if (entityType.getTable() != null)
1791:                    column = entityType.getTable()
1792:                            .createColumn(name, amberType);
1793:                else { // jpa/0ge2: MappedSuperclassType
1794:                    column = new Column(null, name, amberType);
1795:                }
1796:
1797:                if (column != null && columnAnn != null) {
1798:                    // primaryKey = column.primaryKey();
1799:                    column.setUnique(columnAnn.getBoolean("unique"));
1800:                    column.setNotNull(!columnAnn.getBoolean("nullable"));
1801:                    //insertable = column.insertable();
1802:                    //updateable = column.updatable();
1803:                    if (!"".equals(columnAnn.getString("columnDefinition")))
1804:                        column.setSQLType(columnAnn
1805:                                .getString("columnDefinition"));
1806:                    column.setLength(columnAnn.getInt("length"));
1807:                    int precision = columnAnn.getInt("precision");
1808:                    if (precision < 0) {
1809:                        throw error(field, L.l(
1810:                                "{0} @Column precision cannot be less than 0.",
1811:                                fieldName));
1812:                    }
1813:
1814:                    int scale = columnAnn.getInt("scale");
1815:                    if (scale < 0) {
1816:                        throw error(field, L.l(
1817:                                "{0} @Column scale cannot be less than 0.",
1818:                                fieldName));
1819:                    }
1820:
1821:                    // this test implicitly works for case where
1822:                    // precision is not set explicitly (ie: set to 0 by default)
1823:                    // and scale is set
1824:                    if (scale > precision) {
1825:                        throw error(
1826:                                field,
1827:                                L
1828:                                        .l(
1829:                                                "{0} @Column scale cannot be greater than precision. Must set precision to a non-zero value before setting scale.",
1830:                                                fieldName));
1831:                    }
1832:
1833:                    if (precision > 0) {
1834:                        column.setPrecision(precision);
1835:                        column.setScale(scale);
1836:                    }
1837:                }
1838:
1839:                return column;
1840:            }
1841:
1842:            void addManyToOne(RelatedType sourceType, JAccessibleObject field,
1843:                    String fieldName, JClass fieldType) throws ConfigException {
1844:                AmberPersistenceUnit persistenceUnit = sourceType
1845:                        .getPersistenceUnit();
1846:
1847:                getInternalManyToOneConfig(sourceType.getBeanClass(), field,
1848:                        fieldName, _annotationCfg);
1849:                JAnnotation manyToOneAnn = _annotationCfg.getAnnotation();
1850:                Object manyToOneConfig = _annotationCfg.getManyToOneConfig();
1851:                HashMap<String, JoinColumnConfig> joinColumnMap = null;
1852:                CascadeType cascadeTypes[] = null;
1853:
1854:                JClass parentClass = sourceType.getBeanClass();
1855:
1856:                do {
1857:                    getInternalEntityConfig(parentClass, _annotationCfg);
1858:                    JAnnotation parentEntity = _annotationCfg.getAnnotation();
1859:                    EntityConfig super EntityConfig = _annotationCfg
1860:                            .getEntityConfig();
1861:
1862:                    if (super EntityConfig != null) {
1863:                        AttributesConfig attributesConfig = super EntityConfig
1864:                                .getAttributes();
1865:
1866:                        if (attributesConfig != null) {
1867:                            if (manyToOneConfig == null)
1868:                                manyToOneConfig = attributesConfig
1869:                                        .getManyToOne(fieldName);
1870:                        }
1871:                    }
1872:
1873:                    parentClass = parentClass.getSuperClass();
1874:                } while ((parentClass != null) && (manyToOneConfig == null));
1875:
1876:                FetchType fetchType = FetchType.EAGER;
1877:                JClass targetClass = null;
1878:
1879:                boolean isManyToOne = true;
1880:
1881:                if ((manyToOneAnn == null) && (manyToOneConfig == null)) {
1882:                    // jpa/0j67
1883:                    isManyToOne = false;
1884:
1885:                    // jpa/0o03
1886:                    getInternalOneToOneConfig(sourceType.getBeanClass(), field,
1887:                            fieldName, _annotationCfg);
1888:                    manyToOneAnn = _annotationCfg.getAnnotation();
1889:                    manyToOneConfig = _annotationCfg.getOneToOneConfig();
1890:
1891:                    if (manyToOneConfig != null) {
1892:                        fetchType = ((OneToOneConfig) manyToOneConfig)
1893:                                .getFetch();
1894:                        joinColumnMap = ((OneToOneConfig) manyToOneConfig)
1895:                                .getJoinColumnMap();
1896:
1897:                        String s = ((OneToOneConfig) manyToOneConfig)
1898:                                .getTargetEntity();
1899:                        if (s != null)
1900:                            targetClass = _persistenceUnit.getJClassLoader()
1901:                                    .forName(s);
1902:                    }
1903:                } else {
1904:                    if (manyToOneConfig != null) {
1905:                        fetchType = ((ManyToOneConfig) manyToOneConfig)
1906:                                .getFetch();
1907:                        joinColumnMap = ((ManyToOneConfig) manyToOneConfig)
1908:                                .getJoinColumnMap();
1909:                        CascadeConfig cascade = ((ManyToOneConfig) manyToOneConfig)
1910:                                .getCascade();
1911:
1912:                        if (cascade != null) {
1913:                            cascadeTypes = cascade.getCascadeTypes();
1914:                        }
1915:
1916:                        String s = ((ManyToOneConfig) manyToOneConfig)
1917:                                .getTargetEntity();
1918:                        if (s != null)
1919:                            targetClass = _persistenceUnit.getJClassLoader()
1920:                                    .forName(s);
1921:                    }
1922:                }
1923:
1924:                if (manyToOneAnn != null) {
1925:                    fetchType = (FetchType) manyToOneAnn.get("fetch");
1926:
1927:                    targetClass = manyToOneAnn.getClass("targetEntity");
1928:
1929:                    // XXX: runtime does not cast this
1930:                    // cascadeType = (CascadeType []) manyToOneAnn.get("cascade");
1931:                    Object cascade[] = (Object[]) manyToOneAnn.get("cascade");
1932:
1933:                    cascadeTypes = new CascadeType[cascade.length];
1934:
1935:                    for (int i = 0; i < cascade.length; i++)
1936:                        cascadeTypes[i] = (CascadeType) cascade[i];
1937:                }
1938:
1939:                if (fetchType == FetchType.EAGER) {
1940:                    if (sourceType.getBeanClass().getName().equals(
1941:                            fieldType.getName())) {
1942:                        throw error(
1943:                                field,
1944:                                L
1945:                                        .l(
1946:                                                "'{0}': '{1}' is an illegal recursive type for @OneToOne/@ManyToOne with EAGER fetching. You should specify FetchType.LAZY for this relationship.",
1947:                                                field.getName(), fieldType
1948:                                                        .getName()));
1949:                    }
1950:                }
1951:
1952:                JAnnotation joinColumns = field
1953:                        .getAnnotation(JoinColumns.class);
1954:
1955:                Object[] joinColumnsAnn = null;
1956:
1957:                if (joinColumns != null)
1958:                    joinColumnsAnn = (Object[]) joinColumns.get("value");
1959:
1960:                JAnnotation joinColumnAnn = field
1961:                        .getAnnotation(JoinColumn.class);
1962:
1963:                if (joinColumnsAnn != null && joinColumnAnn != null) {
1964:                    throw error(
1965:                            field,
1966:                            L
1967:                                    .l(
1968:                                            "{0} may not have both @JoinColumn and @JoinColumns",
1969:                                            field.getName()));
1970:                }
1971:
1972:                if (joinColumnAnn != null)
1973:                    joinColumnsAnn = new Object[] { joinColumnAnn };
1974:
1975:                String targetName = "";
1976:                if (targetClass != null)
1977:                    targetName = targetClass.getName();
1978:
1979:                if (targetName.equals("") || targetName.equals("void"))
1980:                    targetName = fieldType.getName();
1981:
1982:                EntityManyToOneField manyToOneField;
1983:                manyToOneField = new EntityManyToOneField(sourceType,
1984:                        fieldName, cascadeTypes, isManyToOne);
1985:
1986:                EntityType targetType = persistenceUnit.createEntity(
1987:                        targetName, fieldType);
1988:
1989:                manyToOneField.setType(targetType);
1990:
1991:                manyToOneField.setLazy(fetchType == FetchType.LAZY);
1992:
1993:                manyToOneField.setJoinColumns(joinColumnsAnn);
1994:                manyToOneField.setJoinColumnMap(joinColumnMap);
1995:
1996:                sourceType.addField(manyToOneField);
1997:
1998:                // jpa/0ge3
1999:                if (sourceType instanceof  MappedSuperclassType)
2000:                    return;
2001:
2002:                validateJoinColumns(field, joinColumnsAnn, joinColumnMap,
2003:                        targetType);
2004:
2005:                manyToOneField.init();
2006:            }
2007:
2008:            public static JAnnotation getJoinColumn(JAnnotation joinColumns,
2009:                    String keyName) {
2010:                if (joinColumns == null)
2011:                    return null;
2012:
2013:                return getJoinColumn((Object[]) joinColumns.get("value"),
2014:                        keyName);
2015:            }
2016:
2017:            void validateJoinColumns(JAccessibleObject field,
2018:                    Object[] columnsAnn,
2019:                    HashMap<String, JoinColumnConfig> joinColumnMap,
2020:                    RelatedType targetType) throws ConfigException {
2021:                if ((joinColumnMap == null) && (columnsAnn == null))
2022:                    return;
2023:
2024:                com.caucho.amber.field.Id id = targetType.getId();
2025:
2026:                RelatedType parentType = targetType;
2027:
2028:                int idCols;
2029:
2030:                // XXX: jpa/0l48
2031:                while ((idCols = id.getColumns().size()) == 0) {
2032:                    parentType = parentType.getParentType();
2033:
2034:                    if (parentType == null)
2035:                        break;
2036:
2037:                    id = parentType.getId();
2038:                }
2039:
2040:                int size;
2041:                Object joinColumnCfg[] = null;
2042:
2043:                if (columnsAnn != null)
2044:                    size = columnsAnn.length;
2045:                else {
2046:                    size = joinColumnMap.size();
2047:                    joinColumnCfg = joinColumnMap.values().toArray();
2048:                }
2049:
2050:                if (idCols != size) {
2051:                    throw error(
2052:                            field,
2053:                            L
2054:                                    .l(
2055:                                            "Number of @JoinColumns for '{1}' ({0}) does not match the number of primary key columns for '{3}' ({2}).",
2056:                                            "" + size, field.getName(), idCols,
2057:                                            targetType.getName()));
2058:                }
2059:
2060:                for (int i = 0; i < size; i++) {
2061:                    String ref;
2062:
2063:                    if (joinColumnCfg != null) {
2064:                        ref = ((JoinColumnConfig) joinColumnCfg[i])
2065:                                .getReferencedColumnName();
2066:                    } else {
2067:                        JAnnotation ann = (JAnnotation) columnsAnn[i];
2068:
2069:                        ref = ann.getString("referencedColumnName");
2070:                    }
2071:
2072:                    if (((ref == null) || ref.equals("")) && size > 1)
2073:                        throw error(
2074:                                field,
2075:                                L
2076:                                        .l("referencedColumnName is required when more than one @JoinColumn is specified."));
2077:
2078:                    Column column = findColumn(id.getColumns(), ref);
2079:
2080:                    if (column == null)
2081:                        throw error(
2082:                                field,
2083:                                L
2084:                                        .l(
2085:                                                "referencedColumnName '{0}' does not match any key column in '{1}'.",
2086:                                                ref, targetType.getName()));
2087:                }
2088:            }
2089:
2090:            private Column findColumn(ArrayList<Column> columns, String ref) {
2091:                if (((ref == null) || ref.equals("")) && columns.size() == 1)
2092:                    return columns.get(0);
2093:
2094:                for (Column column : columns) {
2095:                    if (column.getName().equals(ref))
2096:                        return column;
2097:                }
2098:
2099:                return null;
2100:            }
2101:
2102:            public static JAnnotation getJoinColumn(Object[] columnsAnn,
2103:                    String keyName) {
2104:                if (columnsAnn == null || columnsAnn.length == 0)
2105:                    return null;
2106:
2107:                for (int i = 0; i < columnsAnn.length; i++) {
2108:                    JAnnotation ann = (JAnnotation) columnsAnn[i];
2109:
2110:                    String ref = ann.getString("referencedColumnName");
2111:
2112:                    if (ref.equals("") || ref.equals(keyName))
2113:                        return ann;
2114:                }
2115:
2116:                return null;
2117:            }
2118:
2119:            void addManyToMany(RelatedType sourceType, JAccessibleObject field,
2120:                    String fieldName, JClass fieldType) throws ConfigException {
2121:                getInternalManyToManyConfig(sourceType.getBeanClass(), field,
2122:                        fieldName, _annotationCfg);
2123:                JAnnotation manyToManyAnn = _annotationCfg.getAnnotation();
2124:                ManyToManyConfig manyToManyConfig = _annotationCfg
2125:                        .getManyToManyConfig();
2126:
2127:                JType retType;
2128:
2129:                if (field instanceof  JField)
2130:                    retType = ((JField) field).getGenericType();
2131:                else
2132:                    retType = ((JMethod) field).getGenericReturnType();
2133:
2134:                JType[] typeArgs = retType.getActualTypeArguments();
2135:
2136:                String targetName = "";
2137:
2138:                if (manyToManyAnn != null) {
2139:                    JClass targetEntity = manyToManyAnn
2140:                            .getClass("targetEntity");
2141:
2142:                    if (targetEntity != null)
2143:                        targetName = targetEntity.getName();
2144:                } else
2145:                    targetName = manyToManyConfig.getTargetEntity();
2146:
2147:                if (!targetName.equals("") && !targetName.equals("void")) {
2148:                } else if (typeArgs.length > 0)
2149:                    targetName = typeArgs[0].getName();
2150:                else
2151:                    throw error(
2152:                            field,
2153:                            L
2154:                                    .l(
2155:                                            "Can't determine targetEntity for {0}.  @OneToMany properties must target @Entity beans.",
2156:                                            field.getName()));
2157:
2158:                EntityType targetType = _persistenceUnit
2159:                        .getEntityType(targetName);
2160:
2161:                if (targetType == null)
2162:                    throw error(
2163:                            field,
2164:                            L
2165:                                    .l(
2166:                                            "targetEntity '{0}' is not an @Entity bean for {1}.  The targetEntity of a @ManyToMany collection must be an @Entity bean.",
2167:                                            targetName, field.getName()));
2168:
2169:                // XXX: introspect cascade types
2170:                CascadeType[] cascadeTypes = null;
2171:
2172:                String mappedBy;
2173:
2174:                if (manyToManyAnn != null) {
2175:                    mappedBy = manyToManyAnn.getString("mappedBy");
2176:
2177:                    // XXX: runtime does not cast this
2178:                    // cascadeType = (CascadeType []) manyToManyAnn.get("cascade");
2179:                    Object cascade[] = (Object[]) manyToManyAnn.get("cascade");
2180:
2181:                    cascadeTypes = new CascadeType[cascade.length];
2182:
2183:                    for (int i = 0; i < cascade.length; i++)
2184:                        cascadeTypes[i] = (CascadeType) cascade[i];
2185:                } else {
2186:                    mappedBy = manyToManyConfig.getMappedBy();
2187:
2188:                    CascadeConfig cascade = ((ManyToManyConfig) manyToManyConfig)
2189:                            .getCascade();
2190:
2191:                    if (cascade != null) {
2192:                        cascadeTypes = cascade.getCascadeTypes();
2193:                    }
2194:                }
2195:
2196:                if (!((mappedBy == null) || "".equals(mappedBy))) {
2197:                    EntityManyToManyField sourceField = (EntityManyToManyField) targetType
2198:                            .getField(mappedBy);
2199:
2200:                    EntityManyToManyField manyToManyField;
2201:
2202:                    if (sourceField == null)
2203:                        throw error(
2204:                                field,
2205:                                L
2206:                                        .l(
2207:                                                "Unable to find the associated field in '{0}' for a @ManyToMany relationship from '{1}'",
2208:                                                targetName, field.getName()));
2209:
2210:                    manyToManyField = new EntityManyToManyField(sourceType,
2211:                            fieldName, sourceField, cascadeTypes);
2212:                    manyToManyField.setType(targetType);
2213:                    sourceType.addField(manyToManyField);
2214:
2215:                    // jpa/0i5-
2216:                    // Update column names for bidirectional many-to-many
2217:
2218:                    if (!sourceField.hasJoinColumns()) {
2219:                        LinkColumns sourceLink = sourceField.getSourceLink();
2220:                        ArrayList<ForeignColumn> columns = sourceLink
2221:                                .getColumns();
2222:                        for (ForeignColumn column : columns) {
2223:                            String columnName = column.getName();
2224:                            columnName = columnName.substring(columnName
2225:                                    .indexOf('_'));
2226:                            columnName = toSqlName(manyToManyField.getName())
2227:                                    + columnName;
2228:                            column.setName(columnName);
2229:                        }
2230:                    }
2231:
2232:                    if (!sourceField.hasInverseJoinColumns()) {
2233:                        LinkColumns targetLink = sourceField.getTargetLink();
2234:                        ArrayList<ForeignColumn> columns = targetLink
2235:                                .getColumns();
2236:                        for (ForeignColumn column : columns) {
2237:                            String columnName = column.getName();
2238:                            columnName = columnName.substring(columnName
2239:                                    .indexOf('_'));
2240:                            columnName = toSqlName(sourceField.getName())
2241:                                    + columnName;
2242:                            column.setName(columnName);
2243:                        }
2244:                    }
2245:
2246:                    return;
2247:                }
2248:
2249:                EntityManyToManyField manyToManyField;
2250:
2251:                manyToManyField = new EntityManyToManyField(sourceType,
2252:                        fieldName, cascadeTypes);
2253:                manyToManyField.setType(targetType);
2254:
2255:                String sqlTable = sourceType.getTable().getName() + "_"
2256:                        + targetType.getTable().getName();
2257:
2258:                JAnnotation joinTableAnn = field
2259:                        .getAnnotation(javax.persistence.JoinTable.class);
2260:
2261:                JoinTableConfig joinTableConfig = null;
2262:
2263:                if (manyToManyConfig != null)
2264:                    joinTableConfig = manyToManyConfig.getJoinTable();
2265:
2266:                Table mapTable = null;
2267:
2268:                ArrayList<ForeignColumn> sourceColumns = null;
2269:                ArrayList<ForeignColumn> targetColumns = null;
2270:
2271:                if ((joinTableAnn != null) || (joinTableConfig != null)) {
2272:
2273:                    Object joinColumns[] = null;
2274:                    Object inverseJoinColumns[] = null;
2275:
2276:                    HashMap<String, JoinColumnConfig> joinColumnsConfig = null;
2277:                    HashMap<String, JoinColumnConfig> inverseJoinColumnsConfig = null;
2278:
2279:                    String joinTableName;
2280:
2281:                    if (joinTableAnn != null) {
2282:                        joinTableName = joinTableAnn.getString("name");
2283:                        joinColumns = (Object[]) joinTableAnn
2284:                                .get("joinColumns");
2285:                        inverseJoinColumns = (Object[]) joinTableAnn
2286:                                .get("inverseJoinColumns");
2287:
2288:                        if ((joinColumns != null) && (joinColumns.length > 0))
2289:                            manyToManyField.setJoinColumns(true);
2290:
2291:                        if ((inverseJoinColumns != null)
2292:                                && (inverseJoinColumns.length > 0))
2293:                            manyToManyField.setInverseJoinColumns(true);
2294:                    } else {
2295:                        joinTableName = joinTableConfig.getName();
2296:                        joinColumnsConfig = joinTableConfig.getJoinColumnMap();
2297:                        inverseJoinColumnsConfig = joinTableConfig
2298:                                .getInverseJoinColumnMap();
2299:
2300:                        if ((joinColumnsConfig != null)
2301:                                && (joinColumnsConfig.size() > 0))
2302:                            manyToManyField.setJoinColumns(true);
2303:
2304:                        if ((inverseJoinColumnsConfig != null)
2305:                                && (inverseJoinColumnsConfig.size() > 0))
2306:                            manyToManyField.setInverseJoinColumns(true);
2307:                    }
2308:
2309:                    if (!joinTableName.equals(""))
2310:                        sqlTable = joinTableName;
2311:
2312:                    mapTable = _persistenceUnit.createTable(sqlTable);
2313:
2314:                    sourceColumns = AbstractConfigIntrospector
2315:                            .calculateColumns(field, mapTable, sourceType
2316:                                    .getTable().getName()
2317:                                    + "_", sourceType, joinColumns,
2318:                                    joinColumnsConfig);
2319:
2320:                    targetColumns = AbstractConfigIntrospector
2321:                            .calculateColumns(field, mapTable, targetType
2322:                                    .getTable().getName()
2323:                                    + "_", targetType, inverseJoinColumns,
2324:                                    inverseJoinColumnsConfig);
2325:                } else {
2326:                    mapTable = _persistenceUnit.createTable(sqlTable);
2327:
2328:                    sourceColumns = AbstractConfigIntrospector
2329:                            .calculateColumns(mapTable, sourceType.getTable()
2330:                                    .getName()
2331:                                    + "_", sourceType);
2332:
2333:                    targetColumns = AbstractConfigIntrospector
2334:                            .calculateColumns(mapTable, targetType.getTable()
2335:                                    .getName()
2336:                                    + "_", targetType);
2337:                }
2338:
2339:                manyToManyField.setAssociationTable(mapTable);
2340:                manyToManyField.setTable(sqlTable);
2341:
2342:                manyToManyField.setSourceLink(new LinkColumns(mapTable,
2343:                        sourceType.getTable(), sourceColumns));
2344:
2345:                manyToManyField.setTargetLink(new LinkColumns(mapTable,
2346:                        targetType.getTable(), targetColumns));
2347:
2348:                getInternalMapKeyConfig(sourceType.getBeanClass(), field,
2349:                        fieldName, _annotationCfg);
2350:                JAnnotation mapKeyAnn = _annotationCfg.getAnnotation();
2351:                MapKeyConfig mapKeyConfig = _annotationCfg.getMapKeyConfig();
2352:
2353:                if (!_annotationCfg.isNull()) {
2354:
2355:                    String key;
2356:
2357:                    if (mapKeyAnn != null)
2358:                        key = mapKeyAnn.getString("name");
2359:                    else
2360:                        key = mapKeyConfig.getName();
2361:
2362:                    String getter = "get"
2363:                            + Character.toUpperCase(key.charAt(0))
2364:                            + key.substring(1);
2365:
2366:                    JMethod method = targetType.getGetter(getter);
2367:
2368:                    if (method == null) {
2369:                        throw error(
2370:                                field,
2371:                                L
2372:                                        .l(
2373:                                                "targetEntity '{0}' has no getter for field named '{1}'. Either the @MapKey name or the @ManyToMany targetEntity is incorrect.",
2374:                                                targetName, key));
2375:                    }
2376:
2377:                    manyToManyField.setMapKey(key);
2378:                }
2379:
2380:                sourceType.addField(manyToManyField);
2381:            }
2382:
2383:            EntityManyToOneField getSourceField(RelatedType targetType,
2384:                    String mappedBy, RelatedType sourceType) {
2385:                do {
2386:                    ArrayList<AmberField> fields = targetType.getFields();
2387:
2388:                    for (AmberField field : fields) {
2389:                        // jpa/0o07: there is no mappedBy at all on any sides.
2390:                        if ("".equals(mappedBy) || mappedBy == null) {
2391:                            if (field.getJavaType().isAssignableFrom(
2392:                                    sourceType.getBeanClass()))
2393:                                return (EntityManyToOneField) field;
2394:                        } else if (field.getName().equals(mappedBy))
2395:                            return (EntityManyToOneField) field;
2396:                    }
2397:
2398:                    // jpa/0ge4
2399:                    targetType = targetType.getParentType();
2400:                } while (targetType != null);
2401:
2402:                return null;
2403:            }
2404:
2405:            OneToOneCompletion getSourceCompletion(RelatedType targetType,
2406:                    String mappedBy) {
2407:                do {
2408:                    ArrayList<OneToOneCompletion> sourceCompletions = _oneToOneCompletions
2409:                            .get(targetType);
2410:
2411:                    if (sourceCompletions == null) {
2412:                    } // jpa/0o07
2413:                    else if (sourceCompletions.size() == 1)
2414:                        return sourceCompletions.get(0);
2415:                    else {
2416:                        for (OneToOneCompletion oneToOne : sourceCompletions) {
2417:                            if (oneToOne.getFieldName().equals(mappedBy)) {
2418:                                return oneToOne;
2419:                            }
2420:                        }
2421:                    }
2422:
2423:                    // jpa/0ge4
2424:                    targetType = targetType.getParentType();
2425:                } while (targetType != null);
2426:
2427:                return null;
2428:            }
2429:
2430:            /**
2431:             * completes for dependent
2432:             */
2433:            class Completion {
2434:                protected RelatedType _relatedType;
2435:
2436:                protected Completion(RelatedType relatedType, String fieldName) {
2437:                    _relatedType = relatedType;
2438:                    _relatedType.addCompletionField(fieldName);
2439:                }
2440:
2441:                protected Completion(RelatedType relatedType) {
2442:                    _relatedType = relatedType;
2443:                }
2444:
2445:                RelatedType getRelatedType() {
2446:                    return _relatedType;
2447:                }
2448:
2449:                void complete() throws ConfigException {
2450:                }
2451:            }
2452:
2453:            /**
2454:             * completes for dependent
2455:             */
2456:            class OneToManyCompletion extends Completion {
2457:                private JAccessibleObject _field;
2458:                private String _fieldName;
2459:                private JClass _fieldType;
2460:                private OneToManyConfig _oneToManyConfig;
2461:
2462:                OneToManyCompletion(RelatedType type, JAccessibleObject field,
2463:                        String fieldName, JClass fieldType,
2464:                        OneToManyConfig oneToManyConfig) {
2465:                    super (type, fieldName);
2466:
2467:                    _field = field;
2468:                    _fieldName = fieldName;
2469:                    _fieldType = fieldType;
2470:                    _oneToManyConfig = oneToManyConfig;
2471:                }
2472:
2473:                void complete() throws ConfigException {
2474:                    getInternalOneToManyConfig(_relatedType.getBeanClass(),
2475:                            _field, _fieldName, _annotationCfg);
2476:                    JAnnotation oneToManyAnn = _annotationCfg.getAnnotation();
2477:                    OneToManyConfig oneToManyConfig = _annotationCfg
2478:                            .getOneToManyConfig();
2479:
2480:                    AmberPersistenceUnit persistenceUnit = _relatedType
2481:                            .getPersistenceUnit();
2482:
2483:                    JType retType;
2484:
2485:                    if (_field instanceof  JField)
2486:                        retType = ((JField) _field).getGenericType();
2487:                    else
2488:                        retType = ((JMethod) _field).getGenericReturnType();
2489:
2490:                    JType[] typeArgs = retType.getActualTypeArguments();
2491:
2492:                    JClass targetEntity = null;
2493:
2494:                    if (oneToManyAnn != null)
2495:                        targetEntity = oneToManyAnn.getClass("targetEntity");
2496:                    else {
2497:                        String s = oneToManyConfig.getTargetEntity();
2498:
2499:                        if (s != null)
2500:                            targetEntity = _persistenceUnit.getJClassLoader()
2501:                                    .forName(s);
2502:                    }
2503:
2504:                    String targetName = "";
2505:
2506:                    if (targetEntity != null)
2507:                        targetName = targetEntity.getName();
2508:
2509:                    if (!targetName.equals("") && !targetName.equals("void")) {
2510:                    } else if (typeArgs.length > 0)
2511:                        targetName = typeArgs[typeArgs.length - 1].getName();
2512:                    else
2513:                        throw error(
2514:                                _field,
2515:                                L
2516:                                        .l(
2517:                                                "Can't determine targetEntity for {0}.  @OneToMany properties must target @Entity beans.",
2518:                                                _field.getName()));
2519:
2520:                    EntityType targetType = persistenceUnit
2521:                            .getEntityType(targetName);
2522:                    if (targetType == null) {
2523:
2524:                        EntityConfig entityConfig = getEntityConfig(targetName);
2525:
2526:                        if (entityConfig == null)
2527:                            throw error(
2528:                                    _field,
2529:                                    L
2530:                                            .l(
2531:                                                    "targetEntity '{0}' is not an @Entity bean for {1}.  The targetEntity of a @OneToMany collection must be an @Entity bean.",
2532:                                                    targetName, _field
2533:                                                            .getName()));
2534:                    }
2535:
2536:                    CascadeType[] cascadeTypes = null;
2537:
2538:                    String mappedBy;
2539:
2540:                    if (oneToManyAnn != null) {
2541:                        mappedBy = oneToManyAnn.getString("mappedBy");
2542:
2543:                        // XXX: runtime does not cast this
2544:                        // cascadeType = (CascadeType []) oneToManyAnn.get("cascade");
2545:                        Object cascade[] = (Object[]) oneToManyAnn
2546:                                .get("cascade");
2547:
2548:                        cascadeTypes = new CascadeType[cascade.length];
2549:
2550:                        for (int i = 0; i < cascade.length; i++)
2551:                            cascadeTypes[i] = (CascadeType) cascade[i];
2552:                    } else {
2553:                        mappedBy = oneToManyConfig.getMappedBy();
2554:
2555:                        CascadeConfig cascade = ((OneToManyConfig) oneToManyConfig)
2556:                                .getCascade();
2557:
2558:                        if (cascade != null) {
2559:                            cascadeTypes = cascade.getCascadeTypes();
2560:                        }
2561:                    }
2562:
2563:                    if (mappedBy != null && !mappedBy.equals("")) {
2564:                        oneToManyBidirectional(targetType, targetName,
2565:                                mappedBy, cascadeTypes);
2566:                    } else {
2567:                        oneToManyUnidirectional(targetType, targetName,
2568:                                cascadeTypes);
2569:                    }
2570:                }
2571:
2572:                private void oneToManyBidirectional(RelatedType targetType,
2573:                        String targetName, String mappedBy,
2574:                        CascadeType[] cascadeTypes) throws ConfigException {
2575:                    JAnnotation joinTableAnn = _field
2576:                            .getAnnotation(javax.persistence.JoinTable.class);
2577:
2578:                    JoinTableConfig joinTableConfig = null;
2579:
2580:                    if (_oneToManyConfig != null)
2581:                        joinTableConfig = _oneToManyConfig.getJoinTable();
2582:
2583:                    if ((joinTableAnn != null) || (joinTableConfig != null)) {
2584:                        throw error(
2585:                                _field,
2586:                                L
2587:                                        .l(
2588:                                                "Bidirectional @ManyToOne property {0} may not have a @JoinTable annotation.",
2589:                                                _field.getName()));
2590:                    }
2591:
2592:                    EntityManyToOneField sourceField = getSourceField(
2593:                            targetType, mappedBy, null);
2594:
2595:                    if (sourceField == null)
2596:                        throw error(
2597:                                _field,
2598:                                L
2599:                                        .l(
2600:                                                "'{0}' does not have matching field for @ManyToOne(mappedBy={1}).",
2601:                                                targetType.getName(), mappedBy));
2602:
2603:                    JAnnotation orderByAnn = _field
2604:                            .getAnnotation(javax.persistence.OrderBy.class);
2605:
2606:                    String orderBy = null;
2607:                    ArrayList<String> orderByFields = null;
2608:                    ArrayList<Boolean> orderByAscending = null;
2609:
2610:                    if (orderByAnn != null) {
2611:                        orderBy = (String) orderByAnn.get("value");
2612:
2613:                        if (orderBy == null)
2614:                            orderBy = "";
2615:
2616:                        if ("".equals(orderBy)) {
2617:                            if (targetType instanceof  RelatedType) {
2618:                                RelatedType targetRelatedType = (RelatedType) targetType;
2619:                                orderBy = targetRelatedType.getId()
2620:                                        .generateJavaSelect(null);
2621:                            }
2622:                        }
2623:
2624:                        orderByFields = new ArrayList<String>();
2625:                        orderByAscending = new ArrayList<Boolean>();
2626:
2627:                        int len = orderBy.length();
2628:
2629:                        int i = 0;
2630:
2631:                        while (i < len) {
2632:
2633:                            int index = orderBy.indexOf(",", i);
2634:
2635:                            if (index < 0)
2636:                                index = len;
2637:
2638:                            String orderByField = orderBy.substring(i, index);
2639:
2640:                            i += index;
2641:
2642:                            // ASC or DESC
2643:                            index = orderByField.toUpperCase()
2644:                                    .lastIndexOf("SC");
2645:
2646:                            Boolean asc = Boolean.TRUE;
2647:
2648:                            if (index > 1) {
2649:                                if (orderByField.charAt(index - 1) != 'E') {
2650:                                    // field ASC or default
2651:                                    if (orderByField.charAt(index - 1) == 'A'
2652:                                            && Character
2653:                                                    .isSpaceChar(orderByField
2654:                                                            .charAt(index - 2))) {
2655:                                        index -= 2;
2656:                                    }
2657:                                } else if (index > 2
2658:                                        && orderByField.charAt(index - 2) == 'D'
2659:                                        && Character.isSpaceChar(orderByField
2660:                                                .charAt(index - 3))) {
2661:
2662:                                    asc = Boolean.FALSE;
2663:                                    index -= 3;
2664:                                }
2665:                            }
2666:
2667:                            if (index > 0)
2668:                                orderByField = orderByField.substring(0, index)
2669:                                        .trim();
2670:
2671:                            AmberField amberField = targetType
2672:                                    .getField(orderByField);
2673:
2674:                            if (amberField == null)
2675:                                throw error(
2676:                                        _field,
2677:                                        L
2678:                                                .l(
2679:                                                        "'{0}' has no field named '{1}' in @OrderBy",
2680:                                                        targetType.getName(),
2681:                                                        orderByField));
2682:
2683:                            /*
2684:                            if (amberField instanceof PropertyField) {
2685:                              PropertyField property = (PropertyField) amberField;
2686:                              orderByField = property.getColumn().getName();
2687:                            }
2688:                             */
2689:
2690:                            orderByFields.add(orderByField);
2691:                            orderByAscending.add(asc);
2692:                        }
2693:                    }
2694:
2695:                    EntityOneToManyField oneToMany;
2696:
2697:                    oneToMany = new EntityOneToManyField(_relatedType,
2698:                            _fieldName, cascadeTypes);
2699:                    oneToMany.setSourceField(sourceField);
2700:                    oneToMany.setOrderBy(orderByFields, orderByAscending);
2701:
2702:                    getInternalMapKeyConfig(_relatedType.getBeanClass(),
2703:                            _field, _fieldName, _annotationCfg);
2704:                    JAnnotation mapKeyAnn = _annotationCfg.getAnnotation();
2705:                    MapKeyConfig mapKeyConfig = _annotationCfg
2706:                            .getMapKeyConfig();
2707:
2708:                    if (!_annotationCfg.isNull()) {
2709:
2710:                        String key = mapKeyAnn.getString("name");
2711:
2712:                        String getter = "get"
2713:                                + Character.toUpperCase(key.charAt(0))
2714:                                + key.substring(1);
2715:
2716:                        JMethod method = targetType.getGetter(getter);
2717:
2718:                        if (method == null) {
2719:                            throw error(
2720:                                    _field,
2721:                                    L
2722:                                            .l(
2723:                                                    "targetEntity '{0}' has no getter for field named '{1}'. Either the @MapKey name or the @OneToMany targetEntity is incorrect.",
2724:                                                    targetName, key));
2725:                        }
2726:
2727:                        oneToMany.setMapKey(key);
2728:                    }
2729:
2730:                    _relatedType.addField(oneToMany);
2731:                }
2732:
2733:                private void oneToManyUnidirectional(RelatedType targetType,
2734:                        String targetName, CascadeType[] cascadeTypes)
2735:                        throws ConfigException {
2736:                    EntityManyToManyField manyToManyField;
2737:
2738:                    manyToManyField = new EntityManyToManyField(_relatedType,
2739:                            _fieldName, cascadeTypes);
2740:                    manyToManyField.setType(targetType);
2741:
2742:                    String sqlTable = _relatedType.getTable().getName() + "_"
2743:                            + targetType.getTable().getName();
2744:
2745:                    JAnnotation joinTableAnn = _field
2746:                            .getAnnotation(javax.persistence.JoinTable.class);
2747:
2748:                    JoinTableConfig joinTableConfig = null;
2749:
2750:                    if (_oneToManyConfig != null)
2751:                        joinTableConfig = _oneToManyConfig.getJoinTable();
2752:
2753:                    Table mapTable = null;
2754:
2755:                    ArrayList<ForeignColumn> sourceColumns = null;
2756:                    ArrayList<ForeignColumn> targetColumns = null;
2757:
2758:                    if ((joinTableAnn != null) || (joinTableConfig != null)) {
2759:
2760:                        Object joinColumns[] = null;
2761:                        Object inverseJoinColumns[] = null;
2762:
2763:                        HashMap<String, JoinColumnConfig> joinColumnsConfig = null;
2764:                        HashMap<String, JoinColumnConfig> inverseJoinColumnsConfig = null;
2765:
2766:                        if (joinTableAnn != null) {
2767:                            if (!joinTableAnn.getString("name").equals(""))
2768:                                sqlTable = joinTableAnn.getString("name");
2769:
2770:                            joinColumns = (Object[]) joinTableAnn
2771:                                    .get("joinColumns");
2772:                            inverseJoinColumns = (Object[]) joinTableAnn
2773:                                    .get("inverseJoinColumns");
2774:                        } else {
2775:                            if (!joinTableConfig.getName().equals(""))
2776:                                sqlTable = joinTableConfig.getName();
2777:
2778:                            joinColumnsConfig = joinTableConfig
2779:                                    .getJoinColumnMap();
2780:                            inverseJoinColumnsConfig = joinTableConfig
2781:                                    .getInverseJoinColumnMap();
2782:                        }
2783:
2784:                        mapTable = _persistenceUnit.createTable(sqlTable);
2785:
2786:                        sourceColumns = AbstractConfigIntrospector
2787:                                .calculateColumns(
2788:                                        _field,
2789:                                        mapTable,
2790:                                        _relatedType.getTable().getName() + "_",
2791:                                        _relatedType, joinColumns,
2792:                                        joinColumnsConfig);
2793:
2794:                        targetColumns = AbstractConfigIntrospector
2795:                                .calculateColumns(_field, mapTable, targetType
2796:                                        .getTable().getName()
2797:                                        + "_", targetType, inverseJoinColumns,
2798:                                        inverseJoinColumnsConfig);
2799:                    } else {
2800:                        mapTable = _persistenceUnit.createTable(sqlTable);
2801:
2802:                        sourceColumns = AbstractConfigIntrospector
2803:                                .calculateColumns(mapTable, _relatedType
2804:                                        .getTable().getName()
2805:                                        + "_", _relatedType);
2806:
2807:                        targetColumns = AbstractConfigIntrospector
2808:                                .calculateColumns(mapTable,
2809:                                // jpa/0j40
2810:                                        toSqlName(_fieldName) + "_", targetType);
2811:                    }
2812:
2813:                    manyToManyField.setAssociationTable(mapTable);
2814:                    manyToManyField.setTable(sqlTable);
2815:
2816:                    manyToManyField.setSourceLink(new LinkColumns(mapTable,
2817:                            _relatedType.getTable(), sourceColumns));
2818:
2819:                    manyToManyField.setTargetLink(new LinkColumns(mapTable,
2820:                            targetType.getTable(), targetColumns));
2821:
2822:                    getInternalMapKeyConfig(_relatedType.getBeanClass(),
2823:                            _field, _field.getName(), _annotationCfg);
2824:                    JAnnotation mapKeyAnn = _annotationCfg.getAnnotation();
2825:                    MapKeyConfig mapKeyConfig = _annotationCfg
2826:                            .getMapKeyConfig();
2827:
2828:                    if (!_annotationCfg.isNull()) {
2829:
2830:                        String key;
2831:
2832:                        if (mapKeyAnn != null)
2833:                            key = mapKeyAnn.getString("name");
2834:                        else
2835:                            key = mapKeyConfig.getName();
2836:
2837:                        String getter = "get"
2838:                                + Character.toUpperCase(key.charAt(0))
2839:                                + key.substring(1);
2840:
2841:                        JMethod method = targetType.getGetter(getter);
2842:
2843:                        if (method == null) {
2844:                            throw error(
2845:                                    _field,
2846:                                    L
2847:                                            .l(
2848:                                                    "targetEntity '{0}' has no getter for field named '{1}'. Either the @MapKey name or the @ManyToMany targetEntity is incorrect.",
2849:                                                    targetName, key));
2850:                        }
2851:
2852:                        manyToManyField.setMapKey(key);
2853:                    }
2854:
2855:                    _relatedType.addField(manyToManyField);
2856:                }
2857:            }
2858:
2859:            /**
2860:             * completes for dependent
2861:             */
2862:            class OneToOneCompletion extends Completion {
2863:                private JAccessibleObject _field;
2864:                private String _fieldName;
2865:                private JClass _fieldType;
2866:
2867:                OneToOneCompletion(RelatedType type, JAccessibleObject field,
2868:                        String fieldName, JClass fieldType) {
2869:                    super (type, fieldName);
2870:
2871:                    _field = field;
2872:                    _fieldName = fieldName;
2873:                    _fieldType = fieldType;
2874:                }
2875:
2876:                String getFieldName() {
2877:                    return _fieldName;
2878:                }
2879:
2880:                void complete() throws ConfigException {
2881:                    getInternalOneToOneConfig(_relatedType.getBeanClass(),
2882:                            _field, _fieldName, _annotationCfg);
2883:                    JAnnotation oneToOneAnn = _annotationCfg.getAnnotation();
2884:                    OneToOneConfig oneToOneConfig = _annotationCfg
2885:                            .getOneToOneConfig();
2886:
2887:                    boolean isLazy;
2888:
2889:                    if (oneToOneAnn != null)
2890:                        isLazy = oneToOneAnn.get("fetch") == FetchType.LAZY;
2891:                    else
2892:                        isLazy = oneToOneConfig.getFetch() == FetchType.LAZY;
2893:
2894:                    if (!isLazy) {
2895:                        if (_relatedType.getBeanClass().getName().equals(
2896:                                _fieldType.getName())) {
2897:                            throw error(
2898:                                    _field,
2899:                                    L
2900:                                            .l(
2901:                                                    "'{0}': '{1}' is an illegal recursive type for @OneToOne with EAGER fetching. You should specify FetchType.LAZY for this relationship.",
2902:                                                    _field.getName(),
2903:                                                    _fieldType.getName()));
2904:                        }
2905:                    }
2906:
2907:                    AmberPersistenceUnit persistenceUnit = _relatedType
2908:                            .getPersistenceUnit();
2909:
2910:                    JClass targetEntity = null;
2911:                    String targetName = "";
2912:
2913:                    if (oneToOneAnn != null) {
2914:                        targetEntity = oneToOneAnn.getClass("targetEntity");
2915:
2916:                        if (targetEntity != null)
2917:                            targetEntity.getName();
2918:                    } else {
2919:                        targetName = oneToOneConfig.getTargetEntity();
2920:
2921:                        if (!((targetName == null) || "".equals(targetName)))
2922:                            targetEntity = _persistenceUnit.getJClassLoader()
2923:                                    .forName(targetName);
2924:                    }
2925:
2926:                    if (targetEntity == null
2927:                            || targetEntity.getName().equals("void"))
2928:                        targetEntity = _fieldType;
2929:
2930:                    getInternalEntityConfig(targetEntity, _annotationCfg);
2931:                    JAnnotation targetEntityAnn = _annotationCfg
2932:                            .getAnnotation();
2933:                    EntityConfig targetEntityConfig = _annotationCfg
2934:                            .getEntityConfig();
2935:
2936:                    if (_annotationCfg.isNull()) {
2937:                        throw error(
2938:                                _field,
2939:                                L
2940:                                        .l(
2941:                                                "'{0}' is an illegal targetEntity for {1}.  @OneToOne relations must target a valid @Entity.",
2942:                                                targetEntity.getName(), _field
2943:                                                        .getName()));
2944:                    }
2945:
2946:                    if (!_fieldType.isAssignableFrom(targetEntity)) {
2947:                        throw error(
2948:                                _field,
2949:                                L
2950:                                        .l(
2951:                                                "'{0}' is an illegal targetEntity for {1}.  @OneToOne targetEntity must be assignable to the field type '{2}'.",
2952:                                                targetEntity.getName(), _field
2953:                                                        .getName(), _fieldType
2954:                                                        .getName()));
2955:                    }
2956:
2957:                    String mappedBy;
2958:
2959:                    if (oneToOneAnn != null)
2960:                        mappedBy = oneToOneAnn.getString("mappedBy");
2961:                    else
2962:                        mappedBy = oneToOneConfig.getMappedBy();
2963:
2964:                    RelatedType targetType = null;
2965:
2966:                    if (targetName != null && !targetName.equals("")) {
2967:                        targetType = persistenceUnit.getEntityType(targetName);
2968:
2969:                        if (targetType == null)
2970:                            throw new ConfigException(
2971:                                    L
2972:                                            .l(
2973:                                                    "{0}: '{1}' is an unknown entity for '{2}'.",
2974:                                                    _field.getDeclaringClass()
2975:                                                            .getName(),
2976:                                                    targetName, _field
2977:                                                            .getName()));
2978:                    } else {
2979:                        targetType = persistenceUnit.getEntityType(_field
2980:                                .getReturnType().getName());
2981:
2982:                        if (targetType == null)
2983:                            throw new ConfigException(
2984:                                    L
2985:                                            .l(
2986:                                                    "{0} can't determine target name for '{1}'",
2987:                                                    _field.getDeclaringClass()
2988:                                                            .getName(), _field
2989:                                                            .getName()));
2990:                    }
2991:
2992:                    // jpa/0o00, jpa/0o03, jpa/0o06, jpa/0o07, jpa/10ca, jpa/0s2d
2993:
2994:                    // jpa/0o06
2995:                    boolean isManyToOne = (mappedBy == null)
2996:                            || "".equals(mappedBy);
2997:
2998:                    // jpa/0o07
2999:                    if (isManyToOne) {
3000:                        getInternalJoinColumnConfig(
3001:                                _relatedType.getBeanClass(), _field,
3002:                                _fieldName, _annotationCfg);
3003:                        JAnnotation joinColumnAnn = _annotationCfg
3004:                                .getAnnotation();
3005:                        JoinColumnConfig joinColumnConfig = _annotationCfg
3006:                                .getJoinColumnConfig();
3007:
3008:                        if (!_annotationCfg.isNull()) {
3009:                            // jpa/0o07: DstBean.getParent()
3010:                            // OK: isManyToOne = true;
3011:                        } else {
3012:                            // jpa/10ca
3013:                            OneToOneCompletion otherSide = getSourceCompletion(
3014:                                    targetType, mappedBy);
3015:
3016:                            if (otherSide != null) {
3017:                                getInternalJoinColumnConfig(targetType
3018:                                        .getBeanClass(), otherSide._field,
3019:                                        otherSide._fieldName, _annotationCfg);
3020:
3021:                                // jpa/0o07, jpa/0s2d
3022:                                if (!_annotationCfg.isNull())
3023:                                    isManyToOne = false;
3024:                            }
3025:                        }
3026:                    }
3027:
3028:                    // XXX: jpa/0ge4
3029:                    if (targetType.getParentType() != null) {
3030:                        if (targetType.getParentType() instanceof  MappedSuperclassType) {
3031:                            isManyToOne = false;
3032:
3033:                            OneToOneCompletion otherSide = getSourceCompletion(
3034:                                    targetType.getParentType(), mappedBy);
3035:
3036:                            if (otherSide != null) {
3037:                                // jpa/0ge4
3038:                                if (_depCompletions.remove(otherSide)) {
3039:                                    otherSide.complete();
3040:                                }
3041:                            }
3042:                        }
3043:                    }
3044:
3045:                    if (isManyToOne) {
3046:
3047:                        addManyToOne(_relatedType, _field, _fieldName, _field
3048:                                .getReturnType());
3049:
3050:                        // XXX: set unique
3051:                    } else {
3052:
3053:                        if (!(mappedBy == null || "".equals(mappedBy))) {
3054:
3055:                            // jpa/0o06
3056:
3057:                            OneToOneCompletion otherSide = getSourceCompletion(
3058:                                    targetType, mappedBy);
3059:
3060:                            if (otherSide != null) {
3061:                                // jpa/0o00
3062:                                if (_depCompletions.remove(otherSide)) {
3063:                                    otherSide.complete();
3064:                                }
3065:                            }
3066:                        }
3067:
3068:                        // Owner
3069:                        EntityManyToOneField sourceField = getSourceField(
3070:                                targetType, mappedBy, _relatedType);
3071:
3072:                        if (sourceField == null) {
3073:                            throw new ConfigException(
3074:                                    L
3075:                                            .l(
3076:                                                    "{0}: OneToOne target '{1}' does not have a matching ManyToOne relation.",
3077:                                                    _field.getDeclaringClass()
3078:                                                            .getName(),
3079:                                                    targetType.getName()));
3080:                        }
3081:
3082:                        DependentEntityOneToOneField oneToOne;
3083:
3084:                        CascadeType cascadeTypes[] = null;
3085:
3086:                        if (oneToOneAnn != null) {
3087:                            // jpa/0o33
3088:
3089:                            // XXX: runtime does not cast this
3090:                            // cascadeType = (CascadeType []) manyToOneAnn.get("cascade");
3091:                            Object cascade[] = (Object[]) oneToOneAnn
3092:                                    .get("cascade");
3093:
3094:                            cascadeTypes = new CascadeType[cascade.length];
3095:
3096:                            for (int i = 0; i < cascade.length; i++)
3097:                                cascadeTypes[i] = (CascadeType) cascade[i];
3098:                        }
3099:
3100:                        oneToOne = new DependentEntityOneToOneField(
3101:                                _relatedType, _fieldName, cascadeTypes);
3102:                        oneToOne.setTargetField(sourceField);
3103:                        sourceField.setTargetField(oneToOne);
3104:                        oneToOne.setLazy(isLazy);
3105:
3106:                        _relatedType.addField(oneToOne);
3107:                    }
3108:                }
3109:            }
3110:
3111:            /**
3112:             * completes for dependent
3113:             */
3114:            class ManyToManyCompletion extends Completion {
3115:                private JAccessibleObject _field;
3116:                private String _fieldName;
3117:                private JClass _fieldType;
3118:
3119:                ManyToManyCompletion(RelatedType type, JAccessibleObject field,
3120:                        String fieldName, JClass fieldType) {
3121:                    super (type, fieldName);
3122:
3123:                    _field = field;
3124:                    _fieldName = fieldName;
3125:                    _fieldType = fieldType;
3126:                }
3127:
3128:                void complete() throws ConfigException {
3129:                    addManyToMany(_relatedType, _field, _fieldName, _fieldType);
3130:                }
3131:            }
3132:
3133:            /**
3134:             * completes for link
3135:             */
3136:            class ManyToOneCompletion extends Completion {
3137:                private JAccessibleObject _field;
3138:                private String _fieldName;
3139:                private JClass _fieldType;
3140:
3141:                ManyToOneCompletion(RelatedType type, JAccessibleObject field,
3142:                        String fieldName, JClass fieldType) {
3143:                    super (type, fieldName);
3144:
3145:                    _field = field;
3146:                    _fieldName = fieldName;
3147:                    _fieldType = fieldType;
3148:                }
3149:
3150:                void complete() throws ConfigException {
3151:                    addManyToOne(_relatedType, _field, _fieldName, _fieldType);
3152:                }
3153:            }
3154:
3155:            /**
3156:             * completes for dependent
3157:             */
3158:            class EmbeddedCompletion extends Completion {
3159:                private JAccessibleObject _field;
3160:                private String _fieldName;
3161:                private JClass _fieldType;
3162:                // The same completion is used for both:
3163:                // @Embedded or @EmbeddedId
3164:                private boolean _embeddedId;
3165:
3166:                EmbeddedCompletion(RelatedType type, JAccessibleObject field,
3167:                        String fieldName, JClass fieldType, boolean embeddedId) {
3168:                    super (type, fieldName);
3169:
3170:                    _field = field;
3171:                    _fieldName = fieldName;
3172:                    _fieldType = fieldType;
3173:                    _embeddedId = embeddedId;
3174:                }
3175:
3176:                void complete() throws ConfigException {
3177:                    getInternalAttributeOverrideConfig(_relatedType
3178:                            .getBeanClass(), _annotationCfg);
3179:                    JAnnotation attributeOverrideAnn = _annotationCfg
3180:                            .getAnnotation();
3181:                    AttributeOverrideConfig attributeOverrideConfig = _annotationCfg
3182:                            .getAttributeOverrideConfig();
3183:
3184:                    boolean hasAttributeOverride = !_annotationCfg.isNull();
3185:
3186:                    JAnnotation attributeOverridesAnn = _field
3187:                            .getAnnotation(AttributeOverrides.class);
3188:
3189:                    boolean hasAttributeOverrides = (attributeOverridesAnn != null);
3190:
3191:                    if (hasAttributeOverride && hasAttributeOverrides) {
3192:                        throw error(
3193:                                _field,
3194:                                L
3195:                                        .l(
3196:                                                "{0} may not have both @AttributeOverride and @AttributeOverrides",
3197:                                                _field.getName()));
3198:                    }
3199:
3200:                    Object attOverridesAnn[] = null;
3201:
3202:                    if (attributeOverrideAnn != null) {
3203:                        attOverridesAnn = new Object[] { attributeOverrideAnn };
3204:                    } else if (attributeOverridesAnn != null) {
3205:                        attOverridesAnn = (Object[]) attributeOverridesAnn
3206:                                .get("value");
3207:                    }
3208:
3209:                    AmberPersistenceUnit persistenceUnit = _relatedType
3210:                            .getPersistenceUnit();
3211:
3212:                    EmbeddableType type = persistenceUnit
3213:                            .createEmbeddable(_fieldType);
3214:
3215:                    EntityEmbeddedField embeddedField;
3216:
3217:                    if (_embeddedId) {
3218:                        embeddedField = _relatedType.getId()
3219:                                .getEmbeddedIdField();
3220:                    } else {
3221:                        embeddedField = new EntityEmbeddedField(_relatedType,
3222:                                type, _fieldName);
3223:                    }
3224:
3225:                    // embeddedField.setEmbeddedId(_embeddedId);
3226:
3227:                    embeddedField.setLazy(false);
3228:
3229:                    _relatedType.addField(embeddedField);
3230:
3231:                    // XXX: todo ...
3232:                    // validateAttributeOverrides(_field, attributeOverridesAnn, type);
3233:
3234:                    Table sourceTable = _relatedType.getTable();
3235:
3236:                    HashMap<String, Column> embeddedColumns = new HashMap<String, Column>();
3237:                    HashMap<String, String> fieldNameByColumn = new HashMap<String, String>();
3238:
3239:                    for (EmbeddedSubField subField : embeddedField
3240:                            .getSubFields()) {
3241:                        String embeddedFieldName = subField.getName();
3242:
3243:                        String columnName = toSqlName(embeddedFieldName);
3244:                        boolean notNull = false;
3245:                        boolean unique = false;
3246:
3247:                        if (attOverridesAnn != null) {
3248:                            for (int j = 0; j < attOverridesAnn.length; j++) {
3249:
3250:                                if (embeddedFieldName
3251:                                        .equals(((JAnnotation) attOverridesAnn[j])
3252:                                                .getString("name"))) {
3253:
3254:                                    JAnnotation columnAnn = ((JAnnotation) attOverridesAnn[j])
3255:                                            .getAnnotation("column");
3256:
3257:                                    if (columnAnn != null) {
3258:                                        columnName = columnAnn
3259:                                                .getString("name");
3260:                                        notNull = !columnAnn
3261:                                                .getBoolean("nullable");
3262:                                        unique = columnAnn.getBoolean("unique");
3263:
3264:                                        subField.getColumn()
3265:                                                .setName(columnName);
3266:                                        subField.getColumn()
3267:                                                .setNotNull(notNull);
3268:                                        subField.getColumn().setUnique(unique);
3269:                                    }
3270:                                }
3271:                            }
3272:                        }
3273:
3274:                        /*
3275:                            Type amberType = _persistenceUnit.createType(fields.get(i).getJavaType().getName());
3276:
3277:                            Column column = sourceTable.createColumn(columnName, amberType);
3278:
3279:                            column.setNotNull(notNull);
3280:                            column.setUnique(unique);
3281:
3282:                            embeddedColumns.put(columnName, column);
3283:                            fieldNameByColumn.put(columnName, embeddedFieldName);
3284:                         */
3285:                    }
3286:
3287:                    /*
3288:                    embeddedField.setEmbeddedColumns(embeddedColumns);
3289:                    embeddedField.setFieldNameByColumn(fieldNameByColumn);
3290:                     */
3291:
3292:                    embeddedField.init();
3293:                }
3294:            }
3295:
3296:            /**
3297:             * completes for dependent
3298:             */
3299:            class SqlResultSetMappingCompletion extends Completion {
3300:                private String _name;
3301:                private Object _entities[];
3302:                private Object _columns[];
3303:
3304:                SqlResultSetMappingCompletion(RelatedType type, String name,
3305:                        Object entities[], Object columns[]) {
3306:                    super (type);
3307:
3308:                    _name = name;
3309:                    _entities = entities;
3310:                    _columns = columns;
3311:                }
3312:
3313:                void complete() throws ConfigException {
3314:                    addSqlResultSetMapping(_name, _entities, _columns);
3315:                }
3316:            }
3317:
3318:            /**
3319:             * completes for link
3320:             */
3321:            class AttributeOverrideCompletion extends Completion {
3322:                private JClass _type;
3323:
3324:                AttributeOverrideCompletion(RelatedType relatedType, JClass type) {
3325:                    super (relatedType);
3326:
3327:                    _type = type;
3328:                }
3329:
3330:                void complete() throws ConfigException {
3331:                    getInternalAttributeOverrideConfig(_type, _annotationCfg);
3332:                    JAnnotation attributeOverrideAnn = _annotationCfg
3333:                            .getAnnotation();
3334:
3335:                    boolean hasAttributeOverride = (attributeOverrideAnn != null);
3336:
3337:                    JAnnotation attributeOverridesAnn = _type
3338:                            .getAnnotation(AttributeOverrides.class);
3339:
3340:                    ArrayList<AttributeOverrideConfig> attributeOverrideList = null;
3341:
3342:                    EntityConfig entityConfig = getEntityConfig(_type.getName());
3343:
3344:                    if (entityConfig != null)
3345:                        attributeOverrideList = entityConfig
3346:                                .getAttributeOverrideList();
3347:
3348:                    boolean hasAttributeOverrides = false;
3349:
3350:                    if ((attributeOverrideList != null)
3351:                            && (attributeOverrideList.size() > 0)) {
3352:                        hasAttributeOverrides = true;
3353:                    } else if (attributeOverridesAnn != null)
3354:                        hasAttributeOverrides = true;
3355:
3356:                    if (hasAttributeOverride && hasAttributeOverrides)
3357:                        throw new ConfigException(
3358:                                L
3359:                                        .l(
3360:                                                "{0} may not have both @AttributeOverride and @AttributeOverrides",
3361:                                                _type));
3362:
3363:                    if (attributeOverrideList == null)
3364:                        attributeOverrideList = new ArrayList<AttributeOverrideConfig>();
3365:
3366:                    if (hasAttributeOverride) {
3367:                        // Convert annotation to configuration.
3368:
3369:                        AttributeOverrideConfig attOverrideConfig = convertAttributeOverrideAnnotationToConfig(attributeOverrideAnn);
3370:
3371:                        attributeOverrideList.add(attOverrideConfig);
3372:                    } else if (hasAttributeOverrides) {
3373:                        if (attributeOverrideList.size() > 0) {
3374:                            // OK: attributeOverrideList came from orm.xml
3375:                        } else {
3376:                            // Convert annotations to configurations.
3377:
3378:                            Object attOverridesAnn[] = (Object[]) attributeOverridesAnn
3379:                                    .get("value");
3380:
3381:                            AttributeOverrideConfig attOverrideConfig;
3382:
3383:                            for (int i = 0; i < attOverridesAnn.length; i++) {
3384:                                attOverrideConfig = convertAttributeOverrideAnnotationToConfig((JAnnotation) attOverridesAnn[i]);
3385:
3386:                                attributeOverrideList.add(attOverrideConfig);
3387:                            }
3388:                        }
3389:                    }
3390:
3391:                    // jpa/0ge8, jpa/0ge9, jpa/0gea
3392:                    // Fields which have not been overridden are added to the
3393:                    // entity subclass. This makes the columns to be properly
3394:                    // created at each entity table -- not the mapped superclass
3395:                    // table, even because the parent might not have a valid table.
3396:
3397:                    RelatedType parent = _relatedType.getParentType();
3398:
3399:                    ArrayList<AmberField> fields = parent.getFields();
3400:
3401:                    for (AmberField field : fields) {
3402:                        String fieldName = field.getName();
3403:
3404:                        AttributeOverrideConfig attOverrideConfig = null;
3405:
3406:                        int i = 0;
3407:
3408:                        for (; i < attributeOverrideList.size(); i++) {
3409:                            attOverrideConfig = attributeOverrideList.get(i);
3410:
3411:                            if (fieldName.equals(attOverrideConfig.getName())) {
3412:                                break;
3413:                            }
3414:                        }
3415:
3416:                        if (i < attributeOverrideList.size())
3417:                            continue;
3418:
3419:                        if (field instanceof  PropertyField) {
3420:                            Column column = ((PropertyField) field).getColumn();
3421:
3422:                            // jpa/0ge8, jpa/0gea
3423:                            // Creates the missing attribute override config.
3424:                            attOverrideConfig = createAttributeOverrideConfig(
3425:                                    fieldName, column.getName(), !column
3426:                                            .isNotNull(), column.isUnique());
3427:
3428:                            attributeOverrideList.add(attOverrideConfig);
3429:                        }
3430:                    }
3431:
3432:                    // jpa/0ge8, jpa/0ge9
3433:                    // Similar code to create any missing configuration for keys.
3434:
3435:                    com.caucho.amber.field.Id parentId = parent.getId();
3436:
3437:                    // jpa/0ge6
3438:                    if (parentId != null) {
3439:                        ArrayList<IdField> keys = parentId.getKeys();
3440:
3441:                        for (IdField field : keys) {
3442:                            String fieldName = field.getName();
3443:
3444:                            AttributeOverrideConfig attOverrideConfig = null;
3445:
3446:                            int i = 0;
3447:
3448:                            for (; i < attributeOverrideList.size(); i++) {
3449:                                attOverrideConfig = attributeOverrideList
3450:                                        .get(i);
3451:
3452:                                if (fieldName.equals(attOverrideConfig
3453:                                        .getName())) {
3454:                                    break;
3455:                                }
3456:                            }
3457:
3458:                            if (i < attributeOverrideList.size())
3459:                                continue;
3460:
3461:                            if (field instanceof  KeyPropertyField) {
3462:                                try {
3463:                                    if (_relatedType.isFieldAccess())
3464:                                        introspectIdField(_persistenceUnit,
3465:                                                _relatedType, null, parent
3466:                                                        .getBeanClass(), null,
3467:                                                null);
3468:                                    else
3469:                                        introspectIdMethod(_persistenceUnit,
3470:                                                _relatedType, null, parent
3471:                                                        .getBeanClass(), null,
3472:                                                null);
3473:                                } catch (SQLException e) {
3474:                                    throw ConfigException.create(e);
3475:                                }
3476:
3477:                                field = _relatedType.getId().getKeys().get(0);
3478:
3479:                                Column column = ((KeyPropertyField) field)
3480:                                        .getColumn();
3481:
3482:                                // jpa/0ge8, jpa/0ge9, jpa/0gea
3483:                                // Creates the missing attribute override config.
3484:                                attOverrideConfig = createAttributeOverrideConfig(
3485:                                        fieldName, column.getName(), !column
3486:                                                .isNotNull(), column.isUnique());
3487:
3488:                                attributeOverrideList.add(attOverrideConfig);
3489:                            }
3490:                        }
3491:                    }
3492:
3493:                    // Overrides fields from MappedSuperclass.
3494:
3495:                    Table sourceTable = _relatedType.getTable();
3496:
3497:                    for (int i = 0; i < attributeOverrideList.size(); i++) {
3498:
3499:                        AttributeOverrideConfig attOverrideConfig = attributeOverrideList
3500:                                .get(i);
3501:
3502:                        String entityFieldName;
3503:                        String columnName;
3504:                        boolean notNull = false;
3505:                        boolean unique = false;
3506:
3507:                        Type amberType = null;
3508:
3509:                        for (int j = 0; j < fields.size(); j++) {
3510:
3511:                            AmberField field = fields.get(j);
3512:
3513:                            if (!(field instanceof  PropertyField)) {
3514:                                // jpa/0ge3: relationship fields are fully mapped in the
3515:                                // mapped superclass, i.e., are not included in @AttributeOverrides
3516:                                // and can be added to the entity right away.
3517:
3518:                                // Adds only once.
3519:                                if (i == 0) {
3520:                                    _relatedType
3521:                                            .addMappedSuperclassField(field);
3522:                                }
3523:
3524:                                continue;
3525:                            }
3526:
3527:                            entityFieldName = field.getName();
3528:
3529:                            columnName = toSqlName(entityFieldName);
3530:
3531:                            if (entityFieldName.equals(attOverrideConfig
3532:                                    .getName())) {
3533:
3534:                                ColumnConfig columnConfig = attOverrideConfig
3535:                                        .getColumn();
3536:
3537:                                if (columnConfig != null) {
3538:                                    columnName = columnConfig.getName();
3539:                                    notNull = !columnConfig.getNullable();
3540:                                    unique = columnConfig.getUnique();
3541:                                    amberType = _persistenceUnit
3542:                                            .createType(field.getJavaType()
3543:                                                    .getName());
3544:
3545:                                    Column column = sourceTable.createColumn(
3546:                                            columnName, amberType);
3547:
3548:                                    column.setNotNull(notNull);
3549:                                    column.setUnique(unique);
3550:
3551:                                    PropertyField overriddenField = new PropertyField(
3552:                                            field.getSourceType(), field
3553:                                                    .getName());
3554:
3555:                                    overriddenField
3556:                                            .setType(((PropertyField) field)
3557:                                                    .getType());
3558:                                    overriddenField.setLazy(field.isLazy());
3559:                                    overriddenField.setColumn(column);
3560:
3561:                                    _relatedType
3562:                                            .addMappedSuperclassField(overriddenField);
3563:                                }
3564:                            }
3565:                        }
3566:
3567:                        if (_relatedType.getId() != null) {
3568:                            ArrayList<IdField> keys = _relatedType.getId()
3569:                                    .getKeys();
3570:
3571:                            for (int j = 0; j < keys.size(); j++) {
3572:
3573:                                IdField field = keys.get(j);
3574:
3575:                                entityFieldName = field.getName();
3576:
3577:                                columnName = toSqlName(entityFieldName);
3578:
3579:                                if (entityFieldName.equals(attOverrideConfig
3580:                                        .getName())) {
3581:
3582:                                    ColumnConfig columnConfig = attOverrideConfig
3583:                                            .getColumn();
3584:
3585:                                    if (columnConfig != null) {
3586:                                        columnName = columnConfig.getName();
3587:                                        notNull = !columnConfig.getNullable();
3588:                                        unique = columnConfig.getUnique();
3589:                                        amberType = _persistenceUnit
3590:                                                .createType(field.getJavaType()
3591:                                                        .getName());
3592:
3593:                                        Column column = sourceTable
3594:                                                .createColumn(columnName,
3595:                                                        amberType);
3596:
3597:                                        column.setNotNull(notNull);
3598:                                        column.setUnique(unique);
3599:
3600:                                        if (field instanceof  KeyPropertyField) {
3601:                                            KeyPropertyField overriddenField = new KeyPropertyField(
3602:                                                    (RelatedType) field
3603:                                                            .getSourceType(),
3604:                                                    field.getName());
3605:
3606:                                            overriddenField.setGenerator(field
3607:                                                    .getGenerator());
3608:                                            overriddenField.setColumn(column);
3609:
3610:                                            // XXX: needs to handle compound pk with @AttributeOverride ???
3611:                                            if (keys.size() == 1) {
3612:                                                keys.remove(0);
3613:                                                keys.add(overriddenField);
3614:                                                _relatedType
3615:                                                        .setId(new com.caucho.amber.field.Id(
3616:                                                                _relatedType,
3617:                                                                keys));
3618:                                            }
3619:                                        }
3620:                                    }
3621:                                }
3622:                            }
3623:                        }
3624:                    }
3625:                }
3626:            }
3627:
3628:            void getInternalEmbeddableConfig(JClass type,
3629:                    AnnotationConfig annotationCfg) {
3630:                annotationCfg.reset(type, Embeddable.class);
3631:
3632:                EmbeddableConfig embeddableConfig = null;
3633:
3634:                if (_embeddableConfigMap != null)
3635:                    embeddableConfig = _embeddableConfigMap.get(type.getName());
3636:
3637:                annotationCfg.setConfig(embeddableConfig);
3638:            }
3639:
3640:            void getInternalEntityConfig(JClass type,
3641:                    AnnotationConfig annotationCfg) {
3642:                annotationCfg.reset(type, Entity.class);
3643:
3644:                EntityConfig entityConfig = getEntityConfig(type.getName());
3645:
3646:                annotationCfg.setConfig(entityConfig);
3647:            }
3648:
3649:            void getInternalMappedSuperclassConfig(JClass type,
3650:                    AnnotationConfig annotationCfg) {
3651:                annotationCfg.reset(type, MappedSuperclass.class);
3652:
3653:                MappedSuperclassConfig mappedSuperConfig = getMappedSuperclassConfig(type
3654:                        .getName());
3655:
3656:                annotationCfg.setConfig(mappedSuperConfig);
3657:            }
3658:
3659:            void getInternalEntityListenersConfig(JClass type,
3660:                    AnnotationConfig annotationCfg) {
3661:                annotationCfg.reset(type, EntityListeners.class);
3662:
3663:                EntityConfig entityConfig = getEntityConfig(type.getName());
3664:
3665:                if (entityConfig == null)
3666:                    return;
3667:
3668:                annotationCfg.setConfig(entityConfig.getEntityListeners());
3669:            }
3670:
3671:            void getInternalExcludeDefaultListenersConfig(JClass type,
3672:                    AnnotationConfig annotationCfg) {
3673:                annotationCfg.reset(type, ExcludeDefaultListeners.class);
3674:
3675:                MappedSuperclassConfig entityConfig = getInternalMappedSuperclassOrEntityConfig(type
3676:                        .getName());
3677:
3678:                if (entityConfig == null)
3679:                    return;
3680:
3681:                if (entityConfig.getExcludeDefaultListeners())
3682:                    annotationCfg.setConfig(entityConfig
3683:                            .getExcludeDefaultListeners());
3684:            }
3685:
3686:            void getInternalExcludeSuperclassListenersConfig(JClass type,
3687:                    AnnotationConfig annotationCfg) {
3688:                annotationCfg.reset(type, ExcludeSuperclassListeners.class);
3689:
3690:                MappedSuperclassConfig entityConfig = getInternalMappedSuperclassOrEntityConfig(type
3691:                        .getName());
3692:
3693:                if (entityConfig == null)
3694:                    return;
3695:
3696:                if (entityConfig.getExcludeSuperclassListeners())
3697:                    annotationCfg.setConfig(entityConfig
3698:                            .getExcludeSuperclassListeners());
3699:            }
3700:
3701:            void getInternalInheritanceConfig(JClass type,
3702:                    AnnotationConfig annotationCfg) {
3703:                annotationCfg.reset(type, Inheritance.class);
3704:
3705:                EntityConfig entityConfig = getEntityConfig(type.getName());
3706:
3707:                if (entityConfig != null) {
3708:                    annotationCfg.setConfig(entityConfig.getInheritance());
3709:                }
3710:            }
3711:
3712:            void getInternalNamedQueryConfig(JClass type,
3713:                    AnnotationConfig annotationCfg) {
3714:                annotationCfg.reset(type, NamedQuery.class);
3715:
3716:                EntityConfig entityConfig = getEntityConfig(type.getName());
3717:
3718:                if (entityConfig != null) {
3719:                    annotationCfg.setConfig(entityConfig.getNamedQuery());
3720:                }
3721:            }
3722:
3723:            void getInternalNamedNativeQueryConfig(JClass type,
3724:                    AnnotationConfig annotationCfg) {
3725:                annotationCfg.reset(type, NamedNativeQuery.class);
3726:
3727:                EntityConfig entityConfig = getEntityConfig(type.getName());
3728:
3729:                if (entityConfig != null) {
3730:                    annotationCfg.setConfig(entityConfig.getNamedNativeQuery());
3731:                }
3732:            }
3733:
3734:            void getInternalSqlResultSetMappingConfig(JClass type,
3735:                    AnnotationConfig annotationCfg) {
3736:                annotationCfg.reset(type, SqlResultSetMapping.class);
3737:
3738:                EntityConfig entityConfig = getEntityConfig(type.getName());
3739:
3740:                if (entityConfig != null) {
3741:                    annotationCfg.setConfig(entityConfig
3742:                            .getSqlResultSetMapping());
3743:                }
3744:            }
3745:
3746:            void getInternalTableConfig(JClass type,
3747:                    AnnotationConfig annotationCfg) {
3748:                annotationCfg.reset(type, javax.persistence.Table.class);
3749:
3750:                EntityConfig entityConfig = getEntityConfig(type.getName());
3751:
3752:                if (entityConfig != null) {
3753:                    annotationCfg.setConfig(entityConfig.getTable());
3754:                }
3755:            }
3756:
3757:            void getInternalSecondaryTableConfig(JClass type,
3758:                    AnnotationConfig annotationCfg) {
3759:                annotationCfg.reset(type, SecondaryTable.class);
3760:
3761:                EntityConfig entityConfig = getEntityConfig(type.getName());
3762:
3763:                if (entityConfig != null) {
3764:                    annotationCfg.setConfig(entityConfig.getSecondaryTable());
3765:                }
3766:            }
3767:
3768:            void getInternalIdClassConfig(JClass type,
3769:                    AnnotationConfig annotationCfg) {
3770:                annotationCfg.reset(type, IdClass.class);
3771:
3772:                MappedSuperclassConfig entityConfig = getInternalMappedSuperclassOrEntityConfig(type
3773:                        .getName());
3774:
3775:                if (entityConfig == null)
3776:                    return;
3777:
3778:                annotationCfg.setConfig(entityConfig.getIdClass());
3779:            }
3780:
3781:            void getInternalPrimaryKeyJoinColumnConfig(JClass type,
3782:                    AnnotationConfig annotationCfg) {
3783:                annotationCfg.reset(type, PrimaryKeyJoinColumn.class);
3784:
3785:                EntityConfig entityConfig = getEntityConfig(type.getName());
3786:
3787:                if (entityConfig != null) {
3788:                    annotationCfg.setConfig(entityConfig
3789:                            .getPrimaryKeyJoinColumn());
3790:                }
3791:            }
3792:
3793:            void getInternalDiscriminatorColumnConfig(JClass type,
3794:                    AnnotationConfig annotationCfg) {
3795:                annotationCfg.reset(type, DiscriminatorColumn.class);
3796:
3797:                EntityConfig entityConfig = getEntityConfig(type.getName());
3798:
3799:                if (entityConfig != null) {
3800:                    annotationCfg.setConfig(entityConfig
3801:                            .getDiscriminatorColumn());
3802:                }
3803:            }
3804:
3805:            void getInternalOneToOneConfig(JClass type,
3806:                    JAccessibleObject field, String fieldName,
3807:                    AnnotationConfig annotationCfg) {
3808:                annotationCfg.reset(field, OneToOne.class);
3809:
3810:                MappedSuperclassConfig entityConfig = getInternalMappedSuperclassOrEntityConfig(type
3811:                        .getName());
3812:
3813:                if (entityConfig == null)
3814:                    return;
3815:
3816:                AttributesConfig attributes = entityConfig.getAttributes();
3817:
3818:                if (attributes != null) {
3819:                    OneToOneConfig oneToOne = attributes.getOneToOne(fieldName);
3820:
3821:                    annotationCfg.setConfig(oneToOne);
3822:                }
3823:            }
3824:
3825:            void getInternalOneToManyConfig(JClass type,
3826:                    JAccessibleObject field, String fieldName,
3827:                    AnnotationConfig annotationCfg) {
3828:                annotationCfg.reset(field, OneToMany.class);
3829:
3830:                MappedSuperclassConfig entityConfig = getInternalMappedSuperclassOrEntityConfig(type
3831:                        .getName());
3832:
3833:                if (entityConfig == null)
3834:                    return;
3835:
3836:                AttributesConfig attributes = entityConfig.getAttributes();
3837:
3838:                if (attributes != null) {
3839:                    OneToManyConfig oneToMany = attributes
3840:                            .getOneToMany(fieldName);
3841:
3842:                    annotationCfg.setConfig(oneToMany);
3843:                }
3844:            }
3845:
3846:            void getInternalManyToOneConfig(JClass type,
3847:                    JAccessibleObject field, String fieldName,
3848:                    AnnotationConfig annotationCfg) {
3849:                annotationCfg.reset(field, ManyToOne.class);
3850:
3851:                MappedSuperclassConfig entityConfig = getInternalMappedSuperclassOrEntityConfig(type
3852:                        .getName());
3853:
3854:                if (entityConfig == null)
3855:                    return;
3856:
3857:                AttributesConfig attributes = entityConfig.getAttributes();
3858:
3859:                if (attributes != null) {
3860:                    ManyToOneConfig manyToOne = attributes
3861:                            .getManyToOne(fieldName);
3862:
3863:                    annotationCfg.setConfig(manyToOne);
3864:                }
3865:            }
3866:
3867:            void getInternalManyToManyConfig(JClass type,
3868:                    JAccessibleObject field, String fieldName,
3869:                    AnnotationConfig annotationCfg) {
3870:                annotationCfg.reset(field, ManyToMany.class);
3871:
3872:                MappedSuperclassConfig entityConfig = getInternalMappedSuperclassOrEntityConfig(type
3873:                        .getName());
3874:
3875:                if (entityConfig == null)
3876:                    return;
3877:
3878:                AttributesConfig attributes = entityConfig.getAttributes();
3879:
3880:                if (attributes != null) {
3881:                    ManyToManyConfig manyToMany = attributes
3882:                            .getManyToMany(fieldName);
3883:
3884:                    annotationCfg.setConfig(manyToMany);
3885:                }
3886:            }
3887:
3888:            void getInternalIdConfig(JClass type, JAccessibleObject method,
3889:                    String fieldName, AnnotationConfig annotationCfg) {
3890:                annotationCfg.reset(method, javax.persistence.Id.class);
3891:
3892:                MappedSuperclassConfig mappedSuperclassOrEntityConfig = getInternalMappedSuperclassOrEntityConfig(type
3893:                        .getName());
3894:
3895:                if (mappedSuperclassOrEntityConfig == null)
3896:                    return;
3897:
3898:                AttributesConfig attributes = mappedSuperclassOrEntityConfig
3899:                        .getAttributes();
3900:
3901:                if (attributes != null) {
3902:                    IdConfig id = attributes.getId(fieldName);
3903:
3904:                    annotationCfg.setConfig(id);
3905:                }
3906:            }
3907:
3908:            void getInternalCallbackConfig(int callback, JClass type,
3909:                    JAccessibleObject method, String fieldName,
3910:                    AnnotationConfig annotationCfg) {
3911:                annotationCfg.reset(method,
3912:                        ListenerType.CALLBACK_CLASS[callback]);
3913:
3914:                MappedSuperclassConfig entityConfig = getInternalMappedSuperclassOrEntityConfig(type
3915:                        .getName());
3916:
3917:                if (entityConfig == null)
3918:                    return;
3919:
3920:                AbstractListenerConfig callbackConfig;
3921:
3922:                switch (callback) {
3923:                case Listener.PRE_PERSIST:
3924:                    callbackConfig = entityConfig.getPrePersist();
3925:                    break;
3926:                case Listener.POST_PERSIST:
3927:                    callbackConfig = entityConfig.getPostPersist();
3928:                    break;
3929:                case Listener.PRE_REMOVE:
3930:                    callbackConfig = entityConfig.getPreRemove();
3931:                    break;
3932:                case Listener.POST_REMOVE:
3933:                    callbackConfig = entityConfig.getPostRemove();
3934:                    break;
3935:                case Listener.PRE_UPDATE:
3936:                    callbackConfig = entityConfig.getPreUpdate();
3937:                    break;
3938:                case Listener.POST_UPDATE:
3939:                    callbackConfig = entityConfig.getPostUpdate();
3940:                    break;
3941:                case Listener.POST_LOAD:
3942:                    callbackConfig = entityConfig.getPostLoad();
3943:                    break;
3944:                default:
3945:                    return;
3946:                }
3947:
3948:                if (callbackConfig == null)
3949:                    return;
3950:
3951:                if (callbackConfig.getMethodName().equals(method.getName()))
3952:                    annotationCfg.setConfig(callbackConfig);
3953:            }
3954:
3955:            void getInternalEmbeddedIdConfig(JClass type,
3956:                    JAccessibleObject method, String fieldName,
3957:                    AnnotationConfig annotationCfg) {
3958:                annotationCfg.reset(method, EmbeddedId.class);
3959:            }
3960:
3961:            void getInternalVersionConfig(JClass type,
3962:                    JAccessibleObject method, String fieldName,
3963:                    AnnotationConfig annotationCfg) {
3964:                annotationCfg.reset(method, Version.class);
3965:            }
3966:
3967:            void getInternalJoinColumnConfig(JClass type,
3968:                    JAccessibleObject field, String fieldName,
3969:                    AnnotationConfig annotationCfg) {
3970:                annotationCfg.reset(field, JoinColumn.class);
3971:            }
3972:
3973:            void getInternalJoinTableConfig(JClass type,
3974:                    JAccessibleObject field, String fieldName,
3975:                    AnnotationConfig annotationCfg) {
3976:                annotationCfg.reset(field, JoinTable.class);
3977:            }
3978:
3979:            void getInternalMapKeyConfig(JClass type, JAccessibleObject field,
3980:                    String fieldName, AnnotationConfig annotationCfg) {
3981:                annotationCfg.reset(field, MapKey.class);
3982:            }
3983:
3984:            void getInternalAttributeOverrideConfig(JClass type,
3985:                    AnnotationConfig annotationCfg) {
3986:                annotationCfg.reset(type, AttributeOverride.class);
3987:            }
3988:
3989:            private MappedSuperclassConfig getInternalMappedSuperclassOrEntityConfig(
3990:                    String name) {
3991:                MappedSuperclassConfig mappedSuperclassConfig = null;
3992:
3993:                mappedSuperclassConfig = getEntityConfig(name);
3994:
3995:                if (mappedSuperclassConfig != null)
3996:                    return mappedSuperclassConfig;
3997:
3998:                mappedSuperclassConfig = getMappedSuperclassConfig(name);
3999:
4000:                return mappedSuperclassConfig;
4001:            }
4002:
4003:            private static AttributeOverrideConfig convertAttributeOverrideAnnotationToConfig(
4004:                    JAnnotation attOverrideAnn) {
4005:                JAnnotation columnAnn = attOverrideAnn.getAnnotation("column");
4006:
4007:                return createAttributeOverrideConfig(attOverrideAnn
4008:                        .getString("name"), columnAnn.getString("name"),
4009:                        columnAnn.getBoolean("nullable"), columnAnn
4010:                                .getBoolean("unique"));
4011:            }
4012:
4013:            private static AttributeOverrideConfig createAttributeOverrideConfig(
4014:                    String name, String columnName, boolean isNullable,
4015:                    boolean isUnique) {
4016:                AttributeOverrideConfig attOverrideConfig = new AttributeOverrideConfig();
4017:
4018:                attOverrideConfig.setName(name);
4019:
4020:                ColumnConfig columnConfig = new ColumnConfig();
4021:
4022:                columnConfig.setName(columnName);
4023:                columnConfig.setNullable(isNullable);
4024:                columnConfig.setUnique(isUnique);
4025:
4026:                attOverrideConfig.setColumn(columnConfig);
4027:
4028:                return attOverrideConfig;
4029:            }
4030:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.