Source Code Cross Referenced for QueryReferenceBroker.java in  » Database-ORM » db-ojb » org » apache » ojb » broker » core » 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 » db ojb » org.apache.ojb.broker.core 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        package org.apache.ojb.broker.core;
0002:
0003:        /* Copyright 2003-2005 The Apache Software Foundation
0004:         *
0005:         * Licensed under the Apache License, Version 2.0 (the "License");
0006:         * you may not use this file except in compliance with the License.
0007:         * You may obtain a copy of the License at
0008:         *
0009:         *     http://www.apache.org/licenses/LICENSE-2.0
0010:         *
0011:         * Unless required by applicable law or agreed to in writing, software
0012:         * distributed under the License is distributed on an "AS IS" BASIS,
0013:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014:         * See the License for the specific language governing permissions and
0015:         * limitations under the License.
0016:         */
0017:
0018:        import java.lang.reflect.Array;
0019:        import java.util.ArrayList;
0020:        import java.util.Collection;
0021:        import java.util.HashMap;
0022:        import java.util.Iterator;
0023:        import java.util.List;
0024:        import java.util.Map;
0025:
0026:        import org.apache.ojb.broker.Identity;
0027:        import org.apache.ojb.broker.ManageableCollection;
0028:        import org.apache.ojb.broker.PBLifeCycleEvent;
0029:        import org.apache.ojb.broker.PersistenceBrokerException;
0030:        import org.apache.ojb.broker.accesslayer.OJBIterator;
0031:        import org.apache.ojb.broker.accesslayer.PagingIterator;
0032:        import org.apache.ojb.broker.accesslayer.PlainPrefetcher;
0033:        import org.apache.ojb.broker.accesslayer.RelationshipPrefetcher;
0034:        import org.apache.ojb.broker.core.proxy.CollectionProxyDefaultImpl;
0035:        import org.apache.ojb.broker.core.proxy.CollectionProxyListener;
0036:        import org.apache.ojb.broker.core.proxy.IndirectionHandler;
0037:        import org.apache.ojb.broker.core.proxy.MaterializationListener;
0038:        import org.apache.ojb.broker.core.proxy.ProxyHelper;
0039:        import org.apache.ojb.broker.metadata.ClassDescriptor;
0040:        import org.apache.ojb.broker.metadata.ClassNotPersistenceCapableException;
0041:        import org.apache.ojb.broker.metadata.CollectionDescriptor;
0042:        import org.apache.ojb.broker.metadata.FieldDescriptor;
0043:        import org.apache.ojb.broker.metadata.FieldHelper;
0044:        import org.apache.ojb.broker.metadata.MetadataException;
0045:        import org.apache.ojb.broker.metadata.ObjectReferenceDescriptor;
0046:        import org.apache.ojb.broker.metadata.fieldaccess.PersistentField;
0047:        import org.apache.ojb.broker.query.Criteria;
0048:        import org.apache.ojb.broker.query.Query;
0049:        import org.apache.ojb.broker.query.QueryByCriteria;
0050:        import org.apache.ojb.broker.query.QueryFactory;
0051:        import org.apache.ojb.broker.util.BrokerHelper;
0052:        import org.apache.ojb.broker.util.collections.ManageableArrayList;
0053:        import org.apache.ojb.broker.util.collections.ManageableHashSet;
0054:        import org.apache.ojb.broker.util.collections.RemovalAwareCollection;
0055:        import org.apache.ojb.broker.util.collections.RemovalAwareList;
0056:        import org.apache.ojb.broker.util.collections.RemovalAwareSet;
0057:        import org.apache.ojb.broker.util.logging.Logger;
0058:        import org.apache.ojb.broker.util.logging.LoggerFactory;
0059:
0060:        /**
0061:         * Encapsulates 1:1 and 1:n references and collection references stuff.
0062:         *
0063:         * TODO: Should we made this class independend from PB implementation class
0064:         * and only use PB interface methods?
0065:         *
0066:         * @author <a href="mailto:armin@codeAuLait.de">Armin Waibel</a>
0067:         * @version $Id: QueryReferenceBroker.java,v 1.17.2.17 2005/12/21 22:25:00 tomdz Exp $
0068:         */
0069:        public class QueryReferenceBroker {
0070:            private Logger log = LoggerFactory
0071:                    .getLogger(QueryReferenceBroker.class);
0072:
0073:            private PersistenceBrokerImpl pb;
0074:            private HashMap m_retrievalTasks;
0075:            private ArrayList prefetchingListeners;
0076:            private final boolean batchRetrieval = true;
0077:            private final boolean prefetchProxies = true;
0078:            private Class classToPrefetch;
0079:            private PBLifeCycleEvent afterLookupEvent;
0080:
0081:            public QueryReferenceBroker(final PersistenceBrokerImpl pb) {
0082:                this .pb = pb;
0083:                afterLookupEvent = new PBLifeCycleEvent(pb,
0084:                        PBLifeCycleEvent.Type.AFTER_LOOKUP);
0085:            }
0086:
0087:            /**
0088:             * retrieve a collection of itemClass Objects matching the Query query
0089:             * @param collectionClass type the collection to be returned
0090:             * @param itemClass Class of item in collection
0091:             * @param query the query
0092:             */
0093:            private ManageableCollection getCollectionByQuery(
0094:                    Class collectionClass, Class itemClass, Query query)
0095:                    throws ClassNotPersistenceCapableException,
0096:                    PersistenceBrokerException {
0097:                if (log.isDebugEnabled())
0098:                    log.debug("getCollectionByQuery (" + collectionClass + ", "
0099:                            + itemClass + ", " + query + ")");
0100:
0101:                ClassDescriptor cld = pb.getClassDescriptor(itemClass);
0102:                ManageableCollection result = null;
0103:                OJBIterator iter = null;
0104:                int fullSize = -1;
0105:                int size = 0;
0106:
0107:                final boolean isRetrievalTasksCreated = batchRetrieval
0108:                        && m_retrievalTasks == null;
0109:                if (isRetrievalTasksCreated) {
0110:                    // Maps ReferenceDescriptors to HashSets of owners
0111:                    m_retrievalTasks = new HashMap();
0112:                }
0113:
0114:                // ==> enable materialization cache
0115:                pb.getInternalCache().enableMaterializationCache();
0116:                try {
0117:                    result = (ManageableCollection) collectionClass
0118:                            .newInstance();
0119:
0120:                    // now iterate over all elements and add them to the new collection
0121:                    // lifecycle events are disabled
0122:                    iter = pb.getIteratorFromQuery(query, cld);
0123:                    iter.disableLifeCycleEvents();
0124:
0125:                    // BRJ : get fullSizefor Query
0126:                    // to be removed when Query.fullSize is removed
0127:                    if (iter instanceof  PagingIterator) {
0128:                        fullSize = iter.fullSize();
0129:                    }
0130:
0131:                    while (iter.hasNext()) {
0132:                        Object candidate = iter.next();
0133:
0134:                        /**
0135:                         * MBAIRD
0136:                         * candidate CAN be null in the case of materializing from an iterator based
0137:                         * on a query for a class that is mapped to a table that has other classes
0138:                         * mapped to that table as well, but aren't extents.
0139:                         */
0140:                        if (candidate != null) {
0141:                            IndirectionHandler handler = ProxyHelper
0142:                                    .getIndirectionHandler(candidate);
0143:
0144:                            if ((handler != null)
0145:                                    || itemClass.isAssignableFrom(candidate
0146:                                            .getClass())) {
0147:                                result.ojbAdd(candidate);
0148:
0149:                                // BRJ: count added objects
0150:                                // to be removed when Query.fullSize is removed
0151:                                size++;
0152:                            } else {
0153:                                //warn the user
0154:                                log
0155:                                        .warn("Candidate object ["
0156:                                                + candidate
0157:                                                + "] class ["
0158:                                                + candidate.getClass()
0159:                                                        .getName()
0160:                                                + "] is not a subtype of ["
0161:                                                + itemClass.getName()
0162:                                                + "] or any type of proxy. NOT INCLUDED in result collection");
0163:                            }
0164:                            if (prefetchProxies && (handler != null)
0165:                                    && (cld.getProxyPrefetchingLimit() > 0)
0166:                                    && addRetrievalTask(candidate, this )) {
0167:                                new PBMaterializationListener(candidate,
0168:                                        m_retrievalTasks, this , cld
0169:                                                .getProxyPrefetchingLimit());
0170:                            }
0171:                        }
0172:                    }
0173:
0174:                    if (isRetrievalTasksCreated) {
0175:                        // turn off auto prefetching for related proxies
0176:                        final Class saveClassToPrefetch = classToPrefetch;
0177:                        classToPrefetch = null;
0178:                        try {
0179:                            performRetrievalTasks();
0180:                        } finally {
0181:                            classToPrefetch = saveClassToPrefetch;
0182:                        }
0183:                    }
0184:
0185:                    // BRJ: fire LifeCycleEvents after execution of RetrievalTasks
0186:                    // to ensure objects are fully materialized
0187:                    Iterator resultIter = result.ojbIterator();
0188:                    while (resultIter.hasNext()) {
0189:                        Object obj = resultIter.next();
0190:                        afterLookupEvent.setTarget(obj);
0191:                        pb.fireBrokerEvent(afterLookupEvent);
0192:                        afterLookupEvent.setTarget(null);
0193:                    }
0194:
0195:                    // ==> disable materialization cache
0196:                    pb.getInternalCache().disableMaterializationCache();
0197:                } catch (RuntimeException e) {
0198:                    // ==> clear materialization cache
0199:                    pb.getInternalCache().doLocalClear();
0200:                    throw e;
0201:                } catch (Exception ex) {
0202:                    // ==> clear materialization cache
0203:                    pb.getInternalCache().doLocalClear();
0204:                    log.error(ex);
0205:                    throw new PersistenceBrokerException(ex);
0206:                } finally {
0207:                    if (iter != null) {
0208:                        iter.releaseDbResources();
0209:                    }
0210:                    if (isRetrievalTasksCreated) {
0211:                        m_retrievalTasks = null;
0212:                    }
0213:                }
0214:
0215:                // BRJ: store fullSize in Query to re-enable deprecated functionality
0216:                // to be removed when Query.fullSize is removed
0217:                if (fullSize < 0) {
0218:                    fullSize = size; // use size of result
0219:                }
0220:                query.fullSize(fullSize);
0221:
0222:                return result;
0223:            }
0224:
0225:            /**
0226:             * retrieve a collection of type collectionClass matching the Query query
0227:             * if lazy = true return a CollectionProxy
0228:             *
0229:             * @param collectionClass
0230:             * @param query
0231:             * @param lazy
0232:             * @return ManageableCollection
0233:             * @throws PersistenceBrokerException
0234:             */
0235:            public ManageableCollection getCollectionByQuery(
0236:                    Class collectionClass, Query query, boolean lazy)
0237:                    throws PersistenceBrokerException {
0238:                ManageableCollection result;
0239:
0240:                try {
0241:                    // BRJ: return empty Collection  for null query
0242:                    if (query == null) {
0243:                        result = (ManageableCollection) collectionClass
0244:                                .newInstance();
0245:                    } else {
0246:                        if (lazy) {
0247:                            result = pb.getProxyFactory()
0248:                                    .createCollectionProxy(pb.getPBKey(),
0249:                                            query, collectionClass);
0250:                        } else {
0251:                            result = getCollectionByQuery(collectionClass,
0252:                                    query.getSearchClass(), query);
0253:                        }
0254:                    }
0255:                    return result;
0256:                } catch (Exception e) {
0257:                    if (e instanceof  PersistenceBrokerException) {
0258:                        throw (PersistenceBrokerException) e;
0259:                    } else {
0260:                        throw new PersistenceBrokerException(e);
0261:                    }
0262:                }
0263:            }
0264:
0265:            /**
0266:             * retrieve a collection of itemClass Objects matching the Query query
0267:             */
0268:            public Collection getCollectionByQuery(Query query, boolean lazy)
0269:                    throws PersistenceBrokerException {
0270:                // thma: the following cast is safe because:
0271:                // 1. ManageableVector implements Collection (will be returned if lazy == false)
0272:                // 2. CollectionProxy implements Collection (will be returned if lazy == true)
0273:                return (Collection) getCollectionByQuery(
0274:                        RemovalAwareCollection.class, query, lazy);
0275:            }
0276:
0277:            private Class getCollectionTypeClass(CollectionDescriptor cds)
0278:                    throws PersistenceBrokerException {
0279:                // BRJ: do not use RemovalAwareCollection for m:n relationships
0280:                // see http://db.apache.org/ojb/docu/guides/basic-technique.html#Mapping+m%3An+associations
0281:
0282:                Class fieldType = cds.getPersistentField().getType();
0283:                Class collType;
0284:
0285:                if (fieldType.isArray()
0286:                        || fieldType
0287:                                .isAssignableFrom(RemovalAwareCollection.class)) {
0288:                    collType = cds.isMtoNRelation() ? ManageableArrayList.class
0289:                            : RemovalAwareCollection.class;
0290:                } else if (fieldType.isAssignableFrom(RemovalAwareList.class)) {
0291:                    collType = cds.isMtoNRelation() ? ManageableArrayList.class
0292:                            : RemovalAwareList.class;
0293:                } else if (fieldType.isAssignableFrom(RemovalAwareSet.class)) {
0294:                    collType = cds.isMtoNRelation() ? ManageableHashSet.class
0295:                            : RemovalAwareSet.class;
0296:                } else if (ManageableCollection.class
0297:                        .isAssignableFrom(fieldType)) {
0298:                    collType = fieldType;
0299:                } else {
0300:                    throw new MetadataException(
0301:                            "Cannot determine a default collection type for collection "
0302:                                    + cds.getAttributeName()
0303:                                    + " in type "
0304:                                    + cds.getClassDescriptor()
0305:                                            .getClassNameOfObject());
0306:                }
0307:                return collType;
0308:            }
0309:
0310:            /**
0311:             * @return true if this is the first task for the given ObjectReferenceDescriptor
0312:             */
0313:            private boolean addRetrievalTask(Object obj, Object key) {
0314:                ArrayList owners = (ArrayList) m_retrievalTasks.get(key);
0315:                boolean isFirst = false;
0316:
0317:                if (owners == null) {
0318:                    owners = new ArrayList();
0319:                    m_retrievalTasks.put(key, owners);
0320:                    isFirst = true;
0321:                }
0322:                owners.add(obj);
0323:                return isFirst;
0324:            }
0325:
0326:            /**
0327:             * Perform the stored retrieval tasks
0328:             * BRJ: made it public to access it from BasePrefetcher
0329:             * TODO: this is a quick fix !
0330:             */
0331:            public void performRetrievalTasks() {
0332:                if (m_retrievalTasks == null) {
0333:                    return;
0334:                }
0335:
0336:                while (m_retrievalTasks.size() > 0) {
0337:                    HashMap tmp = m_retrievalTasks;
0338:                    m_retrievalTasks = new HashMap();
0339:                    // during execution of these tasks new tasks may be added
0340:
0341:                    for (Iterator it = tmp.entrySet().iterator(); it.hasNext();) {
0342:                        Map.Entry entry = (Map.Entry) it.next();
0343:                        Object key = entry.getKey();
0344:
0345:                        if (!(key instanceof  ObjectReferenceDescriptor)) {
0346:                            continue;
0347:                        }
0348:
0349:                        ObjectReferenceDescriptor ord = (ObjectReferenceDescriptor) key;
0350:                        RelationshipPrefetcher prefetcher;
0351:                        ArrayList owners = (ArrayList) entry.getValue();
0352:
0353:                        //                if (ord instanceof SuperReferenceDescriptor || ord.isLazy() || (ord.getItemProxyClass() != null))
0354:                        if (ord.isLazy() || (ord.getItemProxyClass() != null)) {
0355:                            continue;
0356:                        }
0357:
0358:                        prefetcher = pb.getRelationshipPrefetcherFactory()
0359:                                .createRelationshipPrefetcher(ord);
0360:                        prefetcher.prefetchRelationship(owners);
0361:                        it.remove();
0362:                    }
0363:                }
0364:            }
0365:
0366:            /**
0367:             * Retrieve a single Reference.
0368:             * This implementation retrieves a referenced object from the data backend
0369:             * if <b>cascade-retrieve</b> is true or if <b>forced</b> is true.
0370:             *
0371:             * @param obj - object that will have it's field set with a referenced object.
0372:             * @param cld - the ClassDescriptor describring obj
0373:             * @param rds - the ObjectReferenceDescriptor of the reference attribute to be loaded
0374:             * @param forced - if set to true, the reference is loaded even if the rds differs.
0375:             */
0376:            public void retrieveReference(Object obj, ClassDescriptor cld,
0377:                    ObjectReferenceDescriptor rds, boolean forced) {
0378:                PersistentField refField;
0379:                Object refObj = null;
0380:
0381:                if (forced || rds.getCascadeRetrieve()) {
0382:                    pb.getInternalCache().enableMaterializationCache();
0383:                    try {
0384:                        Identity id = getReferencedObjectIdentity(obj, rds, cld);
0385:                        boolean isRefObjDefined = true;
0386:
0387:                        if (id == null) {
0388:                            refObj = null;
0389:                        } //JMM : why not see if the object has already been loaded
0390:                        else if (pb.serviceObjectCache().lookup(id) != null) {
0391:                            refObj = pb.doGetObjectByIdentity(id);
0392:                            if (rds.isSuperReferenceDescriptor()) {
0393:                                // walk the super-references
0394:                                ClassDescriptor super Cld = cld.getRepository()
0395:                                        .getDescriptorFor(rds.getItemClass());
0396:                                retrieveReferences(refObj, super Cld, false);
0397:                                retrieveCollections(refObj, super Cld, false);
0398:                            }
0399:                        } else if ((m_retrievalTasks != null) && !rds.isLazy()
0400:                                && (rds.getItemProxyClass() == null)) {
0401:                            addRetrievalTask(obj, rds);
0402:                            isRefObjDefined = false;
0403:                        } else {
0404:                            refObj = getReferencedObject(id, rds);
0405:                        }
0406:
0407:                        if (isRefObjDefined) {
0408:                            refField = rds.getPersistentField();
0409:                            refField.set(obj, refObj);
0410:
0411:                            if ((refObj != null) && prefetchProxies
0412:                                    && (m_retrievalTasks != null)
0413:                                    && (rds.getProxyPrefetchingLimit() > 0)) {
0414:                                IndirectionHandler handler = ProxyHelper
0415:                                        .getIndirectionHandler(refObj);
0416:
0417:                                if ((handler != null)
0418:                                        && addRetrievalTask(obj, rds)) {
0419:                                    new PBMaterializationListener(obj,
0420:                                            m_retrievalTasks, rds, rds
0421:                                                    .getProxyPrefetchingLimit());
0422:                                }
0423:                            }
0424:                        }
0425:
0426:                        pb.getInternalCache().disableMaterializationCache();
0427:                    } catch (RuntimeException e) {
0428:                        pb.getInternalCache().doLocalClear();
0429:                        throw e;
0430:                    }
0431:                }
0432:            }
0433:
0434:            /**
0435:             * Retrieve a single Reference.
0436:             * This implementation retrieves a referenced object from the data backend
0437:             * if <b>cascade-retrieve</b> is true or if <b>forced</b> is true.
0438:             *
0439:             * @param obj - object that will have it's field set with a referenced object.
0440:             * @param cld - the ClassDescriptor describring obj
0441:             * @param rds - the ObjectReferenceDescriptor of the reference attribute to be loaded
0442:             * @param forced - if set to true, the reference is loaded even if the rds differs.
0443:             */
0444:            public void retrieveProxyReference(Object obj, ClassDescriptor cld,
0445:                    ObjectReferenceDescriptor rds, boolean forced) {
0446:                PersistentField refField;
0447:                Object refObj = null;
0448:
0449:                pb.getInternalCache().enableMaterializationCache();
0450:                try {
0451:                    Identity id = getReferencedObjectIdentity(obj, rds, cld);
0452:                    if (id != null) {
0453:                        refObj = pb.createProxy(rds.getItemClass(), id);
0454:                    }
0455:                    refField = rds.getPersistentField();
0456:                    refField.set(obj, refObj);
0457:
0458:                    if ((refObj != null) && prefetchProxies
0459:                            && (m_retrievalTasks != null)
0460:                            && (rds.getProxyPrefetchingLimit() > 0)) {
0461:                        IndirectionHandler handler = ProxyHelper
0462:                                .getIndirectionHandler(refObj);
0463:
0464:                        if ((handler != null) && addRetrievalTask(obj, rds)) {
0465:                            new PBMaterializationListener(obj,
0466:                                    m_retrievalTasks, rds, rds
0467:                                            .getProxyPrefetchingLimit());
0468:                        }
0469:                    }
0470:
0471:                    pb.getInternalCache().disableMaterializationCache();
0472:                } catch (RuntimeException e) {
0473:                    pb.getInternalCache().doLocalClear();
0474:                    throw e;
0475:                }
0476:
0477:            }
0478:
0479:            /**
0480:             * Retrieve all References
0481:             *
0482:             * @param newObj the instance to be loaded or refreshed
0483:             * @param cld the ClassDescriptor of the instance
0484:             * @param forced if set to true loading is forced even if cld differs.
0485:             */
0486:            public void retrieveReferences(Object newObj, ClassDescriptor cld,
0487:                    boolean forced) throws PersistenceBrokerException {
0488:                Iterator i = cld.getObjectReferenceDescriptors().iterator();
0489:
0490:                // turn off auto prefetching for related proxies
0491:                final Class saveClassToPrefetch = classToPrefetch;
0492:                classToPrefetch = null;
0493:
0494:                pb.getInternalCache().enableMaterializationCache();
0495:                try {
0496:                    while (i.hasNext()) {
0497:                        ObjectReferenceDescriptor rds = (ObjectReferenceDescriptor) i
0498:                                .next();
0499:                        retrieveReference(newObj, cld, rds, forced);
0500:                    }
0501:
0502:                    pb.getInternalCache().disableMaterializationCache();
0503:                } catch (RuntimeException e) {
0504:                    pb.getInternalCache().doLocalClear();
0505:                    throw e;
0506:                } finally {
0507:                    classToPrefetch = saveClassToPrefetch;
0508:                }
0509:            }
0510:
0511:            /**
0512:             * Retrieve all References
0513:             *
0514:             * @param newObj the instance to be loaded or refreshed
0515:             * @param cld the ClassDescriptor of the instance
0516:             * @param forced if set to true loading is forced even if cld differs.
0517:             */
0518:            public void retrieveProxyReferences(Object newObj,
0519:                    ClassDescriptor cld, boolean forced)
0520:                    throws PersistenceBrokerException {
0521:                Iterator i = cld.getObjectReferenceDescriptors().iterator();
0522:
0523:                // turn off auto prefetching for related proxies
0524:                final Class saveClassToPrefetch = classToPrefetch;
0525:                classToPrefetch = null;
0526:
0527:                pb.getInternalCache().enableMaterializationCache();
0528:                try {
0529:                    while (i.hasNext()) {
0530:                        ObjectReferenceDescriptor rds = (ObjectReferenceDescriptor) i
0531:                                .next();
0532:                        retrieveProxyReference(newObj, cld, rds, forced);
0533:                    }
0534:
0535:                    pb.getInternalCache().disableMaterializationCache();
0536:                } catch (RuntimeException e) {
0537:                    pb.getInternalCache().doLocalClear();
0538:                    throw e;
0539:                } finally {
0540:                    classToPrefetch = saveClassToPrefetch;
0541:                }
0542:            }
0543:
0544:            /**
0545:             * retrieves an Object reference's Identity.
0546:             * <br>
0547:             * Null is returned if all foreign keys are null
0548:             */
0549:            private Identity getReferencedObjectIdentity(Object obj,
0550:                    ObjectReferenceDescriptor rds, ClassDescriptor cld) {
0551:                Object[] fkValues = rds.getForeignKeyValues(obj, cld);
0552:                FieldDescriptor[] fkFieldDescriptors = rds
0553:                        .getForeignKeyFieldDescriptors(cld);
0554:                boolean hasNullifiedFKValue = hasNullifiedFK(
0555:                        fkFieldDescriptors, fkValues);
0556:                /*
0557:                BRJ: if all fk values are null there's no referenced object
0558:
0559:                arminw: Supposed the given object has nullified FK values but the referenced
0560:                object still exists. This could happend after serialization of the main object. In
0561:                this case all anonymous field (AK) information is lost, because AnonymousPersistentField class
0562:                use the object identity to cache the AK values. But we can build Identity anyway from the reference
0563:                 */
0564:                if (hasNullifiedFKValue) {
0565:                    if (BrokerHelper.hasAnonymousKeyReference(cld, rds)) {
0566:                        Object referencedObject = rds.getPersistentField().get(
0567:                                obj);
0568:                        if (referencedObject != null) {
0569:                            return pb.serviceIdentity().buildIdentity(
0570:                                    referencedObject);
0571:                        }
0572:                    }
0573:                } else {
0574:                    // ensure that top-level extents are used for Identities
0575:                    return pb.serviceIdentity().buildIdentity(
0576:                            rds.getItemClass(),
0577:                            pb.getTopLevelClass(rds.getItemClass()), fkValues);
0578:                }
0579:                return null;
0580:            }
0581:
0582:            // BRJ: check if we have non null fk values
0583:            // TBD  we should also check primitives
0584:            // to avoid creation of unmaterializable proxies
0585:            private boolean hasNullifiedFK(
0586:                    FieldDescriptor[] fkFieldDescriptors, Object[] fkValues) {
0587:                boolean result = true;
0588:                for (int i = 0; i < fkValues.length; i++) {
0589:                    if (!pb.serviceBrokerHelper().representsNull(
0590:                            fkFieldDescriptors[i], fkValues[i])) {
0591:                        result = false;
0592:                        break;
0593:                    }
0594:                }
0595:                return result;
0596:            }
0597:
0598:            /**
0599:             * retrieves an Object reference by its Identity.
0600:             * <br>
0601:             * If there is a Proxy-class is defined in the ReferenceDescriptor or
0602:             * if the ReferenceDescriptor is lazy, a Proxy-object is returned.
0603:             * <br>
0604:             * If no Proxy-class is defined, a getObjectByIdentity(...) lookup is performed.
0605:             */
0606:            private Object getReferencedObject(Identity id,
0607:                    ObjectReferenceDescriptor rds) {
0608:                Class baseClassForProxy;
0609:
0610:                if (rds.isLazy()) {
0611:                    /*
0612:                    arminw:
0613:                    use real reference class instead of the top-level class,
0614:                    because we want to use a proxy representing the real class
0615:                    not only the top-level class - right?
0616:                     */
0617:                    // referencedProxy = getClassDescriptor(referencedClass).getDynamicProxyClass();
0618:                    //referencedProxy = rds.getItemClass(); 
0619:                    /*
0620:                     * andrew.clute:
0621:                     * With proxy generation now handled by the ProxyFactory implementations, the class of the Item
0622:                     * is now the nessecary parameter to generate a proxy.
0623:                     */
0624:                    baseClassForProxy = rds.getItemClass();
0625:                } else {
0626:                    /*
0627:                     * andrew.clute:
0628:                     * If the descriptor does not mark it as lazy, then the class for the proxy must be of type VirtualProxy
0629:                     */
0630:                    baseClassForProxy = rds.getItemProxyClass();
0631:                }
0632:
0633:                if (baseClassForProxy != null) {
0634:                    try {
0635:                        return pb.createProxy(baseClassForProxy, id);
0636:                    } catch (Exception e) {
0637:                        log.error("Error while instantiate object " + id
0638:                                + ", msg: " + e.getMessage(), e);
0639:                        if (e instanceof  PersistenceBrokerException) {
0640:                            throw (PersistenceBrokerException) e;
0641:                        } else {
0642:                            throw new PersistenceBrokerException(e);
0643:                        }
0644:                    }
0645:                } else {
0646:                    return pb.doGetObjectByIdentity(id);
0647:                }
0648:            }
0649:
0650:            /**
0651:             * Retrieve a single Collection on behalf of <b>obj</b>.
0652:             * The Collection is retrieved only if <b>cascade.retrieve is true</b>
0653:             * or if <b>forced</b> is set to true.     *
0654:             *
0655:             * @param obj - the object to be updated
0656:             * @param cld - the ClassDescriptor describing obj
0657:             * @param cds - the CollectionDescriptor describing the collection attribute to be loaded
0658:             * @param forced - if set to true loading is forced, even if cds differs.
0659:             *
0660:             */
0661:            public void retrieveCollection(Object obj, ClassDescriptor cld,
0662:                    CollectionDescriptor cds, boolean forced) {
0663:                doRetrieveCollection(obj, cld, cds, forced, cds.isLazy());
0664:            }
0665:
0666:            /**
0667:             * Retrieve a single Proxied Collection on behalf of <b>obj</b>.
0668:             * The Collection is retrieved only if <b>cascade.retrieve is true</b>
0669:             * or if <b>forced</b> is set to true.     *
0670:             *
0671:             * @param obj - the object to be updated
0672:             * @param cld - the ClassDescriptor describing obj
0673:             * @param cds - the CollectionDescriptor describing the collection attribute to be loaded
0674:             * @param forced - if set to true a proxy will be placed, even if cds differs.
0675:             *
0676:             */
0677:            public void retrieveProxyCollection(Object obj,
0678:                    ClassDescriptor cld, CollectionDescriptor cds,
0679:                    boolean forced) {
0680:                doRetrieveCollection(obj, cld, cds, forced, true);
0681:            }
0682:
0683:            private void doRetrieveCollection(Object obj, ClassDescriptor cld,
0684:                    CollectionDescriptor cds, boolean forced, boolean lazyLoad) {
0685:                if (forced || cds.getCascadeRetrieve()) {
0686:                    if ((m_retrievalTasks != null) && !cds.isLazy()
0687:                            && !cds.hasProxyItems()
0688:                            && (cds.getQueryCustomizer() == null)) {
0689:                        addRetrievalTask(obj, cds);
0690:                    } else {
0691:                        // this collection type will be used:
0692:                        Class collectionClass = cds.getCollectionClass();
0693:                        PersistentField collectionField = cds
0694:                                .getPersistentField();
0695:                        Query fkQuery = getFKQuery(obj, cld, cds);
0696:                        Object value;
0697:
0698:                        pb.getInternalCache().enableMaterializationCache();
0699:                        try {
0700:                            if (collectionClass == null) {
0701:                                Collection result = (Collection) getCollectionByQuery(
0702:                                        getCollectionTypeClass(cds), fkQuery,
0703:                                        lazyLoad);
0704:
0705:                                // assign collection to objects attribute
0706:                                // if attribute has an array type build an array, else assign collection directly
0707:                                if (collectionField.getType().isArray()) {
0708:                                    int length = result.size();
0709:                                    Class itemtype = collectionField.getType()
0710:                                            .getComponentType();
0711:                                    Object resultArray = Array.newInstance(
0712:                                            itemtype, length);
0713:                                    int j = 0;
0714:                                    for (Iterator iter = result.iterator(); iter
0715:                                            .hasNext(); j++) {
0716:                                        Array.set(resultArray, j, iter.next());
0717:                                    }
0718:                                    collectionField.set(obj, resultArray);
0719:                                } else {
0720:                                    collectionField.set(obj, result);
0721:                                }
0722:                                value = result;
0723:                            } else {
0724:                                ManageableCollection result = getCollectionByQuery(
0725:                                        collectionClass, fkQuery, lazyLoad);
0726:                                collectionField.set(obj, result);
0727:                                value = result;
0728:                            }
0729:
0730:                            if (prefetchProxies && (m_retrievalTasks != null)
0731:                                    && (cds.getProxyPrefetchingLimit() > 0)
0732:                                    && (cds.getQueryCustomizer() == null)
0733:                                    && (ProxyHelper.isCollectionProxy(value))) {
0734:                                if (addRetrievalTask(obj, cds)) {
0735:                                    new PBCollectionProxyListener(obj,
0736:                                            m_retrievalTasks, cds, cds
0737:                                                    .getProxyPrefetchingLimit());
0738:                                }
0739:                            }
0740:
0741:                            pb.getInternalCache().disableMaterializationCache();
0742:                        } catch (RuntimeException e) {
0743:                            pb.getInternalCache().doLocalClear();
0744:                            throw e;
0745:                        }
0746:                    }
0747:                }
0748:            }
0749:
0750:            /**
0751:             * Answer the foreign key query to retrieve the collection
0752:             * defined by CollectionDescriptor
0753:             */
0754:            private Query getFKQuery(Object obj, ClassDescriptor cld,
0755:                    CollectionDescriptor cds) {
0756:                Query fkQuery;
0757:                QueryByCriteria fkQueryCrit;
0758:
0759:                if (cds.isMtoNRelation()) {
0760:                    fkQueryCrit = getFKQueryMtoN(obj, cld, cds);
0761:                } else {
0762:                    fkQueryCrit = getFKQuery1toN(obj, cld, cds);
0763:                }
0764:
0765:                // check if collection must be ordered
0766:                if (!cds.getOrderBy().isEmpty()) {
0767:                    Iterator iter = cds.getOrderBy().iterator();
0768:                    while (iter.hasNext()) {
0769:                        fkQueryCrit.addOrderBy((FieldHelper) iter.next());
0770:                    }
0771:                }
0772:
0773:                // BRJ: customize the query
0774:                if (cds.getQueryCustomizer() != null) {
0775:                    fkQuery = cds.getQueryCustomizer().customizeQuery(obj, pb,
0776:                            cds, fkQueryCrit);
0777:                } else {
0778:                    fkQuery = fkQueryCrit;
0779:                }
0780:
0781:                return fkQuery;
0782:            }
0783:
0784:            /**
0785:             * Get Foreign key query for m:n <br>
0786:             * supports UNIDIRECTIONAL m:n using QueryByMtoNCriteria
0787:             * @return org.apache.ojb.broker.query.QueryByCriteria
0788:             * @param obj the owner of the relationship
0789:             * @param cld the ClassDescriptor for the owner
0790:             * @param cod the CollectionDescriptor
0791:             */
0792:            private QueryByCriteria getFKQueryMtoN(Object obj,
0793:                    ClassDescriptor cld, CollectionDescriptor cod) {
0794:                ValueContainer[] values = pb.serviceBrokerHelper()
0795:                        .getKeyValues(cld, obj);
0796:                Object[] this ClassFks = cod.getFksToThisClass();
0797:                Object[] itemClassFks = cod.getFksToItemClass();
0798:                ClassDescriptor refCld = pb.getClassDescriptor(cod
0799:                        .getItemClass());
0800:                Criteria criteria = new Criteria();
0801:
0802:                for (int i = 0; i < this ClassFks.length; i++) {
0803:                    criteria.addEqualTo(cod.getIndirectionTable() + "."
0804:                            + this ClassFks[i], values[i].getValue());
0805:                }
0806:                for (int i = 0; i < itemClassFks.length; i++) {
0807:                    criteria.addEqualToField(cod.getIndirectionTable() + "."
0808:                            + itemClassFks[i], refCld.getPkFields()[i]
0809:                            .getAttributeName());
0810:                }
0811:
0812:                return QueryFactory.newQuery(refCld.getClassOfObject(), cod
0813:                        .getIndirectionTable(), criteria);
0814:            }
0815:
0816:            /**
0817:             * Get Foreign key query for 1:n
0818:             * @return org.apache.ojb.broker.query.QueryByCriteria
0819:             * @param obj
0820:             * @param cld
0821:             * @param cod
0822:             */
0823:            private QueryByCriteria getFKQuery1toN(Object obj,
0824:                    ClassDescriptor cld, CollectionDescriptor cod) {
0825:                ValueContainer[] container = pb.serviceBrokerHelper()
0826:                        .getKeyValues(cld, obj);
0827:                ClassDescriptor refCld = pb.getClassDescriptor(cod
0828:                        .getItemClass());
0829:                FieldDescriptor[] fields = cod
0830:                        .getForeignKeyFieldDescriptors(refCld);
0831:                Criteria criteria = new Criteria();
0832:
0833:                for (int i = 0; i < fields.length; i++) {
0834:                    FieldDescriptor fld = fields[i];
0835:                    criteria.addEqualTo(fld.getAttributeName(), container[i]
0836:                            .getValue());
0837:                }
0838:
0839:                return QueryFactory.newQuery(refCld.getClassOfObject(),
0840:                        criteria);
0841:            }
0842:
0843:            /**
0844:             * Answer the primary key query to retrieve an Object
0845:             *
0846:             * @param oid the Identity of the Object to retrieve
0847:             * @return The resulting query
0848:             */
0849:            public Query getPKQuery(Identity oid) {
0850:                Object[] values = oid.getPrimaryKeyValues();
0851:                ClassDescriptor cld = pb.getClassDescriptor(oid
0852:                        .getObjectsTopLevelClass());
0853:                FieldDescriptor[] fields = cld.getPkFields();
0854:                Criteria criteria = new Criteria();
0855:
0856:                for (int i = 0; i < fields.length; i++) {
0857:                    FieldDescriptor fld = fields[i];
0858:                    criteria.addEqualTo(fld.getAttributeName(), values[i]);
0859:                }
0860:                return QueryFactory.newQuery(cld.getClassOfObject(), criteria);
0861:            }
0862:
0863:            /**
0864:             * Retrieve all Collection attributes of a given instance
0865:             *
0866:             * @param newObj the instance to be loaded or refreshed
0867:             * @param cld the ClassDescriptor of the instance
0868:             * @param forced if set to true, loading is forced even if cld differs
0869:             *
0870:             */
0871:            public void retrieveCollections(Object newObj, ClassDescriptor cld,
0872:                    boolean forced) throws PersistenceBrokerException {
0873:                doRetrieveCollections(newObj, cld, forced, false);
0874:            }
0875:
0876:            /**
0877:             * Retrieve all Collection attributes of a given instance, and make all of the Proxy Collections
0878:             *
0879:             * @param newObj the instance to be loaded or refreshed
0880:             * @param cld the ClassDescriptor of the instance
0881:             * @param forced if set to true, loading is forced even if cld differs
0882:             *
0883:             */
0884:            public void retrieveProxyCollections(Object newObj,
0885:                    ClassDescriptor cld, boolean forced)
0886:                    throws PersistenceBrokerException {
0887:                doRetrieveCollections(newObj, cld, forced, true);
0888:            }
0889:
0890:            private void doRetrieveCollections(Object newObj,
0891:                    ClassDescriptor cld, boolean forced,
0892:                    boolean forceProxyCollection)
0893:                    throws PersistenceBrokerException {
0894:                Iterator i = cld.getCollectionDescriptors().iterator();
0895:
0896:                // turn off auto prefetching for related proxies
0897:                final Class saveClassToPrefetch = classToPrefetch;
0898:                classToPrefetch = null;
0899:
0900:                pb.getInternalCache().enableMaterializationCache();
0901:                try {
0902:                    while (i.hasNext()) {
0903:                        CollectionDescriptor cds = (CollectionDescriptor) i
0904:                                .next();
0905:                        if (forceProxyCollection) {
0906:                            retrieveProxyCollection(newObj, cld, cds, forced);
0907:                        } else {
0908:                            retrieveCollection(newObj, cld, cds, forced);
0909:                        }
0910:                    }
0911:                    pb.getInternalCache().disableMaterializationCache();
0912:                } catch (RuntimeException e) {
0913:                    pb.getInternalCache().doLocalClear();
0914:                    throw e;
0915:                } finally {
0916:                    classToPrefetch = saveClassToPrefetch;
0917:                }
0918:            }
0919:
0920:            /**
0921:             * remove all prefetching listeners
0922:             */
0923:            public void removePrefetchingListeners() {
0924:                if (prefetchingListeners != null) {
0925:                    for (Iterator it = prefetchingListeners.iterator(); it
0926:                            .hasNext();) {
0927:                        PBPrefetchingListener listener = (PBPrefetchingListener) it
0928:                                .next();
0929:                        listener.removeThisListener();
0930:                    }
0931:                    prefetchingListeners.clear();
0932:                }
0933:            }
0934:
0935:            public Class getClassToPrefetch() {
0936:                return classToPrefetch;
0937:            }
0938:
0939:            //**********************************************************************
0940:            // inner classes
0941:            //**********************************************************************
0942:
0943:            class PBMaterializationListener extends PBPrefetchingListener
0944:                    implements  MaterializationListener {
0945:                private IndirectionHandler _listenedHandler;
0946:
0947:                PBMaterializationListener(Object owner, HashMap retrievalTasks,
0948:                        Object key, int limit) {
0949:                    super (owner, retrievalTasks, key, limit);
0950:                }
0951:
0952:                protected void addThisListenerTo(Object owner) {
0953:                    _listenedHandler = ProxyHelper.getIndirectionHandler(owner);
0954:
0955:                    if (_listenedHandler != null) {
0956:                        _listenedHandler.addListener(this );
0957:                    }
0958:                }
0959:
0960:                protected void removeThisListener() {
0961:                    if (_listenedHandler != null) {
0962:                        _listenedHandler.removeListener(this );
0963:                        _listenedHandler = null;
0964:                    }
0965:                }
0966:
0967:                protected RelationshipPrefetcher getPrefetcher(
0968:                        Object listenedObject) {
0969:                    if (_key instanceof  ObjectReferenceDescriptor) {
0970:                        return pb.getRelationshipPrefetcherFactory()
0971:                                .createRelationshipPrefetcher(
0972:                                        (ObjectReferenceDescriptor) _key);
0973:                    } else // PersistentBrokerImpl.this
0974:                    {
0975:                        // a special case: current collection being loaded contains proxies,
0976:                        // just load them without setting any fields
0977:                        IndirectionHandler handler = (IndirectionHandler) listenedObject;
0978:                        return new PlainPrefetcher(pb, handler.getIdentity()
0979:                                .getObjectsTopLevelClass());
0980:                    }
0981:                }
0982:
0983:                public void beforeMaterialization(IndirectionHandler handler,
0984:                        Identity oid) {
0985:                    prefetch(handler);
0986:                }
0987:
0988:                public void afterMaterialization(IndirectionHandler handler,
0989:                        Object materializedObject) {
0990:                    //do nothing            
0991:                }
0992:            }
0993:
0994:            abstract class PBPrefetchingListener {
0995:                private HashMap _retrievalTasks;
0996:                private int _limit;
0997:                protected Object _key;
0998:
0999:                PBPrefetchingListener(Object owner, HashMap retrievalTasks,
1000:                        Object key, int limit) {
1001:                    _retrievalTasks = retrievalTasks;
1002:                    _key = key;
1003:                    _limit = limit + 1; // lestenedObject + next limit objects
1004:                    if (prefetchingListeners == null) {
1005:                        prefetchingListeners = new ArrayList();
1006:                    }
1007:                    addThisListenerTo(owner);
1008:                    prefetchingListeners.add(this );
1009:                }
1010:
1011:                abstract protected void addThisListenerTo(Object owner);
1012:
1013:                abstract protected void removeThisListener();
1014:
1015:                abstract protected RelationshipPrefetcher getPrefetcher(
1016:                        Object listenedObject);
1017:
1018:                protected void prefetch(Object listenedObject) {
1019:                    ArrayList owners = (ArrayList) _retrievalTasks.get(_key);
1020:                    List toPrefetch;
1021:                    RelationshipPrefetcher prefetcher;
1022:                    boolean prefetchingAll;
1023:
1024:                    removeThisListener();
1025:
1026:                    if (owners == null) {
1027:                        return;
1028:                    }
1029:
1030:                    prefetcher = getPrefetcher(listenedObject);
1031:
1032:                    if (owners.size() <= _limit) {
1033:                        toPrefetch = owners;
1034:                        prefetchingAll = true;
1035:                    } else {
1036:                        toPrefetch = owners.subList(0, _limit);
1037:                        prefetchingAll = false;
1038:                    }
1039:
1040:                    final Class saveClassToPrefetch = classToPrefetch;
1041:                    classToPrefetch = prefetcher.getItemClassDescriptor()
1042:                            .getClassOfObject();
1043:                    try {
1044:                        prefetcher.prefetchRelationship(toPrefetch);
1045:                    } finally {
1046:                        classToPrefetch = saveClassToPrefetch;
1047:                    }
1048:
1049:                    if (prefetchingAll) {
1050:                        _retrievalTasks.remove(_key);
1051:                    } else {
1052:                        // ArrayList documented trick:
1053:                        // "the following idiom removes a range of elements from a list:
1054:                        // list.subList(from, to).clear();
1055:                        toPrefetch.clear();
1056:                        addThisListenerTo(owners.get(0));
1057:                    }
1058:                }
1059:            }
1060:
1061:            class PBCollectionProxyListener extends PBPrefetchingListener
1062:                    implements  CollectionProxyListener {
1063:                CollectionProxyDefaultImpl _listenedCollection;
1064:
1065:                PBCollectionProxyListener(Object owner, HashMap retrievalTasks,
1066:                        CollectionDescriptor key, int limit) {
1067:                    super (owner, retrievalTasks, key, limit);
1068:                }
1069:
1070:                protected void addThisListenerTo(Object owner) {
1071:                    PersistentField collectionField = ((CollectionDescriptor) _key)
1072:                            .getPersistentField();
1073:                    _listenedCollection = (CollectionProxyDefaultImpl) collectionField
1074:                            .get(owner);
1075:                    _listenedCollection.addListener(this );
1076:                }
1077:
1078:                protected void removeThisListener() {
1079:                    if (_listenedCollection != null) {
1080:                        _listenedCollection.removeListener(this );
1081:                        _listenedCollection = null;
1082:                    }
1083:                }
1084:
1085:                protected RelationshipPrefetcher getPrefetcher(
1086:                        Object listenedObject) {
1087:                    return pb.getRelationshipPrefetcherFactory()
1088:                            .createRelationshipPrefetcher(
1089:                                    (CollectionDescriptor) _key);
1090:                }
1091:
1092:                public void beforeLoading(CollectionProxyDefaultImpl col) {
1093:                    prefetch(col);
1094:                }
1095:
1096:                public void afterLoading(CollectionProxyDefaultImpl col) {
1097:                    //do nothing
1098:                }
1099:            }
1100:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.