Source Code Cross Referenced for SCOUtils.java in  » Database-ORM » JPOX » org » jpox » sco » Java Source Code / Java DocumentationJava Source Code and Java Documentation

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


0001:        /**********************************************************************
0002:        Copyright (c) 2004 Andy Jefferson and others. All rights reserved.
0003:        Licensed under the Apache License, Version 2.0 (the "License");
0004:        you may not use this file except in compliance with the License.
0005:        You may obtain a copy of the License at
0006:
0007:            http://www.apache.org/licenses/LICENSE-2.0
0008:
0009:        Unless required by applicable law or agreed to in writing, software
0010:        distributed under the License is distributed on an "AS IS" BASIS,
0011:        WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0012:        See the License for the specific language governing permissions and
0013:        limitations under the License.
0014:         
0015:
0016:        Contributors:
0017:        2007 Xuan Baldauf - Make error message "023011" a little bit more verbose
0018:            ...
0019:         **********************************************************************/package org.jpox.sco;
0020:
0021:        import java.util.Collection;
0022:        import java.util.Comparator;
0023:        import java.util.HashMap;
0024:        import java.util.Iterator;
0025:        import java.util.List;
0026:        import java.util.Map;
0027:        import java.util.Set;
0028:
0029:        import org.jpox.ClassLoaderResolver;
0030:        import org.jpox.ObjectManager;
0031:        import org.jpox.ObjectManagerHelper;
0032:        import org.jpox.StateManager;
0033:        import org.jpox.TypeManager;
0034:        import org.jpox.api.ApiAdapter;
0035:        import org.jpox.exceptions.JPOXException;
0036:        import org.jpox.exceptions.JPOXObjectNotFoundException;
0037:        import org.jpox.exceptions.JPOXUserException;
0038:        import org.jpox.metadata.AbstractClassMetaData;
0039:        import org.jpox.metadata.AbstractMemberMetaData;
0040:        import org.jpox.state.FetchPlanState;
0041:        import org.jpox.store.FieldValues;
0042:        import org.jpox.store.scostore.CollectionStore;
0043:        import org.jpox.store.scostore.MapStore;
0044:        import org.jpox.store.scostore.SetStore;
0045:        import org.jpox.util.ClassUtils;
0046:        import org.jpox.util.JPOXLogger;
0047:        import org.jpox.util.Localiser;
0048:        import org.jpox.util.StringUtils;
0049:
0050:        /**
0051:         * Collection of utilities for second class wrappers and objects.
0052:         * 
0053:         * @version $Revision: 1.80 $
0054:         */
0055:        public class SCOUtils {
0056:            /** Localiser for messages. */
0057:            private static final Localiser LOCALISER = Localiser
0058:                    .getInstance("org.jpox.Localisation");
0059:
0060:            /**
0061:             * Method to create a new SCO wrapper for a SCO type.
0062:             * The SCO wrapper will be appropriate for the passed value (which represents the instantiated type of the field)
0063:             * unless it is null when the wrapper will be appropriate for the declared type of the field.
0064:             * While the "instantiated type" and the type of "value" should be the same when value is non-null, there are
0065:             * situations where we need to create a List based collection yet have no value so pass in the declaredType
0066:             * as Collection, instantiatedType as ArrayList, and value as null.
0067:             * @param ownerSM State Manager for the owning object
0068:             * @param fmd The Field MetaData for the related field.
0069:             * @param declaredType The class of the object
0070:             * @param instantiatedType Instantiated type for the field if known
0071:             * @param value The value we are wrapping if known
0072:             * @param forInsert Whether the SCO needs inserting in the datastore with this value
0073:             * @param forUpdate Whether the SCO needs updating in the datastore with this value
0074:             * @param replaceField Whether to replace the field with this value
0075:             * @return The Second-Class Object
0076:             * @throws JPOXUserException if an error occurred when creating the SCO instance
0077:             */
0078:            public static SCO newSCOInstance(StateManager ownerSM,
0079:                    AbstractMemberMetaData fmd, Class declaredType,
0080:                    Class instantiatedType, Object value, boolean forInsert,
0081:                    boolean forUpdate, boolean replaceField) {
0082:                if (!fmd.getType().isAssignableFrom(declaredType)) {
0083:                    throw new JPOXUserException(LOCALISER.msg("023010",
0084:                            declaredType.getName(), fmd.getName(), fmd
0085:                                    .getType()));
0086:                }
0087:
0088:                String typeName = declaredType.getName();
0089:                if (instantiatedType != null) {
0090:                    // Use instantiated type if available
0091:                    typeName = instantiatedType.getName();
0092:                }
0093:                if (value != null) {
0094:                    // If we have a current value, use the actual type to define the wrapper type
0095:                    typeName = value.getClass().getName();
0096:                }
0097:
0098:                // Find the SCO wrapper type most suitable
0099:                TypeManager typeMgr = fmd.getMetaDataManager().getOMFContext()
0100:                        .getTypeManager();
0101:                boolean fullWrapper = ownerSM.getStoreManager()
0102:                        .usesDatastoreClass();
0103:                Class wrapperType = null;
0104:                if (fullWrapper) {
0105:                    wrapperType = typeMgr.getSecondClassWrapper(typeName);
0106:                } else {
0107:                    wrapperType = typeMgr.getSecondClassWrapperSimple(typeName);
0108:                }
0109:
0110:                if (wrapperType == null) {
0111:                    if (value != null && typeMgr.isSecondClassWrapper(typeName)) {
0112:                        // The passed in value is a wrapper type already, so just return it!
0113:                        SCO sco = (SCO) value;
0114:                        if (replaceField) {
0115:                            // Replace the field with this value
0116:                            ownerSM.replaceField(fmd.getAbsoluteFieldNumber(),
0117:                                    sco, false);
0118:                        }
0119:                        return sco;
0120:                    } else {
0121:                        // typeName not supported directly (no SCO wrapper for the precise type)
0122:                        if (instantiatedType != null) {
0123:                            // Try the instantiated type
0124:                            if (fullWrapper) {
0125:                                wrapperType = typeMgr
0126:                                        .getSecondClassWrapper(instantiatedType
0127:                                                .getName());
0128:                            } else {
0129:                                wrapperType = typeMgr
0130:                                        .getSecondClassWrapperSimple(instantiatedType
0131:                                                .getName());
0132:                            }
0133:                        }
0134:                        if (wrapperType == null) {
0135:                            // Try the declared type
0136:                            if (fullWrapper) {
0137:                                wrapperType = typeMgr
0138:                                        .getSecondClassWrapper(declaredType
0139:                                                .getName());
0140:                            } else {
0141:                                wrapperType = typeMgr
0142:                                        .getSecondClassWrapperSimple(declaredType
0143:                                                .getName());
0144:                            }
0145:                        }
0146:                    }
0147:                }
0148:                if (wrapperType == null) {
0149:                    throw new JPOXUserException(LOCALISER.msg("023011",
0150:                            declaredType.getName(), StringUtils
0151:                                    .toJVMIDString(value), fmd
0152:                                    .getFullFieldName()));
0153:                }
0154:
0155:                // Create the SCO wrapper
0156:                SCO sco = (SCO) ClassUtils
0157:                        .newInstance(wrapperType, new Class[] {
0158:                                org.jpox.StateManager.class, String.class },
0159:                                new Object[] { ownerSM, fmd.getName() });
0160:
0161:                if (replaceField) {
0162:                    // Replace the field with this value before initialising it
0163:                    ownerSM.replaceField(fmd.getAbsoluteFieldNumber(), sco,
0164:                            false);
0165:                }
0166:
0167:                // Initialise the SCO for use
0168:                if (value != null) {
0169:                    // Apply the existing value
0170:                    sco.initialise(value, forInsert, forUpdate);
0171:                } else {
0172:                    // Just create it empty and load from the datastore
0173:                    sco.initialise();
0174:                }
0175:
0176:                return sco;
0177:            }
0178:
0179:            /**
0180:             * Utility to generate a message representing the SCO container wrapper and its capabilities.
0181:             * @param ownerSM StateManager for the owner
0182:             * @param fieldName Field with the container
0183:             * @param cont The SCOContainer
0184:             * @param useCache Whether to use caching of values in the container
0185:             * @param queued Whether operations are queued in the wrapper
0186:             * @param allowNulls Whether to allow nulls
0187:             * @param lazyLoading Whether to use lazy loading in the wrapper
0188:             * @return The String
0189:             */
0190:            public static String getContainerInfoMessage(StateManager ownerSM,
0191:                    String fieldName, SCOContainer cont, boolean useCache,
0192:                    boolean queued, boolean allowNulls, boolean lazyLoading) {
0193:                String msg = LOCALISER.msg("023004", StringUtils
0194:                        .toJVMIDString(ownerSM.getObject()), fieldName, cont
0195:                        .getClass().getName(), "[cache-values=" + useCache
0196:                        + ", lazy-loading="
0197:                        + SCOUtils.useCachedLazyLoading(ownerSM, fieldName)
0198:                        + ", queued-operations=" + queued + ", allow-nulls="
0199:                        + allowNulls + "]");
0200:                return msg;
0201:            }
0202:
0203:            /**
0204:             * Convenience method to generate a message containing the options of this SCO wrapper.
0205:             * @param useCache Whether to cache the value in the wrapper (and not go to the datastore)
0206:             * @param queued Whether it supports queueing of updates
0207:             * @param allowNulls Whether it allows null entries
0208:             * @param lazyLoading Whether it is lazy loaded
0209:             * @return the message
0210:             */
0211:            public static String getSCOWrapperOptionsMessage(boolean useCache,
0212:                    boolean queued, boolean allowNulls, boolean lazyLoading) {
0213:                StringBuffer str = new StringBuffer();
0214:                if (useCache) {
0215:                    str.append("cached");
0216:                }
0217:                if (lazyLoading) {
0218:                    if (str.length() > 0) {
0219:                        str.append(",");
0220:                    }
0221:                    str.append("lazy-loaded");
0222:                }
0223:                if (queued) {
0224:                    if (str.length() > 0) {
0225:                        str.append(",");
0226:                    }
0227:                    str.append("queued");
0228:                }
0229:                if (allowNulls) {
0230:                    if (str.length() > 0) {
0231:                        str.append(",");
0232:                    }
0233:                    str.append("allowNulls");
0234:                }
0235:                return str.toString();
0236:            }
0237:
0238:            /**
0239:             * Utility to return whether or not to allow nulls in the container for the specified field.
0240:             * Uses the metadata extension "allow-nulls".
0241:             * @param defaultValue Default value for the container
0242:             * @param fmd MetaData for the field/property
0243:             * @return Whether to allow nulls
0244:             */
0245:            public static boolean allowNullsInContainer(boolean defaultValue,
0246:                    AbstractMemberMetaData fmd) {
0247:                boolean allow = defaultValue;
0248:                if (fmd.hasExtension("allow-nulls")) {
0249:                    // Override the default "nulls" value with the user specification
0250:                    String extValue = fmd.getValueForExtension("allow-nulls");
0251:                    if (extValue.equalsIgnoreCase("true")) {
0252:                        allow = true;
0253:                    } else if (extValue.equalsIgnoreCase("false")) {
0254:                        allow = false;
0255:                    }
0256:                }
0257:                return allow;
0258:            }
0259:
0260:            /**
0261:             * Utility to return whether to use queueing of operations in the SCO container.
0262:             * @param ownerSM The StateManager for the SCO field
0263:             * @return Whether to use queueing
0264:             */
0265:            public static boolean useContainerQueueing(StateManager ownerSM) {
0266:                if (ownerSM.getObjectManager().getTransaction().getOptimistic()) {
0267:                    return true;
0268:                } else {
0269:                    return ownerSM.getObjectManager().getOMFContext()
0270:                            .getPersistenceConfiguration()
0271:                            .getDatastoreTransactionsDelayOperations();
0272:                }
0273:            }
0274:
0275:            /**
0276:             * Utility to return whether or not to use the container cache for the
0277:             * collection/map for the passed StateManager SCO.
0278:             * @param ownerSM The StateManager for the SCO field
0279:             * @param fieldName Name of the field.
0280:             * @return Whether to use the cache.
0281:             */
0282:            public static boolean useContainerCache(StateManager ownerSM,
0283:                    String fieldName) {
0284:                if (ownerSM == null) {
0285:                    return false;
0286:                }
0287:
0288:                // Get global value for PMF
0289:                boolean useCache = ownerSM.getObjectManager().getOMFContext()
0290:                        .getPersistenceConfiguration().getCacheCollections();
0291:
0292:                AbstractMemberMetaData fmd = ownerSM.getMetaDataManager()
0293:                        .getMetaDataForMember(
0294:                                ownerSM.getObject().getClass(),
0295:                                ownerSM.getObjectManager()
0296:                                        .getClassLoaderResolver(), fieldName);
0297:                if (fmd.getOrderMetaData() != null
0298:                        && !fmd.getOrderMetaData().isIndexedList()) {
0299:                    // "Ordered Lists" have to use caching since most List operations are impossible without indexing
0300:                    useCache = true;
0301:                } else if (fmd.getContainer() != null
0302:                        && fmd.getContainer().hasExtension("cache")) {
0303:                    // User has marked the field caching policy
0304:                    useCache = (new Boolean(fmd.getContainer()
0305:                            .getValueForExtension("cache"))).booleanValue();
0306:                }
0307:
0308:                return useCache;
0309:            }
0310:
0311:            /**
0312:             * Accessor for whether the use lazy loading when caching the collection.
0313:             * @param ownerSM StateManager of the owning object
0314:             * @param fieldName Name of the collection/map field
0315:             * @return Whether to use lazy loading when caching the collection
0316:             */
0317:            public static boolean useCachedLazyLoading(StateManager ownerSM,
0318:                    String fieldName) {
0319:                if (ownerSM == null) {
0320:                    return false;
0321:                }
0322:
0323:                boolean lazy = false;
0324:
0325:                AbstractClassMetaData cmd = ownerSM.getClassMetaData();
0326:                AbstractMemberMetaData fmd = cmd
0327:                        .getMetaDataForMember(fieldName);
0328:                if (ownerSM.getObjectManager().getOMFContext()
0329:                        .getPersistenceConfiguration()
0330:                        .getCacheCollectionsLazy() != null) {
0331:                    // Global setting for PMF
0332:                    lazy = ownerSM.getObjectManager().getOMFContext()
0333:                            .getPersistenceConfiguration()
0334:                            .getCacheCollectionsLazy().booleanValue();
0335:                } else if (fmd.getContainer() != null
0336:                        && fmd.getContainer()
0337:                                .hasExtension("cache-lazy-loading")) {
0338:                    // Check if this container has a MetaData value defined
0339:                    lazy = (new Boolean(fmd.getContainer()
0340:                            .getValueForExtension("cache-lazy-loading")))
0341:                            .booleanValue();
0342:                } else {
0343:                    // Check if this SCO is in the current FetchPlan
0344:                    boolean inFP = false;
0345:                    int[] fpFields = ownerSM.getObjectManager().getFetchPlan()
0346:                            .getFetchPlanForClass(cmd)
0347:                            .getFieldsInActualFetchPlan();
0348:                    int fieldNo = fmd.getAbsoluteFieldNumber();
0349:                    if (fpFields != null && fpFields.length > 0) {
0350:                        for (int i = 0; i < fpFields.length; i++) {
0351:                            if (fpFields[i] == fieldNo) {
0352:                                inFP = true;
0353:                                break;
0354:                            }
0355:                        }
0356:                    }
0357:                    // Default to lazy loading when not in FetchPlan, and non-lazy when in FetchPlan
0358:                    lazy = !inFP;
0359:                }
0360:
0361:                return lazy;
0362:            }
0363:
0364:            /**
0365:             * Convenience method to return if a collection field has elements without their own identity.
0366:             * Checks if the elements are embedded in a join table, or in the main table, or serialised.
0367:             * @param fmd MetaData for the field
0368:             * @return Whether the elements have their own identity or not
0369:             */
0370:            public static boolean collectionHasElementsWithoutIdentity(
0371:                    AbstractMemberMetaData fmd) {
0372:                boolean elementsWithoutIdentity = false;
0373:                if (fmd.isSerialized()) {
0374:                    // Elements serialised into main table
0375:                    elementsWithoutIdentity = true;
0376:                } else if (fmd.getElementMetaData() != null
0377:                        && fmd.getElementMetaData().getEmbeddedMetaData() != null
0378:                        && fmd.getJoinMetaData() != null) {
0379:                    // Elements embedded in join table using embedded mapping
0380:                    elementsWithoutIdentity = true;
0381:                } else if (fmd.getCollection() != null
0382:                        && fmd.getCollection().isEmbeddedElement()) {
0383:                    // Elements are embedded (either serialised, or embedded in join table)
0384:                    elementsWithoutIdentity = true;
0385:                }
0386:
0387:                return elementsWithoutIdentity;
0388:            }
0389:
0390:            /**
0391:             * Convenience method to return if a map field has keys without their own identity.
0392:             * Checks if the keys are embedded in a join table, or in the main table, or serialised.
0393:             * @param fmd MetaData for the field
0394:             * @return Whether the keys have their own identity or not
0395:             */
0396:            public static boolean mapHasKeysWithoutIdentity(
0397:                    AbstractMemberMetaData fmd) {
0398:                boolean keysWithoutIdentity = false;
0399:                if (fmd.isSerialized()) {
0400:                    // Keys (and values) serialised into main table
0401:                    keysWithoutIdentity = true;
0402:                } else if (fmd.getKeyMetaData() != null
0403:                        && fmd.getKeyMetaData().getEmbeddedMetaData() != null
0404:                        && fmd.getJoinMetaData() != null) {
0405:                    // Keys embedded in join table using embedded mapping
0406:                    keysWithoutIdentity = true;
0407:                } else if (fmd.getMap() != null && fmd.getMap().isEmbeddedKey()) {
0408:                    // Keys are embedded (either serialised, or embedded in join table)
0409:                    keysWithoutIdentity = true;
0410:                }
0411:
0412:                return keysWithoutIdentity;
0413:            }
0414:
0415:            /**
0416:             * Convenience method to return if a map field has values without their own identity.
0417:             * Checks if the values are embedded in a join table, or in the main table, or serialised.
0418:             * @param fmd MetaData for the field
0419:             * @return Whether the values have their own identity or not
0420:             */
0421:            public static boolean mapHasValuesWithoutIdentity(
0422:                    AbstractMemberMetaData fmd) {
0423:                boolean valuesWithoutIdentity = false;
0424:                if (fmd.isSerialized()) {
0425:                    // Values (and keys) serialised into main table
0426:                    valuesWithoutIdentity = true;
0427:                } else if (fmd.getValueMetaData() != null
0428:                        && fmd.getValueMetaData().getEmbeddedMetaData() != null
0429:                        && fmd.getJoinMetaData() != null) {
0430:                    // Values embedded in join table using embedded mapping
0431:                    valuesWithoutIdentity = true;
0432:                } else if (fmd.getMap() != null
0433:                        && fmd.getMap().isEmbeddedValue()) {
0434:                    // Values are embedded (either serialised, or embedded in join table)
0435:                    valuesWithoutIdentity = true;
0436:                }
0437:
0438:                return valuesWithoutIdentity;
0439:            }
0440:
0441:            /**
0442:             * Convenience method to return if a collection field has the elements serialised into the
0443:             * table of the field as a single BLOB.
0444:             * @param fmd MetaData for the field
0445:             * @return Whether the elements are serialised (either explicitly or implicitly)
0446:             */
0447:            public static boolean collectionHasSerialisedElements(
0448:                    AbstractMemberMetaData fmd) {
0449:                boolean serialised = fmd.isSerialized();
0450:                if (fmd.getCollection() != null
0451:                        && fmd.getCollection().isEmbeddedElement()
0452:                        && fmd.getJoinMetaData() == null) {
0453:                    // Elements are embedded but no join table so we serialise
0454:                    serialised = true;
0455:                }
0456:
0457:                return serialised;
0458:            }
0459:
0460:            /**
0461:             * Convenience method to return if an array field has the elements stored into the
0462:             * table of the field as a single (BLOB) column.
0463:             * @param fmd MetaData for the field
0464:             * @return Whether the elements are stored in a single column
0465:             */
0466:            public static boolean arrayIsStoredInSingleColumn(
0467:                    AbstractMemberMetaData fmd) {
0468:                boolean singleColumn = fmd.isSerialized();
0469:                if (!singleColumn && fmd.getArray() != null
0470:                        && fmd.getJoinMetaData() == null) {
0471:                    if (fmd.getArray().isEmbeddedElement()) {
0472:                        // Elements are embedded but no join table so we store in a single column
0473:                        singleColumn = true;
0474:                    }
0475:
0476:                    Class elementClass = fmd.getType().getComponentType();
0477:                    ApiAdapter api = fmd.getMetaDataManager().getApiAdapter();
0478:                    if (!elementClass.isInterface()
0479:                            && !api.isPersistable(elementClass)) {
0480:                        // Array of non-PC with no join table  so store in single column of main table
0481:                        singleColumn = true;
0482:                    }
0483:                }
0484:
0485:                return singleColumn;
0486:            }
0487:
0488:            /**
0489:             * Convenience method to return if a map field has the keys/values serialised into the
0490:             * table of the field as a single BLOB.
0491:             * @param fmd MetaData for the field
0492:             * @return Whether the keys and values are serialised (either explicitly or implicitly)
0493:             */
0494:            public static boolean mapHasSerialisedKeysAndValues(
0495:                    AbstractMemberMetaData fmd) {
0496:                boolean inverseKeyField = false;
0497:                if (fmd.getKeyMetaData() != null
0498:                        && fmd.getKeyMetaData().getMappedBy() != null) {
0499:                    inverseKeyField = true;
0500:                }
0501:                boolean inverseValueField = false;
0502:                if (fmd.getValueMetaData() != null
0503:                        && fmd.getValueMetaData().getMappedBy() != null) {
0504:                    inverseValueField = true;
0505:                }
0506:                boolean serialised = fmd.isSerialized();
0507:                if (fmd.getMap() != null
0508:                        && fmd.getJoinMetaData() == null
0509:                        && (fmd.getMap().isEmbeddedKey() || fmd.getMap()
0510:                                .isEmbeddedValue()) && !inverseKeyField
0511:                        && !inverseValueField) {
0512:                    // Keys/values are embedded but no join table so we serialise the whole map
0513:                    // Note that we explicitly excluded the JPOX extension 1-N Map with the key stored in the value
0514:                    serialised = true;
0515:                }
0516:
0517:                return serialised;
0518:            }
0519:
0520:            /**
0521:             * Convenience method to update a collection to contain the elements in another collection.
0522:             * Performs the updates by calling the necessary add(), remove() methods just for the
0523:             * elements that have changed. Allows for some elements in one collection being attached
0524:             * and some being detached (so having same id, but different state)
0525:             * @param api API Adapter
0526:             * @param coll The collection to update
0527:             * @param newColl The new collection whose elements we need in "coll"
0528:             */
0529:            public static void updateCollectionWithCollection(ApiAdapter api,
0530:                    Collection coll, Collection newColl) {
0531:                if (coll == null) {
0532:                    return;
0533:                }
0534:
0535:                if (newColl == null) {
0536:                    coll.clear();
0537:                    return;
0538:                }
0539:
0540:                // Remove all elements no longer in the Collection
0541:                Iterator iter = coll.iterator();
0542:                while (iter.hasNext()) {
0543:                    Object element = iter.next();
0544:                    if (api.isPersistable(element)) {
0545:                        Object id = api.getIdForObject(element);
0546:
0547:                        if (id != null) {
0548:                            // Element has an id so compare the id
0549:                            boolean present = false;
0550:                            Iterator newIter = newColl.iterator();
0551:                            while (newIter.hasNext()) {
0552:                                Object newElement = newIter.next();
0553:                                Object newId = api.getIdForObject(newElement);
0554:
0555:                                if (id.equals(newId)) {
0556:                                    present = true;
0557:                                    break;
0558:                                }
0559:                            }
0560:
0561:                            if (!present) {
0562:                                iter.remove();
0563:                            }
0564:                        } else {
0565:                            if (!newColl.contains(element)) {
0566:                                iter.remove();
0567:                            }
0568:                        }
0569:                    } else {
0570:                        if (!newColl.contains(element)) {
0571:                            iter.remove();
0572:                        }
0573:                    }
0574:                }
0575:
0576:                // Add all new elements
0577:                Iterator newIter = newColl.iterator();
0578:                while (newIter.hasNext()) {
0579:                    Object newElement = newIter.next();
0580:
0581:                    if (api.isPersistable(newElement)) {
0582:                        Object newId = api.getIdForObject(newElement);
0583:                        if (newId != null) {
0584:                            boolean present = false;
0585:                            iter = coll.iterator();
0586:                            while (iter.hasNext()) {
0587:                                Object element = iter.next();
0588:                                Object id = api.getIdForObject(element);
0589:                                if (newId.equals(id)) {
0590:                                    present = true;
0591:                                    break;
0592:                                }
0593:                            }
0594:
0595:                            if (!present) {
0596:                                coll.add(newElement);
0597:                            }
0598:                        } else {
0599:                            if (!coll.contains(newElement)) {
0600:                                coll.add(newElement);
0601:                            }
0602:                        }
0603:                    } else {
0604:                        if (!coll.contains(newElement)) {
0605:                            coll.add(newElement);
0606:                        }
0607:                    }
0608:                }
0609:            }
0610:
0611:            /**
0612:             * Convenience method to update a Store collection to contain the elements in another collection.
0613:             * Performs the updates by calling the necessary add(), remove() methods just for the
0614:             * elements that have changed. Allows for some elements in one collection being attached
0615:             * and some being detached (so having same id, but different state)
0616:             * @param store The store to apply changes to
0617:             * @param ownerSM StateManager of the owner
0618:             * @param newColl The new collection whose elements we need in "coll"
0619:             */
0620:            public static void updateStoreWithCollection(CollectionStore store,
0621:                    StateManager ownerSM, Collection newColl) {
0622:                if (store == null || ownerSM == null) {
0623:                    return;
0624:                }
0625:
0626:                if (newColl == null) {
0627:                    store.clear(ownerSM);
0628:                    return;
0629:                }
0630:
0631:                // Retrieve the current elements from the store
0632:                Collection coll = new java.util.HashSet();
0633:                ApiAdapter api = ownerSM.getObjectManager().getApiAdapter();
0634:                Iterator iter = store.iterator(ownerSM);
0635:                while (iter.hasNext()) {
0636:                    coll.add(iter.next());
0637:                }
0638:
0639:                // Remove all elements no longer in the store
0640:                iter = coll.iterator();
0641:                while (iter.hasNext()) {
0642:                    Object element = iter.next();
0643:                    if (api.isPersistable(element)) {
0644:                        Object id = api.getIdForObject(element);
0645:
0646:                        if (id != null) {
0647:                            // Element has an id so compare the id
0648:                            boolean present = false;
0649:                            Iterator newIter = newColl.iterator();
0650:                            while (newIter.hasNext()) {
0651:                                Object newElement = newIter.next();
0652:                                Object newId = api.getIdForObject(newElement);
0653:
0654:                                if (id.equals(newId)) {
0655:                                    present = true;
0656:                                    break;
0657:                                }
0658:                            }
0659:
0660:                            if (!present) {
0661:                                store.remove(ownerSM, element, -1, true);
0662:                            }
0663:                        } else {
0664:                            if (!newColl.contains(element)) {
0665:                                store.remove(ownerSM, element, -1, true);
0666:                            }
0667:                        }
0668:                    } else {
0669:                        if (!newColl.contains(element)) {
0670:                            store.remove(ownerSM, element, -1, true);
0671:                        }
0672:                    }
0673:                }
0674:
0675:                // Add all new elements to the store
0676:                Iterator newIter = newColl.iterator();
0677:                while (newIter.hasNext()) {
0678:                    Object newElement = newIter.next();
0679:
0680:                    if (api.isPersistable(newElement)) {
0681:                        Object newId = api.getIdForObject(newElement);
0682:                        if (newId != null) {
0683:                            boolean present = false;
0684:                            iter = coll.iterator();
0685:                            while (iter.hasNext()) {
0686:                                Object element = iter.next();
0687:                                Object id = api.getIdForObject(element);
0688:                                if (newId.equals(id)) {
0689:                                    present = true;
0690:                                    break;
0691:                                }
0692:                            }
0693:
0694:                            if (!present) {
0695:                                store.add(ownerSM, newElement, -1);
0696:                            }
0697:                        } else {
0698:                            if (!coll.contains(newElement)) {
0699:                                store.add(ownerSM, newElement, -1);
0700:                            }
0701:                        }
0702:                    } else {
0703:                        if (!coll.contains(newElement)) {
0704:                            store.add(ownerSM, newElement, -1);
0705:                        }
0706:                    }
0707:                }
0708:            }
0709:
0710:            /**
0711:             * Convenience method for use by Collection/Set/HashSet attachCopy methods to
0712:             * update the passed (attached) collection using the (attached) elements passed.
0713:             * @param coll The current (attached) collection
0714:             * @param elements The collection of (attached) elements needed.
0715:             * @return If the Collection was updated
0716:             */
0717:            public static boolean updateCollectionWithCollectionElements(
0718:                    Collection coll, Collection elements) {
0719:                boolean updated = false;
0720:
0721:                // Delete any elements that are no longer in the collection
0722:                Iterator attachedIter = coll.iterator();
0723:                while (attachedIter.hasNext()) {
0724:                    Object attachedElement = attachedIter.next();
0725:                    if (!elements.contains(attachedElement)) {
0726:                        // No longer present so remove it
0727:                        attachedIter.remove();
0728:                        updated = true;
0729:                    }
0730:                }
0731:
0732:                // Add any new elements
0733:                Iterator elementsIter = elements.iterator();
0734:                while (elementsIter.hasNext()) {
0735:                    Object element = elementsIter.next();
0736:                    if (!coll.contains(element)) {
0737:                        // Not present so add it
0738:                        coll.add(element);
0739:                        updated = true;
0740:                    }
0741:                }
0742:                return updated;
0743:            }
0744:
0745:            /**
0746:             * Convenience method for use by List attachCopy methods to update the
0747:             * passed (attached) list using the (attached) list elements passed.
0748:             * @param list The current (attached) list
0749:             * @param elements The list of (attached) elements needed.
0750:             * @return If the List was updated
0751:             */
0752:            public static boolean updateListWithListElements(List list,
0753:                    List elements) {
0754:                boolean updated = false;
0755:
0756:                // This method needs to take the existing list and generate a list
0757:                // of add/remove/set/clear operations that change the list to the passed
0758:                // elements in as efficient a way as possible. The simplest is
0759:                // clear() then addAll()!, but if there are many objects and very little
0760:                // has changed this would be very inefficient.
0761:                // What we do currently is remove all elements no longer present, and then
0762:                // add any missing elements, correcting the ordering. This can be non-optimal
0763:                // in some situations.
0764:                // TODO Optimise the process
0765:                // Delete any elements that are no longer in the list
0766:                java.util.ArrayList newCopy = new java.util.ArrayList(elements);
0767:                Iterator attachedIter = list.iterator();
0768:                while (attachedIter.hasNext()) {
0769:                    Object attachedElement = attachedIter.next();
0770:                    if (!newCopy.remove(attachedElement)) {
0771:                        // No longer present, so remove it
0772:                        attachedIter.remove();
0773:                        updated = true;
0774:                    }
0775:                }
0776:
0777:                // Add any new elements that have been added
0778:                java.util.ArrayList oldCopy = new java.util.ArrayList(list);
0779:                Iterator elementsIter = elements.iterator();
0780:                while (elementsIter.hasNext()) {
0781:                    Object element = elementsIter.next();
0782:                    if (!oldCopy.remove(element)) {
0783:                        // Now present, so add it
0784:                        list.add(element);
0785:                        updated = true;
0786:                    }
0787:                }
0788:
0789:                // Update position of elements in the list to match the new order
0790:                elementsIter = elements.iterator();
0791:                int position = 0;
0792:                while (elementsIter.hasNext()) {
0793:                    Object element = elementsIter.next();
0794:                    Object currentElement = list.get(position);
0795:                    boolean updatePosition = false;
0796:                    if ((element == null && currentElement != null)
0797:                            || (element != null && currentElement == null)) {
0798:                        // Cater for null elements in the list
0799:                        updatePosition = true;
0800:                    } else if (element != null && currentElement != null
0801:                            && !currentElement.equals(element)) {
0802:                        updatePosition = true;
0803:                    }
0804:
0805:                    if (updatePosition) {
0806:                        // Update the position, taking care not to have dependent-field deletes taking place
0807:                        ((SCOList) list).set(position, element, false);
0808:                        updated = true;
0809:                    }
0810:
0811:                    position++;
0812:                }
0813:
0814:                return updated;
0815:            }
0816:
0817:            /**
0818:             * Convenience method for use by Map attachCopy methods to update the
0819:             * passed (attached) map using the (attached) map keys/values passed.
0820:             * @param api TODO
0821:             * @param map The current (attached) map
0822:             * @param keysValues The keys/values required
0823:             * @return If the map was updated
0824:             */
0825:            public static boolean updateMapWithMapKeysValues(ApiAdapter api,
0826:                    Map map, Map keysValues) {
0827:                boolean updated = false;
0828:
0829:                // Take a copy of the map so we can call remove() on the map itself
0830:                // TODO Change this to use EntrySet in the future.
0831:                // EntrySet.iterator().remove() doesn't seem to feed through to the DB at the moment
0832:                Map copy = new HashMap(map);
0833:
0834:                // Delete any keys that are no longer in the Map
0835:                Iterator attachedIter = copy.entrySet().iterator();
0836:                while (attachedIter.hasNext()) {
0837:                    Map.Entry entry = (Map.Entry) attachedIter.next();
0838:                    Object key = entry.getKey();
0839:                    if (!keysValues.containsKey(key)) {
0840:                        map.remove(key);
0841:                        updated = true;
0842:                    }
0843:                }
0844:
0845:                // Add any new keys/values and update any changed values
0846:                Iterator keysIter = keysValues.entrySet().iterator();
0847:                while (keysIter.hasNext()) {
0848:                    Map.Entry entry = (Map.Entry) keysIter.next();
0849:                    Object key = entry.getKey();
0850:                    Object value = entry.getValue();
0851:                    if (!map.containsKey(key)) {
0852:                        // Not present so add it
0853:                        map.put(key, keysValues.get(key));
0854:                        updated = true;
0855:                    } else {
0856:                        // Update any values
0857:                        if (api.isPersistable(value)) {
0858:                            // In case they have changed the PC value for this key
0859:                            // TODO Check if the PC has changed ?
0860:                            map.put(key, value);
0861:                        } else {
0862:                            Object oldValue = map.get(key);
0863:                            if ((oldValue == null && value != null)
0864:                                    || (oldValue != null && !oldValue
0865:                                            .equals(value))) {
0866:                                map.put(key, value);
0867:                            }
0868:                        }
0869:                    }
0870:                }
0871:
0872:                return updated;
0873:            }
0874:
0875:            /**
0876:             * Convenience method to populate the passed delegate Map with the keys/values from
0877:             * the associated Store.
0878:             * <P>
0879:             * The issue here is that we need to load the keys and values in as few calls as possible.
0880:             * The method employed here reads in the keys (if PersistenceCapable), then the values
0881:             * (if PersistenceCapable), and then the "entries" (ids of keys and values) so we can 
0882:             * associate the keys to the values.
0883:             * @param delegate The delegate
0884:             * @param store The Store
0885:             * @param ownerSM State Manager of the owner of the map.
0886:             */
0887:            public static void populateMapDelegateWithStoreData(Map delegate,
0888:                    MapStore store, StateManager ownerSM) {
0889:                java.util.HashSet keys = new java.util.HashSet();
0890:                if (!store.keysAreEmbedded() && !store.keysAreSerialised()) {
0891:                    // Retrieve the PersistenceCapable keys
0892:                    SetStore keystore = store.keySetStore(ownerSM
0893:                            .getObjectManager().getClassLoaderResolver());
0894:                    Iterator keyIter = keystore.iterator(ownerSM);
0895:                    while (keyIter.hasNext()) {
0896:                        keys.add(keyIter.next());
0897:                    }
0898:                }
0899:
0900:                java.util.HashSet values = new java.util.HashSet();
0901:                if (!store.valuesAreEmbedded() && !store.valuesAreSerialised()) {
0902:                    // Retrieve the PersistenceCapable values
0903:                    SetStore valuestore = store.valueSetStore(ownerSM
0904:                            .getObjectManager().getClassLoaderResolver());
0905:                    Iterator valueIter = valuestore.iterator(ownerSM);
0906:                    while (valueIter.hasNext()) {
0907:                        values.add(valueIter.next());
0908:                    }
0909:                }
0910:
0911:                // Retrieve the entries (key-value pairs so we can associate them)
0912:                ApiAdapter api = ownerSM.getObjectManager().getApiAdapter();
0913:                SetStore entries = store.entrySetStore();
0914:                Iterator entryIter = entries.iterator(ownerSM);
0915:                while (entryIter.hasNext()) {
0916:                    Map.Entry entry = (Map.Entry) entryIter.next();
0917:                    Object key = entry.getKey();
0918:                    Object value = entry.getValue();
0919:
0920:                    Object trueKey = null;
0921:                    if (store.keysAreEmbedded() || store.keysAreSerialised()) {
0922:                        // The value has been retrieved as part of the entry
0923:                        trueKey = key;
0924:                    } else {
0925:                        // Find the true key (with its fields populated)
0926:                        // The key in the entry contains just the identity
0927:                        Object pcKeyId = api.getIdForObject(key);
0928:                        Iterator keyIter = keys.iterator();
0929:                        while (keyIter.hasNext()) {
0930:                            Object obj = keyIter.next();
0931:                            if (api.getIdForObject(obj).equals(pcKeyId)) {
0932:                                trueKey = obj;
0933:                                break;
0934:                            }
0935:                        }
0936:                    }
0937:
0938:                    Object trueValue = null;
0939:                    if (store.valuesAreEmbedded()
0940:                            || store.valuesAreSerialised()) {
0941:                        // The value has been retrieved as part of the entry
0942:                        trueValue = value;
0943:                    } else {
0944:                        // Find the true value (with its fields populated)
0945:                        // The value in the entry contains just the identity
0946:                        Object pcValueId = api.getIdForObject(value);
0947:                        Iterator valueIter = values.iterator();
0948:                        while (valueIter.hasNext()) {
0949:                            Object obj = valueIter.next();
0950:                            if (api.getIdForObject(obj).equals(pcValueId)) {
0951:                                trueValue = obj;
0952:                            }
0953:                        }
0954:                    }
0955:                    delegate.put(trueKey, trueValue);
0956:                }
0957:                keys.clear();
0958:                values.clear();
0959:            }
0960:
0961:            /**
0962:             * Returns <tt>true</tt> if this collection contains the specified
0963:             * element.  More formally, returns <tt>true</tt> if and only if this
0964:             * collection contains at least one element <tt>it</tt> such that
0965:             * <tt>(o==null ? it==null : o.equals(it))</tt>.<p>
0966:             * <p>
0967:             * This implementation iterates over the elements in the collection,
0968:             * checking each element in turn for equality with the specified element.
0969:             * @param backingStore the Store
0970:             * @param sm the StateManager
0971:             * @return <tt>true</tt> if this collection contains the specified element.
0972:             */
0973:            public static Object[] toArray(CollectionStore backingStore,
0974:                    StateManager sm) {
0975:                Object[] result = new Object[backingStore.size(sm)];
0976:                Iterator it = backingStore.iterator(sm);
0977:                for (int i = 0; it.hasNext(); i++) {
0978:                    result[i] = it.next();
0979:                }
0980:                return result;
0981:            }
0982:
0983:            /**
0984:             * Returns an array containing all of the elements in this collection; 
0985:             * 
0986:             * @param  backingStore the Store
0987:             * @param  sm the StateManager
0988:             * @param  a the array into which the elements of the collection are to
0989:             *         be stored, if it is big enough; otherwise, a new array of the
0990:             *         same runtime type is allocated for this purpose.
0991:             * @return an array containing the elements of the collection.
0992:             * 
0993:             * @throws NullPointerException if the specified array is <tt>null</tt>.
0994:             * 
0995:             * @throws ArrayStoreException if the runtime type of the specified array
0996:             *         is not a supertype of the runtime type of every element in this
0997:             *         collection.
0998:             */
0999:            public static Object[] toArray(CollectionStore backingStore,
1000:                    StateManager sm, Object a[]) {
1001:                int size = backingStore.size(sm);
1002:                if (a.length < size) {
1003:                    a = (Object[]) java.lang.reflect.Array.newInstance(a
1004:                            .getClass().getComponentType(), size);
1005:                }
1006:                Iterator it = backingStore.iterator(sm);
1007:                for (int i = 0; i < size; i++) {
1008:                    a[i] = it.next();
1009:                }
1010:
1011:                if (a.length > size) {
1012:                    a[size] = null;
1013:                }
1014:
1015:                return a;
1016:            }
1017:
1018:            /**
1019:             * Convenience method for creating a Comparator using extension metadata tags for the specified field.
1020:             * Uses the extension key "comparator-name" (and allows for "comparatorName" - deprecated).
1021:             * @param fmd The field that needs the comparator
1022:             * @param clr ClassLoader resolver
1023:             * @return The Comparator
1024:             */
1025:            public static Comparator getComparator(AbstractMemberMetaData fmd,
1026:                    ClassLoaderResolver clr) {
1027:                Comparator comparator = null;
1028:                String comparatorName = null;
1029:                if (fmd.hasMap()
1030:                        && fmd.getMap().hasExtension("comparator-name")) {
1031:                    comparatorName = fmd.getMap().getValueForExtension(
1032:                            "comparator-name");
1033:                } else if (fmd.hasCollection()
1034:                        && fmd.getCollection().hasExtension("comparator-name")) {
1035:                    comparatorName = fmd.getCollection().getValueForExtension(
1036:                            "comparator-name");
1037:                } else if (fmd.hasMap()
1038:                        && fmd.getMap().hasExtension("comparatorName")) {
1039:                    comparatorName = fmd.getMap().getValueForExtension(
1040:                            "comparatorName");
1041:                } else if (fmd.hasCollection()
1042:                        && fmd.getCollection().hasExtension("comparatorName")) {
1043:                    comparatorName = fmd.getCollection().getValueForExtension(
1044:                            "comparatorName");
1045:                }
1046:
1047:                if (comparatorName != null) {
1048:                    Class comparatorCls = null;
1049:                    try {
1050:                        comparatorCls = clr.classForName(comparatorName);
1051:                        comparator = (Comparator) ClassUtils.newInstance(
1052:                                comparatorCls, null, null);
1053:                    } catch (JPOXException jpe) {
1054:                        JPOXLogger.PERSISTENCE.warn(LOCALISER.msg("023012", fmd
1055:                                .getFullFieldName(), comparatorName));
1056:                    }
1057:                }
1058:                return comparator;
1059:            }
1060:
1061:            /**
1062:             * Convenience method to refresh fetch plan fields for all elements for a collection field.
1063:             * All elements that are PersistenceCapable will be made transient.
1064:             * @param ownerSM StateManager for the owning object with the collection
1065:             * @param elements The elements in the collection
1066:             */
1067:            public static void refreshFetchPlanFieldsForCollection(
1068:                    StateManager ownerSM, Object[] elements) {
1069:                ApiAdapter api = ownerSM.getObjectManager().getApiAdapter();
1070:                for (int i = 0; i < elements.length; i++) {
1071:                    if (api.isPersistable(elements[i])) {
1072:                        ownerSM.getObjectManager().refreshObject(elements[i]);
1073:                    }
1074:                }
1075:            }
1076:
1077:            /**
1078:             * Convenience method to refresh fetch plan fields for all elements for a map field.
1079:             * All elements that are PersistenceCapable will be made transient.
1080:             * @param ownerSM StateManager for the owning object with the map
1081:             * @param entries The entries in the map
1082:             */
1083:            public static void refreshFetchPlanFieldsForMap(
1084:                    StateManager ownerSM, Set entries) {
1085:                ApiAdapter api = ownerSM.getObjectManager().getApiAdapter();
1086:                for (Iterator it = entries.iterator(); it.hasNext();) {
1087:                    Map.Entry entry = (Map.Entry) it.next();
1088:                    Object val = entry.getValue();
1089:                    Object key = entry.getKey();
1090:                    if (api.isPersistable(key)) {
1091:                        ownerSM.getObjectManager().refreshObject(key);
1092:                    }
1093:                    if (api.isPersistable(val)) {
1094:                        ownerSM.getObjectManager().refreshObject(val);
1095:                    }
1096:                }
1097:            }
1098:
1099:            /**
1100:             * Convenience method to detach (recursively) all elements for a collection field.
1101:             * All elements that are PersistenceCapable will be detached.
1102:             * @param ownerSM StateManager for the owning object with the collection
1103:             * @param elements The elements in the collection
1104:             * @param state FetchPlan state
1105:             */
1106:            public static void detachForCollection(StateManager ownerSM,
1107:                    Object[] elements, FetchPlanState state) {
1108:                ApiAdapter api = ownerSM.getObjectManager().getApiAdapter();
1109:                for (int i = 0; i < elements.length; i++) {
1110:                    if (api.isPersistable(elements[i])) {
1111:                        ownerSM.getObjectManager().detachObject(elements[i],
1112:                                state);
1113:                    }
1114:                }
1115:            }
1116:
1117:            /**
1118:             * Convenience method to detach copies (recursively) of all elements for a collection field.
1119:             * All elements that are PersistenceCapable will be detached.
1120:             * @param ownerSM StateManager for the owning object with the collection
1121:             * @param elements The elements in the collection
1122:             * @param state FetchPlan state
1123:             * @param detached Collection to add the detached copies to
1124:             */
1125:            public static void detachCopyForCollection(StateManager ownerSM,
1126:                    Object[] elements, FetchPlanState state, Collection detached) {
1127:                ApiAdapter api = ownerSM.getObjectManager().getApiAdapter();
1128:                for (int i = 0; i < elements.length; i++) {
1129:                    if (elements[i] == null) {
1130:                        detached.add(null);
1131:                    } else {
1132:                        Object object = elements[i];
1133:                        if (api.isPersistable(object)) {
1134:                            detached.add(ownerSM.getObjectManager()
1135:                                    .detachObjectCopy(object, state));
1136:                        } else {
1137:                            detached.add(object);
1138:                        }
1139:                    }
1140:                }
1141:            }
1142:
1143:            /**
1144:             * Convenience method to attach (recursively) all elements for a collection field.
1145:             * All elements that are PersistenceCapable will be attached.
1146:             * @param ownerSM StateManager for the owning object with the collection
1147:             * @param elements The elements in the collection
1148:             * @param elementsWithoutIdentity Whether the elements have their own identity
1149:             */
1150:            public static void attachForCollection(StateManager ownerSM,
1151:                    Object[] elements, boolean elementsWithoutIdentity) {
1152:                ApiAdapter api = ownerSM.getObjectManager().getApiAdapter();
1153:                for (int i = 0; i < elements.length; i++) {
1154:                    if (api.isPersistable(elements[i])) {
1155:                        ownerSM.getObjectManager().attachObject(elements[i],
1156:                                elementsWithoutIdentity);
1157:                    }
1158:                }
1159:            }
1160:
1161:            /**
1162:             * Method to return an attached copy of the passed (detached) value. The returned attached copy
1163:             * is a SCO wrapper. Goes through the existing elements in the store for this owner field and
1164:             * removes ones no longer present, and adds new elements. All elements in the (detached)
1165:             * value are attached.
1166:             * @param ownerSM StateManager for the owning object with the collection
1167:             * @param detachedElements The detached elements in the collection
1168:             * @param attached Collection to add the attached copies to
1169:             * @param elementsWithoutIdentity Whether the elements have their own identity
1170:             */
1171:            public static void attachCopyForCollection(StateManager ownerSM,
1172:                    Object[] detachedElements, Collection attached,
1173:                    boolean elementsWithoutIdentity) {
1174:                ApiAdapter api = ownerSM.getObjectManager().getApiAdapter();
1175:                for (int i = 0; i < detachedElements.length; i++) {
1176:                    if (api.isPersistable(detachedElements[i])
1177:                            && api.isDetachable(detachedElements[i])) {
1178:                        attached.add(ownerSM.getObjectManager()
1179:                                .attachObjectCopy(detachedElements[i],
1180:                                        elementsWithoutIdentity));
1181:                    } else {
1182:                        attached.add(detachedElements[i]);
1183:                    }
1184:                }
1185:            }
1186:
1187:            /**
1188:             * Convenience method to detach (recursively) all elements for a map field.
1189:             * All elements that are PersistenceCapable will be detached.
1190:             * @param ownerSM StateManager for the owning object with the map
1191:             * @param entries The entries in the map
1192:             * @param state FetchPlan state
1193:             */
1194:            public static void detachForMap(StateManager ownerSM, Set entries,
1195:                    FetchPlanState state) {
1196:                ApiAdapter api = ownerSM.getObjectManager().getApiAdapter();
1197:                for (Iterator it = entries.iterator(); it.hasNext();) {
1198:                    Map.Entry entry = (Map.Entry) it.next();
1199:                    Object val = entry.getValue();
1200:                    Object key = entry.getKey();
1201:                    if (api.isPersistable(key)) {
1202:                        ownerSM.getObjectManager().detachObject(key, state);
1203:                    }
1204:                    if (api.isPersistable(val)) {
1205:                        ownerSM.getObjectManager().detachObject(val, state);
1206:                    }
1207:                }
1208:            }
1209:
1210:            /**
1211:             * Convenience method to detach copies (recursively) of all elements for a map field.
1212:             * All elements that are PersistenceCapable will be detached.
1213:             * @param ownerSM StateManager for the owning object with the map
1214:             * @param entries The entries in the map
1215:             * @param state FetchPlan state
1216:             * @param detached Map to add the detached copies to
1217:             */
1218:            public static void detachCopyForMap(StateManager ownerSM,
1219:                    Set entries, FetchPlanState state, Map detached) {
1220:                ApiAdapter api = ownerSM.getObjectManager().getApiAdapter();
1221:                for (Iterator it = entries.iterator(); it.hasNext();) {
1222:                    Map.Entry entry = (Map.Entry) it.next();
1223:                    Object val = entry.getValue();
1224:                    Object key = entry.getKey();
1225:                    if (api.isPersistable(val)) {
1226:                        val = ownerSM.getObjectManager().detachObjectCopy(val,
1227:                                state);
1228:                    }
1229:                    if (api.isPersistable(key)) {
1230:                        key = ownerSM.getObjectManager().detachObjectCopy(key,
1231:                                state);
1232:                    }
1233:                    detached.put(key, val);
1234:                }
1235:            }
1236:
1237:            /**
1238:             * Convenience method to attach (recursively) all elements for a map field.
1239:             * All elements that are PersistenceCapable will be attached.
1240:             * @param ownerSM StateManager for the owning object with the map
1241:             * @param entries The entries in the map
1242:             * @param keysWithoutIdentity Whether the keys have their own identity
1243:             * @param valuesWithoutIdentity Whether the values have their own identity
1244:             */
1245:            public static void attachForMap(StateManager ownerSM, Set entries,
1246:                    boolean keysWithoutIdentity, boolean valuesWithoutIdentity) {
1247:                ApiAdapter api = ownerSM.getObjectManager().getApiAdapter();
1248:                for (Iterator it = entries.iterator(); it.hasNext();) {
1249:                    Map.Entry entry = (Map.Entry) it.next();
1250:                    Object val = entry.getValue();
1251:                    Object key = entry.getKey();
1252:                    if (api.isPersistable(key)) {
1253:                        ownerSM.getObjectManager().attachObject(key,
1254:                                keysWithoutIdentity);
1255:                    }
1256:                    if (api.isPersistable(val)) {
1257:                        ownerSM.getObjectManager().attachObject(val,
1258:                                valuesWithoutIdentity);
1259:                    }
1260:                }
1261:            }
1262:
1263:            /**
1264:             * Method to return an attached copy of the passed (detached) value. The returned attached copy
1265:             * is a SCO wrapper. Goes through the existing elements in the store for this owner field and
1266:             * removes ones no longer present, and adds new elements. All elements in the (detached)
1267:             * value are attached.
1268:             * @param ownerSM StateManager for the owning object with the map
1269:             * @param detachedEntries The detached entries in the map
1270:             * @param attached Map to add the attached copies to
1271:             * @param keysWithoutIdentity Whether the keys have their own identity
1272:             * @param valuesWithoutIdentity Whether the values have their own identity
1273:             */
1274:            public static void attachCopyForMap(StateManager ownerSM,
1275:                    Set detachedEntries, Map attached,
1276:                    boolean keysWithoutIdentity, boolean valuesWithoutIdentity) {
1277:                Iterator iter = detachedEntries.iterator();
1278:                ApiAdapter api = ownerSM.getObjectManager().getApiAdapter();
1279:                while (iter.hasNext()) {
1280:                    Map.Entry entry = (Map.Entry) iter.next();
1281:                    Object val = entry.getValue();
1282:                    Object key = entry.getKey();
1283:                    if (api.isPersistable(val) && api.isDetachable(val)) {
1284:                        val = ownerSM.getObjectManager().attachObjectCopy(val,
1285:                                valuesWithoutIdentity);
1286:                    }
1287:                    if (api.isPersistable(key) && api.isDetachable(key)) {
1288:                        key = ownerSM.getObjectManager().attachObjectCopy(key,
1289:                                keysWithoutIdentity);
1290:                    }
1291:                    attached.put(key, val);
1292:                }
1293:            }
1294:
1295:            /**
1296:             * Method to check if an object to be stored in a SCO container is already persistent, or is managed
1297:             * by a different ObjectManager. If not persistent, this call will persist it. If not yet flushed to the
1298:             * datastore this call will flush it.
1299:             * @param om ObjectManager that we are using
1300:             * @param object The object
1301:             * @param fieldValues Values for any fields when persisting (if the object needs persisting)
1302:             * @return Whether the object was persisted during this call
1303:             */
1304:            public static boolean validateObjectForWriting(ObjectManager om,
1305:                    Object object, FieldValues fieldValues) {
1306:                boolean persisted = false;
1307:                ApiAdapter api = om.getApiAdapter();
1308:                if (api.isPersistable(object)) {
1309:                    ObjectManager objectOM = ObjectManagerHelper
1310:                            .getObjectManager(object);
1311:                    if (objectOM != null && om != objectOM) {
1312:                        throw new JPOXUserException(LOCALISER.msg("023009",
1313:                                StringUtils.toJVMIDString(object)), api
1314:                                .getIdForObject(object));
1315:                    } else if (!api.isPersistent(object)) {
1316:                        // Not persistent, so either is detached, or needs persisting for first time
1317:                        boolean exists = false;
1318:                        if (api.isDetached(object)) {
1319:                            if (om.getOMFContext()
1320:                                    .getPersistenceConfiguration()
1321:                                    .getAttachSameDatastore()) {
1322:                                // Assume that it is detached from this datastore
1323:                                exists = true;
1324:                            } else {
1325:                                // Check if the (attached) object exists in this datastore
1326:                                try {
1327:                                    Object obj = om.findObject(api
1328:                                            .getIdForObject(object), true,
1329:                                            false, object.getClass().getName());
1330:                                    if (obj != null) {
1331:                                        // PM.getObjectById creates a dummy object to represent this object and automatically
1332:                                        // enlists it in the txn. Evict it to avoid issues with reachability
1333:                                        StateManager objSM = om
1334:                                                .findStateManager(obj);
1335:                                        if (objSM != null) {
1336:                                            om.evictFromTransaction(objSM);
1337:                                        }
1338:                                    }
1339:                                    exists = true;
1340:                                } catch (JPOXObjectNotFoundException onfe) {
1341:                                    exists = false;
1342:                                }
1343:                            }
1344:                        }
1345:                        if (!exists) {
1346:                            // Persist the object
1347:                            om.persistObjectInternal(object, fieldValues, null,
1348:                                    -1, StateManager.PC);
1349:                            persisted = true;
1350:                        }
1351:                    } else {
1352:                        // Persistent, but is it flushed to the datastore?
1353:                        StateManager objectSM = om.findStateManager(object);
1354:                        if (objectSM.isWaitingToBeFlushedToDatastore()) {
1355:                            // Newly persistent but still not flushed (e.g in optimistic txn)
1356:                            // Process any fieldValues
1357:                            if (fieldValues != null) {
1358:                                objectSM.loadFieldValues(fieldValues);
1359:                            }
1360:
1361:                            // Now flush it
1362:                            objectSM.flush();
1363:                        }
1364:                    }
1365:                }
1366:                return persisted;
1367:            }
1368:
1369:            /**
1370:             * Method to check if objects to be stored in a SCO container are already persistent, or are managed by 
1371:             * a different ObjectManager. If not persistent, this call will persist them.
1372:             * @param om ObjectManager being used
1373:             * @param objects The objects (array, or Collection)
1374:             */
1375:            public static void validateObjectsForWriting(ObjectManager om,
1376:                    Object objects) {
1377:                if (objects != null) {
1378:                    if (objects.getClass().isArray()) {
1379:                        if (!objects.getClass().getComponentType()
1380:                                .isPrimitive()) {
1381:                            Object[] obj = ((Object[]) objects);
1382:                            for (int i = 0; i < obj.length; i++) {
1383:                                validateObjectForWriting(om, obj[i], null);
1384:                            }
1385:                        }
1386:                    } else if (objects instanceof  Collection) {
1387:                        Collection col = (Collection) objects;
1388:                        Iterator it = col.iterator();
1389:                        while (it.hasNext()) {
1390:                            validateObjectForWriting(om, it.next(), null);
1391:                        }
1392:                    }
1393:                }
1394:            }
1395:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.