Source Code Cross Referenced for JDBCEntityBridge.java in  » EJB-Server-JBoss-4.2.1 » server » org » jboss » ejb » plugins » cmp » jdbc » bridge » 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 JBoss 4.2.1 » server » org.jboss.ejb.plugins.cmp.jdbc.bridge 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * JBoss, Home of Professional Open Source.
0003:         * Copyright 2006, Red Hat Middleware LLC, and individual contributors
0004:         * as indicated by the @author tags. See the copyright.txt file in the
0005:         * distribution for a full listing of individual contributors.
0006:         *
0007:         * This is free software; you can redistribute it and/or modify it
0008:         * under the terms of the GNU Lesser General Public License as
0009:         * published by the Free Software Foundation; either version 2.1 of
0010:         * the License, or (at your option) any later version.
0011:         *
0012:         * This software is distributed in the hope that it will be useful,
0013:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
0014:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0015:         * Lesser General Public License for more details.
0016:         *
0017:         * You should have received a copy of the GNU Lesser General Public
0018:         * License along with this software; if not, write to the Free
0019:         * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
0020:         * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
0021:         */
0022:        package org.jboss.ejb.plugins.cmp.jdbc.bridge;
0023:
0024:        import java.sql.PreparedStatement;
0025:        import java.sql.ResultSet;
0026:
0027:        import java.util.ArrayList;
0028:        import java.util.Collection;
0029:        import java.util.Collections;
0030:        import java.util.HashMap;
0031:        import java.util.Iterator;
0032:        import java.util.List;
0033:        import java.util.Map;
0034:        import java.util.Arrays;
0035:        import java.util.NoSuchElementException;
0036:        import java.rmi.RemoteException;
0037:
0038:        import javax.ejb.EJBException;
0039:        import javax.ejb.RemoveException;
0040:        import javax.sql.DataSource;
0041:        import javax.naming.InitialContext;
0042:        import javax.naming.NamingException;
0043:
0044:        import org.jboss.deployment.DeploymentException;
0045:        import org.jboss.ejb.EntityEnterpriseContext;
0046:
0047:        import org.jboss.ejb.plugins.cmp.jdbc.JDBCContext;
0048:        import org.jboss.ejb.plugins.cmp.jdbc.JDBCStoreManager;
0049:        import org.jboss.ejb.plugins.cmp.jdbc.SQLUtil;
0050:        import org.jboss.ejb.plugins.cmp.jdbc.LockingStrategy;
0051:        import org.jboss.ejb.plugins.cmp.jdbc.JDBCTypeFactory;
0052:        import org.jboss.ejb.plugins.cmp.jdbc.JDBCEntityPersistenceStore;
0053:
0054:        import org.jboss.ejb.plugins.cmp.bridge.EntityBridgeInvocationHandler;
0055:        import org.jboss.ejb.plugins.cmp.bridge.FieldBridge;
0056:
0057:        import org.jboss.ejb.plugins.cmp.jdbc.metadata.JDBCAuditMetaData;
0058:        import org.jboss.ejb.plugins.cmp.jdbc.metadata.JDBCEntityMetaData;
0059:        import org.jboss.ejb.plugins.cmp.jdbc.metadata.JDBCCMPFieldMetaData;
0060:        import org.jboss.ejb.plugins.cmp.jdbc.metadata.JDBCQueryMetaData;
0061:        import org.jboss.ejb.plugins.cmp.jdbc.metadata.JDBCRelationshipRoleMetaData;
0062:        import org.jboss.ejb.plugins.cmp.jdbc.metadata.JDBCOptimisticLockingMetaData;
0063:        import org.jboss.ejb.plugins.cmp.jdbc.metadata.JDBCReadAheadMetaData;
0064:        import org.jboss.proxy.compiler.Proxies;
0065:        import org.jboss.proxy.compiler.InvocationHandler;
0066:        import org.jboss.logging.Logger;
0067:
0068:        /**
0069:         * JDBCEntityBridge follows the Bridge pattern [Gamma et. al, 1995].
0070:         * The main job of this class is to construct the bridge from entity meta data.
0071:         *
0072:         * Life-cycle:
0073:         *      Undefined. Should be tied to CMPStoreManager.
0074:         *
0075:         * Multiplicity:
0076:         *      One per cmp entity bean type.
0077:         *
0078:         * @author <a href="mailto:dain@daingroup.com">Dain Sundstrom</a>
0079:         * @author <a href="mailto:loubyansky@ua.fm">Alex Loubyansky</a>
0080:         * @author <a href="mailto:heiko.rupp@cellent.de">Heiko W. Rupp</a>
0081:         * @version $Revision: 57209 $
0082:         */
0083:        public class JDBCEntityBridge implements  JDBCAbstractEntityBridge {
0084:            public final static byte LOADED = 1;
0085:            public final static byte LOAD_REQUIRED = 2;
0086:            public final static byte DIRTY = 4;
0087:            public final static byte CHECK_DIRTY = 8;
0088:            public final static byte LOCKED = 16;
0089:            public final static byte ADD_TO_SET_ON_UPDATE = 32;
0090:            public final static byte ADD_TO_WHERE_ON_UPDATE = 64;
0091:
0092:            private static final String DEFAULT_LOADGROUP_NAME = "*";
0093:
0094:            private JDBCEntityMetaData metadata;
0095:            private JDBCStoreManager manager;
0096:            private DataSource dataSource;
0097:            private String qualifiedTableName;
0098:            private String tableName;
0099:
0100:            /** primary key fields (not added to cmpFields) */
0101:            private final String primaryKeyFieldName;
0102:            private final Class primaryKeyClass;
0103:            private JDBCCMPFieldBridge[] primaryKeyFields;
0104:            /** CMP fields */
0105:            private JDBCCMPFieldBridge[] cmpFields;
0106:            /** CMR fields */
0107:            private JDBCCMRFieldBridge[] cmrFields;
0108:            /** table fields */
0109:            private JDBCCMPFieldBridge[] tableFields;
0110:
0111:            /** used for optimistic locking. (added to cmpFields) */
0112:            private JDBCCMPFieldBridge versionField;
0113:
0114:            // Audit fields (added to cmpFields)
0115:            private JDBCCMPFieldBridge createdPrincipalField;
0116:            private JDBCCMPFieldBridge createdTimeField;
0117:            private JDBCCMPFieldBridge updatedPrincipalField;
0118:            private JDBCCMPFieldBridge updatedTimeField;
0119:
0120:            private Map selectorsByMethod;
0121:
0122:            /** Load group is a boolean array with tableFields.length elements. True means the element is in the group. */
0123:            private Map loadGroupMasks;
0124:            private List lazyLoadGroupMasks;
0125:            private boolean[] eagerLoadGroupMask;
0126:            private boolean[] defaultLockGroupMask;
0127:
0128:            private int jdbcContextSize;
0129:
0130:            private final Logger log;
0131:
0132:            public JDBCEntityBridge(JDBCEntityMetaData metadata,
0133:                    JDBCStoreManager manager) throws DeploymentException {
0134:                this .metadata = metadata;
0135:                this .manager = manager;
0136:                primaryKeyFieldName = metadata.getPrimaryKeyFieldName();
0137:                primaryKeyClass = metadata.getPrimaryKeyClass();
0138:                log = Logger.getLogger(this .getClass().getName() + "."
0139:                        + metadata.getName());
0140:            }
0141:
0142:            public void init() throws DeploymentException {
0143:                try {
0144:                    InitialContext ic = new InitialContext();
0145:                    dataSource = (DataSource) ic.lookup(metadata
0146:                            .getDataSourceName());
0147:                } catch (NamingException e) {
0148:                    throw new DeploymentException(
0149:                            "Error: can't find data source: "
0150:                                    + metadata.getDataSourceName(), e);
0151:                }
0152:
0153:                qualifiedTableName = SQLUtil.fixTableName(metadata
0154:                        .getDefaultTableName(), dataSource);
0155:                int dotIndex = qualifiedTableName.indexOf('.');
0156:                tableName = dotIndex == -1 ? qualifiedTableName
0157:                        : qualifiedTableName.substring(dotIndex + 1);
0158:
0159:                // CMP fields
0160:                loadCMPFields(metadata);
0161:
0162:                // CMR fields
0163:                loadCMRFields(metadata);
0164:
0165:                // create locking field
0166:                JDBCOptimisticLockingMetaData lockMetaData = metadata
0167:                        .getOptimisticLocking();
0168:                if (lockMetaData != null
0169:                        && lockMetaData.getLockingField() != null) {
0170:                    Integer strategy = lockMetaData.getLockingStrategy();
0171:                    JDBCCMPFieldMetaData versionMD = lockMetaData
0172:                            .getLockingField();
0173:
0174:                    versionField = getCMPFieldByName(versionMD.getFieldName());
0175:                    boolean hidden = versionField == null;
0176:                    if (strategy == JDBCOptimisticLockingMetaData.VERSION_COLUMN_STRATEGY) {
0177:                        if (hidden)
0178:                            versionField = new JDBCLongVersionFieldBridge(
0179:                                    manager, versionMD);
0180:                        else
0181:                            versionField = new JDBCLongVersionFieldBridge(
0182:                                    (JDBCCMP2xFieldBridge) versionField);
0183:                    } else if (strategy == JDBCOptimisticLockingMetaData.TIMESTAMP_COLUMN_STRATEGY) {
0184:                        if (hidden)
0185:                            versionField = new JDBCTimestampVersionFieldBridge(
0186:                                    manager, versionMD);
0187:                        else
0188:                            versionField = new JDBCTimestampVersionFieldBridge(
0189:                                    (JDBCCMP2xFieldBridge) versionField);
0190:                    } else if (strategy == JDBCOptimisticLockingMetaData.KEYGENERATOR_COLUMN_STRATEGY) {
0191:                        if (hidden)
0192:                            versionField = new JDBCKeyGenVersionFieldBridge(
0193:                                    manager, versionMD, lockMetaData
0194:                                            .getKeyGeneratorFactory());
0195:                        else
0196:                            versionField = new JDBCKeyGenVersionFieldBridge(
0197:                                    (JDBCCMP2xFieldBridge) versionField,
0198:                                    lockMetaData.getKeyGeneratorFactory());
0199:                    }
0200:
0201:                    if (hidden)
0202:                        addCMPField(versionField);
0203:                    else
0204:                        tableFields[versionField.getTableIndex()] = versionField;
0205:                }
0206:
0207:                // audit fields
0208:                JDBCAuditMetaData auditMetaData = metadata.getAudit();
0209:                if (auditMetaData != null) {
0210:                    JDBCCMPFieldMetaData auditField = auditMetaData
0211:                            .getCreatedPrincipalField();
0212:                    if (auditField != null) {
0213:                        createdPrincipalField = getCMPFieldByName(auditField
0214:                                .getFieldName());
0215:                        if (createdPrincipalField == null) {
0216:                            createdPrincipalField = new JDBCCMP2xFieldBridge(
0217:                                    manager, auditField);
0218:                            addCMPField(createdPrincipalField);
0219:                        }
0220:                    } else {
0221:                        createdPrincipalField = null;
0222:                    }
0223:
0224:                    auditField = auditMetaData.getCreatedTimeField();
0225:                    if (auditField != null) {
0226:                        createdTimeField = getCMPFieldByName(auditField
0227:                                .getFieldName());
0228:                        if (createdTimeField == null) {
0229:                            createdTimeField = new JDBCCMP2xFieldBridge(
0230:                                    manager, auditField,
0231:                                    JDBCTypeFactory.EQUALS, false);
0232:                            addCMPField(createdTimeField);
0233:                        } else {
0234:                            // just to override state factory and check-dirty-after-get
0235:                            createdTimeField = new JDBCCMP2xFieldBridge(
0236:                                    (JDBCCMP2xFieldBridge) createdTimeField,
0237:                                    JDBCTypeFactory.EQUALS, false);
0238:                            tableFields[createdTimeField.getTableIndex()] = createdTimeField;
0239:                        }
0240:                    } else {
0241:                        createdTimeField = null;
0242:                    }
0243:
0244:                    auditField = auditMetaData.getUpdatedPrincipalField();
0245:                    if (auditField != null) {
0246:                        updatedPrincipalField = getCMPFieldByName(auditField
0247:                                .getFieldName());
0248:                        if (updatedPrincipalField == null) {
0249:                            updatedPrincipalField = new JDBCCMP2xUpdatedPrincipalFieldBridge(
0250:                                    manager, auditField);
0251:                            addCMPField(updatedPrincipalField);
0252:                        } else {
0253:                            updatedPrincipalField = new JDBCCMP2xUpdatedPrincipalFieldBridge(
0254:                                    (JDBCCMP2xFieldBridge) updatedPrincipalField);
0255:                            tableFields[updatedPrincipalField.getTableIndex()] = updatedPrincipalField;
0256:                        }
0257:                    } else {
0258:                        updatedPrincipalField = null;
0259:                    }
0260:
0261:                    auditField = auditMetaData.getUpdatedTimeField();
0262:                    if (auditField != null) {
0263:                        updatedTimeField = getCMPFieldByName(auditField
0264:                                .getFieldName());
0265:                        if (updatedTimeField == null) {
0266:                            updatedTimeField = new JDBCCMP2xUpdatedTimeFieldBridge(
0267:                                    manager, auditField);
0268:                            addCMPField(updatedTimeField);
0269:                        } else {
0270:                            updatedTimeField = new JDBCCMP2xUpdatedTimeFieldBridge(
0271:                                    (JDBCCMP2xFieldBridge) updatedTimeField);
0272:                            tableFields[updatedTimeField.getTableIndex()] = updatedTimeField;
0273:                        }
0274:                    } else {
0275:                        updatedTimeField = null;
0276:                    }
0277:                }
0278:
0279:                // ejbSelect methods
0280:                loadSelectors(metadata);
0281:            }
0282:
0283:            public void resolveRelationships() throws DeploymentException {
0284:                for (int i = 0; i < cmrFields.length; ++i)
0285:                    cmrFields[i].resolveRelationship();
0286:
0287:                // load groups:  cannot be created until relationships have
0288:                // been resolved because loadgroups must check for foreign keys
0289:                loadLoadGroups(metadata);
0290:                loadEagerLoadGroup(metadata);
0291:                loadLazyLoadGroups(metadata);
0292:            }
0293:
0294:            /**
0295:             * The third phase of deployment. The method is called when relationships are already resolved.
0296:             * @throws DeploymentException
0297:             */
0298:            public void start() throws DeploymentException {
0299:                for (int i = 0; i < cmrFields.length; ++i) {
0300:                    cmrFields[i].start();
0301:                }
0302:            }
0303:
0304:            public boolean removeFromRelations(EntityEnterpriseContext ctx,
0305:                    Object[] oldRelations) {
0306:                boolean removed = false;
0307:                for (int i = 0; i < cmrFields.length; ++i) {
0308:                    if (cmrFields[i].removeFromRelations(ctx, oldRelations))
0309:                        removed = true;
0310:                }
0311:                return removed;
0312:            }
0313:
0314:            public void cascadeDelete(EntityEnterpriseContext ctx,
0315:                    Map oldRelations) throws RemoveException, RemoteException {
0316:                for (int i = 0; i < cmrFields.length; ++i) {
0317:                    JDBCCMRFieldBridge cmrField = cmrFields[i];
0318:                    Object value = oldRelations.get(cmrField);
0319:                    if (value != null)
0320:                        cmrField.cascadeDelete(ctx, (List) value);
0321:                }
0322:            }
0323:
0324:            public String getEntityName() {
0325:                return metadata.getName();
0326:            }
0327:
0328:            public String getAbstractSchemaName() {
0329:                return metadata.getAbstractSchemaName();
0330:            }
0331:
0332:            public Class getRemoteInterface() {
0333:                return metadata.getRemoteClass();
0334:            }
0335:
0336:            public Class getLocalInterface() {
0337:                return metadata.getLocalClass();
0338:            }
0339:
0340:            public JDBCEntityMetaData getMetaData() {
0341:                return metadata;
0342:            }
0343:
0344:            public JDBCEntityPersistenceStore getManager() {
0345:                return manager;
0346:            }
0347:
0348:            /**
0349:             * Returns the datasource for this entity.
0350:             */
0351:            public DataSource getDataSource() {
0352:                return dataSource;
0353:            }
0354:
0355:            public String getTableName() {
0356:                return tableName;
0357:            }
0358:
0359:            public String getQualifiedTableName() {
0360:                return qualifiedTableName;
0361:            }
0362:
0363:            public Class getPrimaryKeyClass() {
0364:                return primaryKeyClass;
0365:            }
0366:
0367:            public int getListCacheMax() {
0368:                return metadata.getListCacheMax();
0369:            }
0370:
0371:            public int getFetchSize() {
0372:                return metadata.getFetchSize();
0373:            }
0374:
0375:            public Object createPrimaryKeyInstance() {
0376:                if (primaryKeyFieldName == null) {
0377:                    try {
0378:                        return primaryKeyClass.newInstance();
0379:                    } catch (Exception e) {
0380:                        throw new EJBException(
0381:                                "Error creating primary key instance: ", e);
0382:                    }
0383:                }
0384:                return null;
0385:            }
0386:
0387:            public JDBCFieldBridge[] getPrimaryKeyFields() {
0388:                return primaryKeyFields;
0389:            }
0390:
0391:            /**
0392:             * This method is called only at deployment time, not called at runtime.
0393:             * @return the list of all the fields.
0394:             */
0395:            public List getFields() {
0396:                int fieldsTotal = primaryKeyFields.length + cmpFields.length
0397:                        + cmrFields.length;
0398:                JDBCFieldBridge[] fields = new JDBCFieldBridge[fieldsTotal];
0399:                int position = 0;
0400:                // primary key fields
0401:                System.arraycopy(primaryKeyFields, 0, fields, position,
0402:                        primaryKeyFields.length);
0403:                position += primaryKeyFields.length;
0404:                // cmp fields
0405:                System.arraycopy(cmpFields, 0, fields, position,
0406:                        cmpFields.length);
0407:                position += cmpFields.length;
0408:                // cmr fields
0409:                System.arraycopy(cmrFields, 0, fields, position,
0410:                        cmrFields.length);
0411:                return Arrays.asList(fields);
0412:            }
0413:
0414:            public FieldBridge getFieldByName(String name) {
0415:                FieldBridge field = null;
0416:                for (int i = 0; i < primaryKeyFields.length; ++i) {
0417:                    JDBCCMPFieldBridge primaryKeyField = primaryKeyFields[i];
0418:                    if (primaryKeyField.getFieldName().equals(name)) {
0419:                        field = primaryKeyField;
0420:                        break;
0421:                    }
0422:                }
0423:                if (field == null) {
0424:                    field = getCMPFieldByName(name);
0425:                }
0426:                if (field == null) {
0427:                    field = getCMRFieldByName(name);
0428:                }
0429:                return field;
0430:            }
0431:
0432:            public boolean[] getEagerLoadMask() {
0433:                return eagerLoadGroupMask;
0434:            }
0435:
0436:            public Iterator getLazyLoadGroupMasks() {
0437:                return lazyLoadGroupMasks.iterator();
0438:            }
0439:
0440:            public boolean[] getLoadGroupMask(String name) {
0441:                boolean[] mask = (boolean[]) loadGroupMasks.get(name);
0442:                if (mask == null) {
0443:                    throw new IllegalStateException("Load group '" + name
0444:                            + "' is not defined. Defined load groups: "
0445:                            + loadGroupMasks.keySet());
0446:                }
0447:                return mask;
0448:            }
0449:
0450:            public FieldIterator getLoadIterator(
0451:                    JDBCCMPFieldBridge requiredField,
0452:                    JDBCReadAheadMetaData readahead, EntityEnterpriseContext ctx) {
0453:                boolean[] loadGroup;
0454:                if (requiredField == null) {
0455:                    if (readahead != null && !readahead.isNone()) {
0456:                        if (log.isTraceEnabled()) {
0457:                            log.trace("Eager-load for entity: readahead="
0458:                                    + readahead);
0459:                        }
0460:                        loadGroup = getLoadGroupMask(readahead
0461:                                .getEagerLoadGroup());
0462:                    } else {
0463:                        if (log.isTraceEnabled()) {
0464:                            log
0465:                                    .trace("Default eager-load for entity: readahead="
0466:                                            + readahead);
0467:                        }
0468:                        loadGroup = eagerLoadGroupMask;
0469:                    }
0470:                } else {
0471:                    loadGroup = new boolean[tableFields.length];
0472:                    int requiredInd = requiredField.getTableIndex();
0473:                    loadGroup[requiredInd] = true;
0474:                    for (Iterator groups = lazyLoadGroupMasks.iterator(); groups
0475:                            .hasNext();) {
0476:                        boolean[] lazyGroup = (boolean[]) groups.next();
0477:                        if (lazyGroup[requiredInd]) {
0478:                            for (int i = 0; i < loadGroup.length; ++i)
0479:                                loadGroup[i] = loadGroup[i] || lazyGroup[i];
0480:                        }
0481:                    }
0482:                }
0483:
0484:                FieldIterator loadIter;
0485:                if (loadGroup != null) {
0486:                    // filter
0487:                    int fieldsToLoad = 0;
0488:                    EntityState entityState = getEntityState(ctx);
0489:                    for (int i = 0; i < tableFields.length; ++i) {
0490:                        JDBCCMPFieldBridge field = tableFields[i];
0491:                        if (loadGroup[i] && !field.isPrimaryKeyMember()
0492:                                && !field.isLoaded(ctx)) {
0493:                            entityState.setLoadRequired(i);
0494:                            ++fieldsToLoad;
0495:                        }
0496:                    }
0497:                    loadIter = (fieldsToLoad > 0 ? entityState
0498:                            .getLoadIterator(ctx) : EMPTY_FIELD_ITERATOR);
0499:                } else {
0500:                    loadIter = EMPTY_FIELD_ITERATOR;
0501:                }
0502:                return loadIter;
0503:            }
0504:
0505:            /**
0506:             * @param name  CMP field name
0507:             * @return  JDBCCMPFieldBridge instance or null if no field found.
0508:             */
0509:            public JDBCCMPFieldBridge getCMPFieldByName(String name) {
0510:                for (int i = 0; i < primaryKeyFields.length; ++i) {
0511:                    JDBCCMPFieldBridge cmpField = primaryKeyFields[i];
0512:                    if (cmpField.getFieldName().equals(name))
0513:                        return cmpField;
0514:                }
0515:                for (int i = 0; i < cmpFields.length; ++i) {
0516:                    JDBCCMPFieldBridge cmpField = cmpFields[i];
0517:                    if (cmpField.getFieldName().equals(name))
0518:                        return cmpField;
0519:                }
0520:                return null;
0521:            }
0522:
0523:            public JDBCAbstractCMRFieldBridge[] getCMRFields() {
0524:                return cmrFields;
0525:            }
0526:
0527:            public JDBCCMRFieldBridge getCMRFieldByName(String name) {
0528:                for (int i = 0; i < cmrFields.length; ++i) {
0529:                    JDBCCMRFieldBridge cmrField = cmrFields[i];
0530:                    if (cmrField.getFieldName().equals(name))
0531:                        return cmrField;
0532:                }
0533:                return null;
0534:            }
0535:
0536:            public JDBCCMPFieldBridge getVersionField() {
0537:                return versionField;
0538:            }
0539:
0540:            public JDBCCMPFieldBridge getCreatedPrincipalField() {
0541:                return createdPrincipalField;
0542:            }
0543:
0544:            public JDBCCMPFieldBridge getCreatedTimeField() {
0545:                return createdTimeField;
0546:            }
0547:
0548:            public JDBCCMPFieldBridge getUpdatedPrincipalField() {
0549:                return updatedPrincipalField;
0550:            }
0551:
0552:            public JDBCCMPFieldBridge getUpdatedTimeField() {
0553:                return updatedTimeField;
0554:            }
0555:
0556:            public Collection getSelectors() {
0557:                return selectorsByMethod.values();
0558:            }
0559:
0560:            public void initInstance(EntityEnterpriseContext ctx) {
0561:                for (int i = 0; i < tableFields.length; ++i)
0562:                    tableFields[i].initInstance(ctx);
0563:                //for(int i = 0; i < primaryKeyFields.length; ++i)
0564:                //   primaryKeyFields[i].initInstance(ctx);
0565:                //for(int i = 0; i < cmpFields.length; ++i)
0566:                //   cmpFields[i].initInstance(ctx);
0567:                for (int i = 0; i < cmrFields.length; ++i) {
0568:                    JDBCCMRFieldBridge cmrField = cmrFields[i];
0569:                    cmrField.initInstance(ctx);
0570:                }
0571:            }
0572:
0573:            public static boolean isEjbCreateDone(EntityEnterpriseContext ctx) {
0574:                return getEntityState(ctx).ejbCreateDone;
0575:            }
0576:
0577:            public static void setCreated(EntityEnterpriseContext ctx) {
0578:                getEntityState(ctx).setCreated();
0579:            }
0580:
0581:            public static void setEjbCreateDone(EntityEnterpriseContext ctx) {
0582:                getEntityState(ctx).ejbCreateDone = true;
0583:            }
0584:
0585:            /**
0586:             * This method is used to determined whether the instance was modified.
0587:             * NOTE, even if the method returns true the isStoreRequired for this same instance
0588:             * might return false, e.g. a CMR field that doesn't have a foreign key was modified.
0589:             * @param ctx
0590:             * @return
0591:             */
0592:            public boolean isModified(EntityEnterpriseContext ctx) {
0593:                boolean invalidateCache = false;
0594:                final EntityState entityState = getEntityState(ctx);
0595:                if (entityState.isCreated()) {
0596:                    invalidateCache = areCmpFieldsDirty(ctx, entityState);
0597:                    if (!invalidateCache) {
0598:                        for (int i = 0; i < cmrFields.length; ++i) {
0599:                            if (cmrFields[i].invalidateCache(ctx)) {
0600:                                invalidateCache = true;
0601:                                break;
0602:                            }
0603:                        }
0604:                    }
0605:                }
0606:                return invalidateCache;
0607:            }
0608:
0609:            public boolean isStoreRequired(EntityEnterpriseContext ctx) {
0610:                boolean modified = false;
0611:                final EntityState entityState = getEntityState(ctx);
0612:                if (entityState.isCreated()) {
0613:                    modified = areCmpFieldsDirty(ctx, entityState);
0614:                    if (!modified) {
0615:                        for (int i = 0; i < cmrFields.length; ++i) {
0616:                            if (cmrFields[i].isDirty(ctx)) {
0617:                                modified = true;
0618:                                break;
0619:                            }
0620:                        }
0621:                    }
0622:                }
0623:                return modified;
0624:            }
0625:
0626:            private boolean areCmpFieldsDirty(
0627:                    final EntityEnterpriseContext ctx,
0628:                    final EntityState entityState) {
0629:                for (int i = 0; i < tableFields.length; ++i) {
0630:                    final JDBCCMPFieldBridge field = tableFields[i];
0631:                    if (entityState.isCheckDirty(i) && field.isDirty(ctx)) {
0632:                        return true;
0633:                    }
0634:                }
0635:                return false;
0636:            }
0637:
0638:            public FieldIterator getDirtyIterator(EntityEnterpriseContext ctx) {
0639:                int dirtyFields = 0;
0640:                final EntityState entityState = getEntityState(ctx);
0641:                for (int i = 0; i < tableFields.length; ++i) {
0642:                    JDBCCMPFieldBridge field = tableFields[i];
0643:                    if (entityState.isCheckDirty(i) && field.isDirty(ctx)) {
0644:                        entityState.setUpdateRequired(i);
0645:                        ++dirtyFields;
0646:                    }
0647:                }
0648:
0649:                return dirtyFields > 0 ? getEntityState(ctx).getDirtyIterator(
0650:                        ctx) : EMPTY_FIELD_ITERATOR;
0651:            }
0652:
0653:            public boolean hasLockedFields(EntityEnterpriseContext ctx) {
0654:                return getEntityState(ctx).hasLockedFields();
0655:            }
0656:
0657:            public FieldIterator getLockedIterator(EntityEnterpriseContext ctx) {
0658:                return getEntityState(ctx).getLockedIterator(ctx);
0659:            }
0660:
0661:            public void initPersistenceContext(EntityEnterpriseContext ctx) {
0662:                // If we have an EJB 2.0 dynaymic proxy,
0663:                // notify the handler of the assigned context.
0664:                Object instance = ctx.getInstance();
0665:                if (instance instanceof  Proxies.ProxyTarget) {
0666:                    InvocationHandler handler = ((Proxies.ProxyTarget) instance)
0667:                            .getInvocationHandler();
0668:                    if (handler instanceof  EntityBridgeInvocationHandler)
0669:                        ((EntityBridgeInvocationHandler) handler)
0670:                                .setContext(ctx);
0671:                }
0672:                ctx.setPersistenceContext(new JDBCContext(jdbcContextSize,
0673:                        new EntityState()));
0674:            }
0675:
0676:            /**
0677:             * This is only called in commit option B
0678:             */
0679:            public void resetPersistenceContext(EntityEnterpriseContext ctx) {
0680:                for (int i = 0; i < primaryKeyFields.length; ++i)
0681:                    primaryKeyFields[i].resetPersistenceContext(ctx);
0682:                for (int i = 0; i < cmpFields.length; ++i)
0683:                    cmpFields[i].resetPersistenceContext(ctx);
0684:                for (int i = 0; i < cmrFields.length; ++i)
0685:                    cmrFields[i].resetPersistenceContext(ctx);
0686:            }
0687:
0688:            public static void destroyPersistenceContext(
0689:                    EntityEnterpriseContext ctx) {
0690:                // If we have an EJB 2.0 dynaymic proxy,
0691:                // notify the handler of the assigned context.
0692:                Object instance = ctx.getInstance();
0693:                if (instance instanceof  Proxies.ProxyTarget) {
0694:                    InvocationHandler handler = ((Proxies.ProxyTarget) instance)
0695:                            .getInvocationHandler();
0696:                    if (handler instanceof  EntityBridgeInvocationHandler)
0697:                        ((EntityBridgeInvocationHandler) handler)
0698:                                .setContext(null);
0699:                }
0700:                ctx.setPersistenceContext(null);
0701:            }
0702:
0703:            //
0704:            // Commands to handle primary keys
0705:            //
0706:
0707:            public int setPrimaryKeyParameters(PreparedStatement ps,
0708:                    int parameterIndex, Object primaryKey) {
0709:                for (int i = 0; i < primaryKeyFields.length; ++i)
0710:                    parameterIndex = primaryKeyFields[i]
0711:                            .setPrimaryKeyParameters(ps, parameterIndex,
0712:                                    primaryKey);
0713:                return parameterIndex;
0714:            }
0715:
0716:            public int loadPrimaryKeyResults(ResultSet rs, int parameterIndex,
0717:                    Object[] pkRef) {
0718:                pkRef[0] = createPrimaryKeyInstance();
0719:                for (int i = 0; i < primaryKeyFields.length; ++i)
0720:                    parameterIndex = primaryKeyFields[i].loadPrimaryKeyResults(
0721:                            rs, parameterIndex, pkRef);
0722:                return parameterIndex;
0723:            }
0724:
0725:            public Object extractPrimaryKeyFromInstance(
0726:                    EntityEnterpriseContext ctx) {
0727:                try {
0728:                    Object pk = null;
0729:                    for (int i = 0; i < primaryKeyFields.length; ++i) {
0730:                        JDBCCMPFieldBridge pkField = primaryKeyFields[i];
0731:                        Object fieldValue = pkField.getInstanceValue(ctx);
0732:
0733:                        // updated pk object with return form set primary key value to
0734:                        // handle single valued non-composit pks and more complicated behivors.
0735:                        pk = pkField.setPrimaryKeyValue(pk, fieldValue);
0736:                    }
0737:                    return pk;
0738:                } catch (EJBException e) {
0739:                    // to avoid double wrap of EJBExceptions
0740:                    throw e;
0741:                } catch (Exception e) {
0742:                    // Non recoverable internal exception
0743:                    throw new EJBException(
0744:                            "Internal error extracting primary key from "
0745:                                    + "instance", e);
0746:                }
0747:            }
0748:
0749:            public void injectPrimaryKeyIntoInstance(
0750:                    EntityEnterpriseContext ctx, Object pk) {
0751:                for (int i = 0; i < primaryKeyFields.length; ++i) {
0752:                    JDBCCMPFieldBridge pkField = primaryKeyFields[i];
0753:                    Object fieldValue = pkField.getPrimaryKeyValue(pk);
0754:                    pkField.setInstanceValue(ctx, fieldValue);
0755:                }
0756:            }
0757:
0758:            int getNextJDBCContextIndex() {
0759:                return jdbcContextSize++;
0760:            }
0761:
0762:            int addTableField(JDBCCMPFieldBridge field) {
0763:                JDBCCMPFieldBridge[] tmpFields = tableFields;
0764:                if (tableFields == null) {
0765:                    tableFields = new JDBCCMPFieldBridge[1];
0766:                } else {
0767:                    tableFields = new JDBCCMPFieldBridge[tableFields.length + 1];
0768:                    System.arraycopy(tmpFields, 0, tableFields, 0,
0769:                            tmpFields.length);
0770:                }
0771:                int index = tableFields.length - 1;
0772:                tableFields[index] = field;
0773:
0774:                return index;
0775:            }
0776:
0777:            public JDBCFieldBridge[] getTableFields() {
0778:                return tableFields;
0779:            }
0780:
0781:            /**
0782:             * Marks the context as removed.
0783:             * @param ctx instance's context
0784:             */
0785:            public void setRemoved(EntityEnterpriseContext ctx) {
0786:                getEntityState(ctx).setRemoved();
0787:            }
0788:
0789:            /**
0790:             * @param ctx instance's context.
0791:             * @return true if instance was removed.
0792:             */
0793:            public boolean isRemoved(EntityEnterpriseContext ctx) {
0794:                return getEntityState(ctx).isRemoved();
0795:            }
0796:
0797:            /**
0798:             * Marks an instance as being removed
0799:             */
0800:            public void setIsBeingRemoved(EntityEnterpriseContext ctx) {
0801:                getEntityState(ctx).setIsBeingRemoved();
0802:            }
0803:
0804:            /**
0805:             * @param ctx instance's context.
0806:             * @return true if instance is being removed.
0807:             */
0808:            public boolean isBeingRemoved(EntityEnterpriseContext ctx) {
0809:                return getEntityState(ctx).isBeingRemoved();
0810:            }
0811:
0812:            /**
0813:             * Marks the instance as scheduled for cascade delete (not for batch cascade delete)
0814:             * @param ctx instance's context.
0815:             */
0816:            public void scheduleForCascadeDelete(EntityEnterpriseContext ctx) {
0817:                getEntityState(ctx).scheduleForCascadeDelete();
0818:                if (log.isTraceEnabled())
0819:                    log.trace("Scheduled for cascade-delete: " + ctx.getId());
0820:            }
0821:
0822:            /**
0823:             * @param ctx instance's context.
0824:             * @return true if instance was scheduled for cascade delete (not for batch cascade delete)
0825:             */
0826:            public boolean isScheduledForCascadeDelete(
0827:                    EntityEnterpriseContext ctx) {
0828:                return getEntityState(ctx).isScheduledForCascadeDelete();
0829:            }
0830:
0831:            /**
0832:             * Marks the instance as scheduled for batch cascade delete (not for cascade delete)
0833:             * @param ctx instance's context.
0834:             */
0835:            public void scheduleForBatchCascadeDelete(
0836:                    EntityEnterpriseContext ctx) {
0837:                getEntityState(ctx).scheduleForBatchCascadeDelete();
0838:                if (log.isTraceEnabled())
0839:                    log.trace("Scheduled for batch-cascade-delete: "
0840:                            + ctx.getId());
0841:            }
0842:
0843:            /**
0844:             * @param ctx instance's context.
0845:             * @return true if instance was scheduled for batch cascade delete (not for cascade delete)
0846:             */
0847:            public boolean isScheduledForBatchCascadeDelete(
0848:                    EntityEnterpriseContext ctx) {
0849:                return getEntityState(ctx).isScheduledForBatchCascadeDelete();
0850:            }
0851:
0852:            private static EntityState getEntityState(
0853:                    EntityEnterpriseContext ctx) {
0854:                JDBCContext jdbcCtx = (JDBCContext) ctx.getPersistenceContext();
0855:                EntityState entityState = jdbcCtx.getEntityState();
0856:                if (entityState == null)
0857:                    throw new IllegalStateException("Entity state is null.");
0858:                return entityState;
0859:            }
0860:
0861:            private void loadCMPFields(JDBCEntityMetaData metadata)
0862:                    throws DeploymentException {
0863:                // only non pk fields are stored here at first and then later
0864:                // the pk fields are added to the front (makes sql easier to read)
0865:                List cmpFieldsMD = metadata.getCMPFields();
0866:                List cmpFieldsList = new ArrayList(cmpFieldsMD.size());
0867:                // primary key cmp fields
0868:                List pkFieldsList = new ArrayList(cmpFieldsMD.size());
0869:
0870:                // create pk fields
0871:                for (int i = 0; i < cmpFieldsMD.size(); ++i) {
0872:                    JDBCCMPFieldMetaData fieldMD = (JDBCCMPFieldMetaData) cmpFieldsMD
0873:                            .get(i);
0874:                    if (fieldMD.isPrimaryKeyMember()) {
0875:                        JDBCCMPFieldBridge cmpField = createCMPField(metadata,
0876:                                fieldMD);
0877:                        pkFieldsList.add(cmpField);
0878:                    }
0879:                }
0880:
0881:                // create non-pk cmp fields
0882:                for (int i = 0; i < cmpFieldsMD.size(); ++i) {
0883:                    JDBCCMPFieldMetaData fieldMD = (JDBCCMPFieldMetaData) cmpFieldsMD
0884:                            .get(i);
0885:                    if (!fieldMD.isPrimaryKeyMember()) {
0886:                        JDBCCMPFieldBridge cmpField = createCMPField(metadata,
0887:                                fieldMD);
0888:                        cmpFieldsList.add(cmpField);
0889:                    }
0890:                }
0891:
0892:                // save the pk fields in the pk field array
0893:                primaryKeyFields = new JDBCCMPFieldBridge[pkFieldsList.size()];
0894:                for (int i = 0; i < pkFieldsList.size(); ++i)
0895:                    primaryKeyFields[i] = (JDBCCMPFieldBridge) pkFieldsList
0896:                            .get(i);
0897:
0898:                // add the pk fields to the front of the cmp list, per guarantee above
0899:                cmpFields = new JDBCCMPFieldBridge[cmpFieldsMD.size()
0900:                        - primaryKeyFields.length];
0901:                int cmpFieldIndex = 0;
0902:                for (int i = 0; i < cmpFieldsList.size(); ++i)
0903:                    cmpFields[cmpFieldIndex++] = (JDBCCMPFieldBridge) cmpFieldsList
0904:                            .get(i);
0905:            }
0906:
0907:            private void loadCMRFields(JDBCEntityMetaData metadata)
0908:                    throws DeploymentException {
0909:                cmrFields = new JDBCCMRFieldBridge[metadata
0910:                        .getRelationshipRoles().size()];
0911:                // create each field
0912:                int cmrFieldIndex = 0;
0913:                for (Iterator iter = metadata.getRelationshipRoles().iterator(); iter
0914:                        .hasNext();) {
0915:                    JDBCRelationshipRoleMetaData relationshipRole = (JDBCRelationshipRoleMetaData) iter
0916:                            .next();
0917:                    JDBCCMRFieldBridge cmrField = new JDBCCMRFieldBridge(this ,
0918:                            manager, relationshipRole);
0919:                    cmrFields[cmrFieldIndex++] = cmrField;
0920:                }
0921:            }
0922:
0923:            private void loadLoadGroups(JDBCEntityMetaData metadata)
0924:                    throws DeploymentException {
0925:                loadGroupMasks = new HashMap();
0926:
0927:                // load optimistic locking mask and add it to all the load group masks
0928:                JDBCOptimisticLockingMetaData olMD = metadata
0929:                        .getOptimisticLocking();
0930:                if (olMD != null) {
0931:                    if (versionField != null) {
0932:                        defaultLockGroupMask = new boolean[tableFields.length];
0933:                        defaultLockGroupMask[versionField.getTableIndex()] = true;
0934:                        versionField
0935:                                .setLockingStrategy(LockingStrategy.VERSION);
0936:                    } else if (olMD.getGroupName() != null) {
0937:                        defaultLockGroupMask = loadGroupMask(olMD
0938:                                .getGroupName(), null);
0939:                        for (int i = 0; i < tableFields.length; ++i) {
0940:                            if (defaultLockGroupMask[i]) {
0941:                                JDBCCMPFieldBridge tableField = tableFields[i];
0942:                                tableField
0943:                                        .setLockingStrategy(LockingStrategy.GROUP);
0944:                                tableField
0945:                                        .addDefaultFlag(ADD_TO_WHERE_ON_UPDATE);
0946:                            }
0947:                        }
0948:                    } else // read or modified strategy
0949:                    {
0950:                        LockingStrategy strategy = (olMD.getLockingStrategy() == JDBCOptimisticLockingMetaData.READ_STRATEGY ? LockingStrategy.READ
0951:                                : LockingStrategy.MODIFIED);
0952:                        for (int i = 0; i < tableFields.length; ++i) {
0953:                            JDBCCMPFieldBridge field = tableFields[i];
0954:                            if (!field.isPrimaryKeyMember())
0955:                                field.setLockingStrategy(strategy);
0956:                        }
0957:                    }
0958:                }
0959:
0960:                // add the * load group
0961:                boolean[] defaultLoadGroup = new boolean[tableFields.length];
0962:                Arrays.fill(defaultLoadGroup, true);
0963:                for (int i = 0; i < primaryKeyFields.length; ++i) {
0964:                    int tableIndex = primaryKeyFields[i].getTableIndex();
0965:                    defaultLoadGroup[tableIndex] = false;
0966:                }
0967:                loadGroupMasks.put(DEFAULT_LOADGROUP_NAME, defaultLoadGroup);
0968:
0969:                // put each group in the load groups map by group name
0970:                Iterator groupNames = metadata.getLoadGroups().keySet()
0971:                        .iterator();
0972:                while (groupNames.hasNext()) {
0973:                    // get the group name
0974:                    String groupName = (String) groupNames.next();
0975:                    boolean[] loadGroup = loadGroupMask(groupName,
0976:                            defaultLockGroupMask);
0977:                    loadGroupMasks.put(groupName, loadGroup);
0978:                }
0979:                loadGroupMasks = Collections.unmodifiableMap(loadGroupMasks);
0980:            }
0981:
0982:            private boolean[] loadGroupMask(String groupName,
0983:                    boolean[] defaultGroup) throws DeploymentException {
0984:                List fieldNames = metadata.getLoadGroup(groupName);
0985:                boolean[] group = new boolean[tableFields.length];
0986:                if (defaultGroup != null)
0987:                    System.arraycopy(defaultGroup, 0, group, 0, group.length);
0988:                for (Iterator iter = fieldNames.iterator(); iter.hasNext();) {
0989:                    String fieldName = (String) iter.next();
0990:                    JDBCFieldBridge field = (JDBCFieldBridge) getFieldByName(fieldName);
0991:                    if (field == null)
0992:                        throw new DeploymentException("Field " + fieldName
0993:                                + " not found for entity " + getEntityName());
0994:
0995:                    if (field instanceof  JDBCCMRFieldBridge) {
0996:                        JDBCCMRFieldBridge cmrField = (JDBCCMRFieldBridge) field;
0997:                        if (cmrField.hasForeignKey()) {
0998:                            JDBCCMPFieldBridge[] fkFields = (JDBCCMPFieldBridge[]) cmrField
0999:                                    .getForeignKeyFields();
1000:                            for (int i = 0; i < fkFields.length; ++i) {
1001:                                group[fkFields[i].getTableIndex()] = true;
1002:                            }
1003:                        } else {
1004:                            throw new DeploymentException(
1005:                                    "Only CMR fields that have "
1006:                                            + "a foreign-key may be a member of a load group: "
1007:                                            + "fieldName=" + fieldName);
1008:                        }
1009:                    } else {
1010:                        group[((JDBCCMPFieldBridge) field).getTableIndex()] = true;
1011:                    }
1012:                }
1013:                return group;
1014:            }
1015:
1016:            private void loadEagerLoadGroup(JDBCEntityMetaData metadata) {
1017:                String eagerLoadGroupName = metadata.getEagerLoadGroup();
1018:                if (eagerLoadGroupName == null) {
1019:                    // can be null in case of <eager-load-group/>, meaning empty load group
1020:                    eagerLoadGroupMask = defaultLockGroupMask;
1021:                } else
1022:                    eagerLoadGroupMask = (boolean[]) loadGroupMasks
1023:                            .get(eagerLoadGroupName);
1024:            }
1025:
1026:            private void loadLazyLoadGroups(JDBCEntityMetaData metadata) {
1027:                List lazyGroupNames = metadata.getLazyLoadGroups();
1028:                lazyLoadGroupMasks = new ArrayList(lazyGroupNames.size());
1029:                for (Iterator lazyLoadGroupNames = lazyGroupNames.iterator(); lazyLoadGroupNames
1030:                        .hasNext();) {
1031:                    String lazyLoadGroupName = (String) lazyLoadGroupNames
1032:                            .next();
1033:                    lazyLoadGroupMasks.add(loadGroupMasks
1034:                            .get(lazyLoadGroupName));
1035:                }
1036:                lazyLoadGroupMasks = Collections
1037:                        .unmodifiableList(lazyLoadGroupMasks);
1038:            }
1039:
1040:            private JDBCCMPFieldBridge createCMPField(
1041:                    JDBCEntityMetaData metadata,
1042:                    JDBCCMPFieldMetaData cmpFieldMetaData)
1043:                    throws DeploymentException {
1044:                JDBCCMPFieldBridge cmpField;
1045:                if (metadata.isCMP1x())
1046:                    cmpField = new JDBCCMP1xFieldBridge(manager,
1047:                            cmpFieldMetaData);
1048:                else
1049:                    cmpField = new JDBCCMP2xFieldBridge(manager,
1050:                            cmpFieldMetaData);
1051:                return cmpField;
1052:            }
1053:
1054:            private void loadSelectors(JDBCEntityMetaData metadata) {
1055:                // Don't know if this is the best way to do this.  Another way would be
1056:                // to deligate seletors to the JDBCFindEntitiesCommand, but this is
1057:                // easier now.
1058:                selectorsByMethod = new HashMap(metadata.getQueries().size());
1059:                Iterator definedFinders = manager.getMetaData().getQueries()
1060:                        .iterator();
1061:                while (definedFinders.hasNext()) {
1062:                    JDBCQueryMetaData q = (JDBCQueryMetaData) definedFinders
1063:                            .next();
1064:                    if (q.getMethod().getName().startsWith("ejbSelect"))
1065:                        selectorsByMethod.put(q.getMethod(),
1066:                                new JDBCSelectorBridge(manager, q));
1067:                }
1068:                selectorsByMethod = Collections
1069:                        .unmodifiableMap(selectorsByMethod);
1070:            }
1071:
1072:            private void addCMPField(JDBCCMPFieldBridge field) {
1073:                JDBCCMPFieldBridge[] tmpCMPFields = cmpFields;
1074:                cmpFields = new JDBCCMPFieldBridge[cmpFields.length + 1];
1075:                System.arraycopy(tmpCMPFields, 0, cmpFields, 0,
1076:                        tmpCMPFields.length);
1077:                cmpFields[tmpCMPFields.length] = field;
1078:            }
1079:
1080:            public class EntityState {
1081:                private static final byte REMOVED = 1;
1082:                private static final byte SCHEDULED_FOR_CASCADE_DELETE = 2;
1083:                private static final byte SCHEDULED_FOR_BATCH_CASCADE_DELETE = 4;
1084:                private static final byte IS_BEING_REMOVED = 8;
1085:
1086:                /** indicates whether ejbCreate method was executed */
1087:                private boolean ejbCreateDone = false;
1088:                /** indicates whether ejbPostCreate method was executed */
1089:                private boolean ejbPostCreateDone = false;
1090:
1091:                private byte entityFlags;
1092:
1093:                /** array of field flags*/
1094:                private final byte[] fieldFlags = new byte[tableFields.length];
1095:
1096:                public EntityState() {
1097:                    for (int i = 0; i < tableFields.length; ++i) {
1098:                        fieldFlags[i] = tableFields[i].getDefaultFlags();
1099:                    }
1100:                }
1101:
1102:                public void setRemoved() {
1103:                    entityFlags |= REMOVED;
1104:                    entityFlags &= ~(SCHEDULED_FOR_CASCADE_DELETE
1105:                            | SCHEDULED_FOR_BATCH_CASCADE_DELETE | IS_BEING_REMOVED);
1106:                }
1107:
1108:                public boolean isRemoved() {
1109:                    return (entityFlags & REMOVED) > 0;
1110:                }
1111:
1112:                public void setIsBeingRemoved() {
1113:                    entityFlags |= IS_BEING_REMOVED;
1114:                }
1115:
1116:                public boolean isBeingRemoved() {
1117:                    return (entityFlags & IS_BEING_REMOVED) > 0;
1118:                }
1119:
1120:                public void scheduleForCascadeDelete() {
1121:                    entityFlags |= SCHEDULED_FOR_CASCADE_DELETE;
1122:                }
1123:
1124:                public boolean isScheduledForCascadeDelete() {
1125:                    return (entityFlags & SCHEDULED_FOR_CASCADE_DELETE) > 0;
1126:                }
1127:
1128:                public void scheduleForBatchCascadeDelete() {
1129:                    entityFlags |= SCHEDULED_FOR_BATCH_CASCADE_DELETE
1130:                            | SCHEDULED_FOR_CASCADE_DELETE;
1131:                }
1132:
1133:                public boolean isScheduledForBatchCascadeDelete() {
1134:                    return (entityFlags & SCHEDULED_FOR_BATCH_CASCADE_DELETE) > 0;
1135:                }
1136:
1137:                public void setCreated() {
1138:                    ejbCreateDone = true;
1139:                    ejbPostCreateDone = true;
1140:                }
1141:
1142:                public boolean isCreated() {
1143:                    return ejbCreateDone && ejbPostCreateDone;
1144:                }
1145:
1146:                /**
1147:                 * @param fieldIndex  index of the field
1148:                 * @return true if the field is loaded
1149:                 */
1150:                public boolean isLoaded(int fieldIndex) {
1151:                    return (fieldFlags[fieldIndex] & LOADED) > 0;
1152:                }
1153:
1154:                /**
1155:                 * Marks the field as loaded.
1156:                 * @param fieldIndex  index of the field.
1157:                 */
1158:                public void setLoaded(int fieldIndex) {
1159:                    fieldFlags[fieldIndex] |= LOADED;
1160:                }
1161:
1162:                /**
1163:                 * Marks the field to be loaded.
1164:                 * @param fieldIndex  index of the field.
1165:                 */
1166:                public void setLoadRequired(int fieldIndex) {
1167:                    fieldFlags[fieldIndex] |= LOAD_REQUIRED;
1168:                }
1169:
1170:                /**
1171:                 * Marks the field to be updated.
1172:                 * @param fieldIndex  index of the field.
1173:                 */
1174:                public void setUpdateRequired(int fieldIndex) {
1175:                    fieldFlags[fieldIndex] |= DIRTY;
1176:                }
1177:
1178:                /**
1179:                 * The field will be checked for dirty state at commit.
1180:                 * @param fieldIndex  index of the field.
1181:                 */
1182:                public void setCheckDirty(int fieldIndex) {
1183:                    fieldFlags[fieldIndex] |= CHECK_DIRTY;
1184:                }
1185:
1186:                /**
1187:                 * @param fieldIndex the index of the field that should be checked for dirty state.
1188:                 * @return true if the field should be checked for dirty state.
1189:                 */
1190:                public boolean isCheckDirty(int fieldIndex) {
1191:                    return (fieldFlags[fieldIndex] & CHECK_DIRTY) > 0;
1192:                }
1193:
1194:                /**
1195:                 * Marks the field as clean.
1196:                 * @param fieldIndex  nextIndex of the field.
1197:                 */
1198:                public void setClean(int fieldIndex) {
1199:                    fieldFlags[fieldIndex] &= ~(CHECK_DIRTY | DIRTY | LOCKED);
1200:                }
1201:
1202:                /**
1203:                 * Resets field flags.
1204:                 * @param fieldIndex  nextIndex of the field.
1205:                 */
1206:                public void resetFlags(int fieldIndex) {
1207:                    fieldFlags[fieldIndex] = tableFields[fieldIndex]
1208:                            .getDefaultFlags();
1209:                }
1210:
1211:                public FieldIterator getDirtyIterator(
1212:                        EntityEnterpriseContext ctx) {
1213:                    return new MaskFieldIterator(
1214:                            (byte) (DIRTY | ADD_TO_SET_ON_UPDATE));
1215:                }
1216:
1217:                public boolean hasLockedFields() {
1218:                    boolean result = false;
1219:                    for (int i = 0; i < fieldFlags.length; ++i) {
1220:                        if ((fieldFlags[i] & (LOCKED | ADD_TO_WHERE_ON_UPDATE)) > 0) {
1221:                            result = true;
1222:                            break;
1223:                        }
1224:                    }
1225:                    return result;
1226:                }
1227:
1228:                public FieldIterator getLockedIterator(
1229:                        EntityEnterpriseContext ctx) {
1230:                    return new MaskFieldIterator(
1231:                            (byte) (LOCKED | ADD_TO_WHERE_ON_UPDATE));
1232:                }
1233:
1234:                public boolean lockValue(int fieldIndex) {
1235:                    boolean lock = false;
1236:                    byte fieldFlag = fieldFlags[fieldIndex];
1237:                    if ((fieldFlag & LOADED) > 0 && (fieldFlag & LOCKED) == 0) {
1238:                        fieldFlags[fieldIndex] |= LOCKED;
1239:                        lock = true;
1240:                    }
1241:                    return lock;
1242:                }
1243:
1244:                public FieldIterator getLoadIterator(EntityEnterpriseContext ctx) {
1245:                    return new MaskFieldIterator(LOAD_REQUIRED);
1246:                }
1247:
1248:                // Inner
1249:
1250:                private class MaskFieldIterator implements  FieldIterator {
1251:                    private final byte flagMask;
1252:                    private int nextIndex = 0;
1253:                    private int curIndex = -1;
1254:
1255:                    public MaskFieldIterator(byte flagMask) {
1256:                        this .flagMask = flagMask;
1257:                    }
1258:
1259:                    public boolean hasNext() {
1260:                        while (nextIndex < fieldFlags.length) {
1261:                            if ((fieldFlags[nextIndex] & flagMask) > 0) {
1262:                                return true;
1263:                            }
1264:
1265:                            ++nextIndex;
1266:                        }
1267:
1268:                        return false;
1269:                    }
1270:
1271:                    public JDBCCMPFieldBridge next() {
1272:                        if (!hasNext())
1273:                            throw new NoSuchElementException();
1274:                        curIndex = nextIndex;
1275:                        return tableFields[nextIndex++];
1276:                    }
1277:
1278:                    public void remove() {
1279:                        fieldFlags[curIndex] &= ~flagMask;
1280:                    }
1281:
1282:                    public void removeAll() {
1283:                        int inversedMask = ~flagMask;
1284:                        for (int i = 0; i < fieldFlags.length; ++i)
1285:                            fieldFlags[i] &= inversedMask;
1286:                    }
1287:
1288:                    public void reset() {
1289:                        nextIndex = 0;
1290:                        curIndex = -1;
1291:                    }
1292:                }
1293:            }
1294:
1295:            public static final FieldIterator EMPTY_FIELD_ITERATOR = new FieldIterator() {
1296:                public boolean hasNext() {
1297:                    return false;
1298:                }
1299:
1300:                public JDBCCMPFieldBridge next() {
1301:                    throw new NoSuchElementException();
1302:                }
1303:
1304:                public void remove() {
1305:                    throw new UnsupportedOperationException();
1306:                }
1307:
1308:                public void removeAll() {
1309:                    throw new UnsupportedOperationException();
1310:                }
1311:
1312:                public void reset() {
1313:                }
1314:            };
1315:
1316:            public static interface FieldIterator {
1317:                /**
1318:                 * @return true if there are more fields to iterate through.
1319:                 */
1320:                boolean hasNext();
1321:
1322:                /**
1323:                 * @return the next field.
1324:                 */
1325:                JDBCCMPFieldBridge next();
1326:
1327:                /**
1328:                 * Removes the current field from the iterator (not from the underlying array or another source)
1329:                 */
1330:                void remove();
1331:
1332:                /**
1333:                 * Removes all the fields from the iterator (not from the underlying array or another source).
1334:                 */
1335:                void removeAll();
1336:
1337:                /**
1338:                 * Resets the current position to the first field.
1339:                 */
1340:                void reset();
1341:            }
1342:        }
w_w_w___._j_a___va___2__s___._c___o_m___ | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.