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


001:        package org.apache.ojb.odmg;
002:
003:        /* Copyright 2002-2005 The Apache Software Foundation
004:         *
005:         * Licensed under the Apache License, Version 2.0 (the "License");
006:         * you may not use this file except in compliance with the License.
007:         * You may obtain a copy of the License at
008:         *
009:         *     http://www.apache.org/licenses/LICENSE-2.0
010:         *
011:         * Unless required by applicable law or agreed to in writing, software
012:         * distributed under the License is distributed on an "AS IS" BASIS,
013:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014:         * See the License for the specific language governing permissions and
015:         * limitations under the License.
016:         */
017:        /**
018:         *
019:         * @author <a href="mailto:thma@apache.org">Thomas Mahler</a>
020:         * @author <a href="mailto:mattbaird@yahoo.com">Matthew Baird</a>
021:         *
022:         */
023:
024:        import java.util.HashMap;
025:        import java.util.Iterator;
026:        import java.util.Map;
027:        import java.util.List;
028:        import java.util.ArrayList;
029:
030:        import org.apache.commons.lang.builder.ToStringBuilder;
031:        import org.apache.ojb.broker.Identity;
032:        import org.apache.ojb.broker.PersistenceBroker;
033:        import org.apache.ojb.broker.PersistenceBrokerException;
034:        import org.apache.ojb.broker.OJBRuntimeException;
035:        import org.apache.ojb.broker.PersistenceBrokerInternal;
036:        import org.apache.ojb.broker.core.proxy.IndirectionHandler;
037:        import org.apache.ojb.broker.core.proxy.ProxyHelper;
038:        import org.apache.ojb.broker.metadata.ClassDescriptor;
039:        import org.apache.ojb.broker.metadata.CollectionDescriptor;
040:        import org.apache.ojb.broker.metadata.FieldDescriptor;
041:        import org.apache.ojb.broker.metadata.ObjectReferenceDescriptor;
042:        import org.apache.ojb.broker.util.BrokerHelper;
043:        import org.apache.ojb.broker.util.ObjectModification;
044:        import org.apache.ojb.broker.util.logging.Logger;
045:        import org.apache.ojb.broker.util.logging.LoggerFactory;
046:        import org.apache.ojb.odmg.states.ModificationState;
047:        import org.apache.ojb.odmg.states.StateNewDirty;
048:        import org.apache.ojb.odmg.states.StateOldClean;
049:        import org.apache.ojb.odmg.states.StateOldDirty;
050:        import org.apache.ojb.odmg.link.LinkEntry;
051:        import org.apache.ojb.odmg.link.LinkEntryOneToOne;
052:        import org.apache.ojb.odmg.link.LinkEntryOneToN;
053:
054:        /**
055:         * ObjectEnvelope is used during ODMG transactions as a wrapper for a
056:         * persistent objects declaration
057:         *
058:         */
059:        public class ObjectEnvelope implements  ObjectModification,
060:                Image.ImageListener {
061:            private Logger log = LoggerFactory.getLogger(ObjectEnvelope.class);
062:
063:            static final long serialVersionUID = -829177767933340522L;
064:
065:            static final int IS_MATERIALIZED_OBJECT = 11;
066:            static final int IS_MATERIALIZED_PROXY = 13;
067:            static final int IS_UNMATERIALIZED_PROXY = 17;
068:
069:            /**
070:             * The objects modification state, e.g. Old and Clean
071:             */
072:            private ModificationState modificationState = null;
073:            private Identity oid;
074:            private Boolean hasChanged;
075:            private boolean writeLocked;
076:
077:            /**
078:             * myObj holds the object we are wrapping.
079:             */
080:            private Object myObj;
081:
082:            /**
083:             * beforeImage holds a mapping between field
084:             * names and values at the start of the transaction.
085:             * currentImage holds the mapping at the
086:             * end of the transaction.
087:             */
088:            private Map beforeImage;
089:            private Map currentImage;
090:            private ObjectEnvelopeTable buffer;
091:            // list of all LinkEntry's
092:            private List linkEntryList;
093:
094:            /**
095:             * Create a wrapper by providing an Object.
096:             */
097:            public ObjectEnvelope(ObjectEnvelopeTable buffer, Identity oid,
098:                    Object obj, boolean isNewObject) {
099:                this .linkEntryList = new ArrayList();
100:                this .buffer = buffer;
101:                this .oid = oid;
102:                // TODO: do we really need to materialize??
103:                myObj = ProxyHelper.getRealObject(obj);
104:                prepareInitialState(isNewObject);
105:                /*
106:                TODO: is it possible to improve this? Take care that "new"
107:                objects should support "persistence by reachability" too
108:                (detection of new/persistent reference objects after maon object lock)
109:                 */
110:                beforeImage = buildObjectImage(getBroker());
111:            }
112:
113:            public PersistenceBrokerInternal getBroker() {
114:                return buffer.getTransaction().getBrokerInternal();
115:            }
116:
117:            TransactionImpl getTx() {
118:                return buffer.getTransaction();
119:            }
120:
121:            ObjectEnvelopeTable getEnvelopeTable() {
122:                return buffer;
123:            }
124:
125:            public Map getBeforeImage() {
126:                if (beforeImage == null) {
127:                    beforeImage = buildObjectImage(getBroker());
128:                }
129:                return beforeImage;
130:            }
131:
132:            public Map getCurrentImage() {
133:                if (currentImage == null) {
134:                    currentImage = buildObjectImage(getBroker());
135:                }
136:                return currentImage;
137:            }
138:
139:            /**
140:             * This method should be called before transaction ends
141:             * to allow cleanup of used resources, e.g. remove proxy listener objects
142:             * to avoid invoke of registered objects after tx end.
143:             */
144:            public void cleanup(boolean reuse, boolean wasInsert) {
145:                if (currentImage != null) {
146:                    performImageCleanup(currentImage, reuse);
147:                }
148:                if (beforeImage != null) {
149:                    // we always free all resources of the old image
150:                    performImageCleanup(beforeImage, false);
151:                }
152:                if (reuse) {
153:                    refreshObjectImage(wasInsert);
154:                } else {
155:                    myObj = null;
156:                }
157:            }
158:
159:            private void performImageCleanup(Map imageMap, boolean reuse) {
160:                Iterator iterator = imageMap.values().iterator();
161:                while (iterator.hasNext()) {
162:                    Image base = (Image) iterator.next();
163:                    if (base != null)
164:                        base.cleanup(reuse);
165:                }
166:            }
167:
168:            private void refreshObjectImage(boolean wasInsert) {
169:                try {
170:                    // if an image already exists we
171:                    // replace the Identity too, maybe a temporary
172:                    // used PK value was replaced by the real one,
173:                    // see in docs SequenceManagerNativeImpl
174:                    if (getIdentity().isTransient()) {
175:                        refreshIdentity();
176:                    }
177:                    if (currentImage != null) {
178:                        beforeImage = currentImage;
179:                    } else {
180:                        if (beforeImage == null) {
181:                            beforeImage = buildObjectImage(getBroker());
182:                        }
183:                    }
184:                    currentImage = null;
185:                    hasChanged = null;
186:                    if (wasInsert) {
187:                        /*
188:                        on insert we have to replace the PK fields and the version fields, because
189:                        they populated after the object was written to DB, thus replace all field image values
190:                         */
191:                        refreshPKFields();
192:                    }
193:                    // TODO: How to handle version fields incremented by the DB?
194:                    // always refresh the version fields, because these fields will change when written to DB
195:                    refreshLockingFields();
196:                } catch (PersistenceBrokerException e) {
197:                    beforeImage = null;
198:                    currentImage = null;
199:                    hasChanged = null;
200:                    log.error(
201:                            "Can't refresh object image for " + getIdentity(),
202:                            e);
203:                    throw e;
204:                }
205:            }
206:
207:            private void refreshPKFields() {
208:                FieldDescriptor[] flds = getClassDescriptor().getPkFields();
209:                for (int i = 0; i < flds.length; i++) {
210:                    FieldDescriptor fld = flds[i];
211:                    addFieldImage(beforeImage, fld);
212:                }
213:            }
214:
215:            private void refreshLockingFields() {
216:                if (getClassDescriptor().isLocking()) {
217:                    FieldDescriptor[] flds = getClassDescriptor()
218:                            .getLockingFields();
219:                    for (int i = 0; i < flds.length; i++) {
220:                        FieldDescriptor fld = flds[i];
221:                        addFieldImage(beforeImage, fld);
222:                    }
223:                }
224:            }
225:
226:            /**
227:             * Replace the current with a new generated identity object and
228:             * returns the old one.
229:             */
230:            public Identity refreshIdentity() {
231:                Identity oldOid = getIdentity();
232:                this .oid = getBroker().serviceIdentity().buildIdentity(myObj);
233:                return oldOid;
234:            }
235:
236:            public Identity getIdentity() {
237:                if (oid == null) {
238:                    oid = getBroker().serviceIdentity().buildIdentity(
239:                            getObject());
240:                }
241:                return oid;
242:            }
243:
244:            /**
245:             * Returns the managed materialized object.
246:             */
247:            public Object getObject() {
248:                return myObj;
249:            }
250:
251:            public Object getRealObject() {
252:                return ProxyHelper.getRealObject(getObject());
253:            }
254:
255:            public void refreshObjectIfNeeded(Object obj) {
256:                if (this .myObj != obj) {
257:                    this .myObj = obj;
258:                }
259:            }
260:
261:            /**
262:             * We need to implement the Two-Phase Commit
263:             * protocol.
264:             *
265:             * beginCommit is where we say if we can or cannot
266:             * commit the transaction.  At the begining however,
267:             * we need to attain the after image so we can isolate
268:             * everything.
269:             *
270:             * We should issue the call against the database
271:             * at this point.  If we get a SQL Exception, we
272:             * should throw the org.odmg.TransactionAbortedException.
273:             *
274:             * We should also check to see if the object is
275:             * TransactionAware.  If so, we should give it a chance
276:             * to kill the transaction before we toss it to the
277:             * database.
278:             */
279:            public void beforeCommit() {
280:                if (myObj instanceof  TransactionAware) {
281:                    TransactionAware ta = (TransactionAware) myObj;
282:                    ta.beforeCommit();
283:                }
284:            }
285:
286:            /**
287:             * Method declaration
288:             */
289:            public void afterCommit() {
290:                if (myObj instanceof  TransactionAware) {
291:                    TransactionAware ta = (TransactionAware) myObj;
292:                    ta.afterCommit();
293:                }
294:            }
295:
296:            /**
297:             * Method declaration
298:             */
299:            public void beforeAbort() {
300:                if (myObj instanceof  TransactionAware) {
301:                    TransactionAware ta = (TransactionAware) myObj;
302:                    ta.beforeAbort();
303:                }
304:            }
305:
306:            /**
307:             * Method declaration
308:             */
309:            public void afterAbort() {
310:                if (myObj instanceof  TransactionAware) {
311:                    TransactionAware ta = (TransactionAware) myObj;
312:                    ta.afterAbort();
313:                }
314:            }
315:
316:            /**
317:             * buildObjectImage() will return the image of the Object.
318:             */
319:            private Map buildObjectImage(PersistenceBroker broker)
320:                    throws PersistenceBrokerException {
321:                Map imageMap = new HashMap();
322:                ClassDescriptor cld = broker.getClassDescriptor(getObject()
323:                        .getClass());
324:                //System.out.println("++++ build image: " + getObject());
325:                // register 1:1 references in image
326:                buildImageForSingleReferences(imageMap, cld);
327:                // put object values to image map
328:                buildImageForFields(imageMap, cld);
329:                // register 1:n and m:n references in image
330:                buildImageForCollectionReferences(imageMap, cld);
331:                return imageMap;
332:            }
333:
334:            private void buildImageForSingleReferences(Map imageMap,
335:                    ClassDescriptor cld) {
336:                // register all 1:1 references
337:                Iterator iter = cld.getObjectReferenceDescriptors(true)
338:                        .iterator();
339:                ObjectReferenceDescriptor rds;
340:                while (iter.hasNext()) {
341:                    rds = (ObjectReferenceDescriptor) iter.next();
342:                    /*
343:                    arminw:
344:                    if a "super-reference" is matched (a 1:1 reference used to represent a super class)
345:                    we don't handle it, because this will be done by the PB-api and will never be change
346:                     */
347:                    if (!rds.isSuperReferenceDescriptor()) {
348:                        Object referenceObject = rds.getPersistentField().get(
349:                                myObj);
350:
351:                        IndirectionHandler handler = ProxyHelper
352:                                .getIndirectionHandler(referenceObject);
353:                        /*
354:                        arminw:
355:                        if object was serialized and anonymous FK are used in the main object, the FK
356:                        values are null, we have to refresh (re-assign) these values before building field images.
357:                        This will not touch the main object itself, because we only reassign anonymous FK fields.
358:                         */
359:                        if (handler == null
360:                                && referenceObject != null
361:                                && BrokerHelper.hasAnonymousKeyReference(rds
362:                                        .getClassDescriptor(), rds)) {
363:                            getBroker().serviceBrokerHelper().link(myObj, rds,
364:                                    false);
365:                        }
366:                        Image.SingleRef singleRef = new Image.SingleRef(this ,
367:                                rds, referenceObject);
368:                        imageMap.put(rds, singleRef);
369:                    }
370:                }
371:            }
372:
373:            private void buildImageForFields(Map imageMap, ClassDescriptor cld) {
374:                // register all non reference fields of object (with inherited fields)
375:                FieldDescriptor[] fieldDescs = cld.getFieldDescriptor(true);
376:                for (int i = 0; i < fieldDescs.length; i++) {
377:                    addFieldImage(imageMap, fieldDescs[i]);
378:                }
379:            }
380:
381:            private void addFieldImage(Map imageMap, FieldDescriptor fld) {
382:                // register copies of all field values
383:                Object value = fld.getPersistentField().get(myObj);
384:                // get the real sql type value
385:                value = fld.getFieldConversion().javaToSql(value);
386:                // make copy of the sql type value
387:                value = fld.getJdbcType().getFieldType().copy(value);
388:                // buffer in image the field name and the sql type value
389:                // wrapped by a helper class
390:                imageMap
391:                        .put(fld.getPersistentField().getName(),
392:                                new Image.Field(fld.getJdbcType()
393:                                        .getFieldType(), value));
394:            }
395:
396:            private void buildImageForCollectionReferences(Map imageMap,
397:                    ClassDescriptor cld) {
398:                // register the 1:n and m:n references
399:                Iterator collections = cld.getCollectionDescriptors(true)
400:                        .iterator();
401:                CollectionDescriptor cds;
402:                while (collections.hasNext()) {
403:                    cds = (CollectionDescriptor) collections.next();
404:                    Object collectionOrArray = cds.getPersistentField().get(
405:                            myObj);
406:                    Image.MultipleRef colRef = new Image.MultipleRef(this , cds,
407:                            collectionOrArray);
408:                    imageMap.put(cds, colRef);
409:                }
410:            }
411:
412:            /**
413:             * Returns the Modification-state.
414:             * @return org.apache.ojb.server.states.ModificationState
415:             */
416:            public ModificationState getModificationState() {
417:                return modificationState;
418:            }
419:
420:            /**
421:             * Returns true if the underlying Object needs an INSERT statement, else returns false.
422:             */
423:            public boolean needsInsert() {
424:                return this .getModificationState().needsInsert();
425:            }
426:
427:            /**
428:             * Returns true if the underlying Object needs an UPDATE statement, else returns false.
429:             */
430:            public boolean needsUpdate() {
431:                return this .getModificationState().needsUpdate();
432:            }
433:
434:            /**
435:             * Returns true if the underlying Object needs an UPDATE statement, else returns false.
436:             */
437:            public boolean needsDelete() {
438:                return this .getModificationState().needsDelete();
439:            }
440:
441:            /**
442:             * Sets the initial MoificationState of the wrapped object myObj. The initial state will be StateNewDirty if myObj
443:             * is not persisten already. The state will be set to StateOldClean if the object is already persistent.
444:             */
445:            private void prepareInitialState(boolean isNewObject) {
446:                // determine appropriate modification state
447:                ModificationState initialState;
448:                if (isNewObject) {
449:                    // if object is not already persistent it must be marked as new
450:                    // it must be marked as dirty because it must be stored even if it will not modified during tx
451:                    initialState = StateNewDirty.getInstance();
452:                } else if (isDeleted(oid)) {
453:                    // if object is already persistent it will be marked as old.
454:                    // it is marked as dirty as it has been deleted during tx and now it is inserted again,
455:                    // possibly with new field values.
456:                    initialState = StateOldDirty.getInstance();
457:                } else {
458:                    // if object is already persistent it will be marked as old.
459:                    // it is marked as clean as it has not been modified during tx already
460:                    initialState = StateOldClean.getInstance();
461:                }
462:                // remember it:
463:                modificationState = initialState;
464:            }
465:
466:            /**
467:             * Checks if the object with the given identity has been deleted
468:             * within the transaction.
469:             * @param id The identity
470:             * @return true if the object has been deleted
471:             * @throws PersistenceBrokerException
472:             */
473:            public boolean isDeleted(Identity id) {
474:                ObjectEnvelope envelope = buffer.getByIdentity(id);
475:
476:                return (envelope != null && envelope.needsDelete());
477:            }
478:
479:            /**
480:             * set the Modification state to a new value. Used during state transitions.
481:             * @param newModificationState org.apache.ojb.server.states.ModificationState
482:             */
483:            public void setModificationState(
484:                    ModificationState newModificationState) {
485:                if (newModificationState != modificationState) {
486:                    if (log.isDebugEnabled()) {
487:                        log.debug("object state transition for object "
488:                                + this .oid + " (" + modificationState + " --> "
489:                                + newModificationState + ")");
490:                        //                try{throw new Exception();}catch(Exception e)
491:                        //                {
492:                        //                e.printStackTrace();
493:                        //                }
494:                    }
495:                    modificationState = newModificationState;
496:                }
497:            }
498:
499:            /**
500:             * returns a String representation.
501:             * @return java.lang.String
502:             */
503:            public String toString() {
504:                ToStringBuilder buf = new ToStringBuilder(this );
505:                buf.append("Identity", oid).append("ModificationState",
506:                        modificationState.toString());
507:                return buf.toString();
508:            }
509:
510:            /**
511:             * For internal use only! Only call immediately before commit to guarantee
512:             * that all changes can be detected (because this method cache the detected "change state"
513:             * thus on eager call changes could be ignored). Checks whether object and internal clone
514:             * differ and returns <em>true</em> if so, returns <em>false</em> else.
515:             *
516:             * @return boolean The result.
517:             */
518:            public boolean hasChanged(PersistenceBroker broker) {
519:                if (hasChanged == null) {
520:                    Map current = null;
521:                    try {
522:                        current = getCurrentImage();
523:                    } catch (Exception e) {
524:                        log.warn(
525:                                "Could not verify object changes, mark dirty: "
526:                                        + getIdentity(), e);
527:                    }
528:                    if (beforeImage != null && current != null) {
529:                        Iterator it = beforeImage.entrySet().iterator();
530:                        hasChanged = Boolean.FALSE;
531:                        while (it.hasNext()) {
532:                            Map.Entry entry = (Map.Entry) it.next();
533:                            Image imageBefore = (Image) entry.getValue();
534:                            Image imageCurrent = (Image) current.get(entry
535:                                    .getKey());
536:                            if (imageBefore.modified(imageCurrent)) {
537:                                hasChanged = Boolean.TRUE;
538:                                break;
539:                            }
540:                        }
541:                    } else {
542:                        hasChanged = Boolean.TRUE;
543:                    }
544:                    if (log.isDebugEnabled()) {
545:                        log.debug("State detection for "
546:                                + getIdentity()
547:                                + " --> object "
548:                                + (hasChanged.booleanValue() ? "has changed"
549:                                        : "unchanged"));
550:                    }
551:                }
552:                return hasChanged.booleanValue();
553:            }
554:
555:            /**
556:             * Mark new or deleted reference elements
557:             * @param broker
558:             */
559:            void markReferenceElements(PersistenceBroker broker) {
560:                // these cases will be handled by ObjectEnvelopeTable#cascadingDependents()
561:                // if(getModificationState().needsInsert() || getModificationState().needsDelete()) return;
562:
563:                Map oldImage = getBeforeImage();
564:                Map newImage = getCurrentImage();
565:
566:                Iterator iter = newImage.entrySet().iterator();
567:                while (iter.hasNext()) {
568:                    Map.Entry entry = (Map.Entry) iter.next();
569:                    Object key = entry.getKey();
570:                    // we only interested in references
571:                    if (key instanceof  ObjectReferenceDescriptor) {
572:                        Image oldRefImage = (Image) oldImage.get(key);
573:                        Image newRefImage = (Image) entry.getValue();
574:                        newRefImage.performReferenceDetection(oldRefImage);
575:                    }
576:                }
577:            }
578:
579:            public void doUpdate() {
580:                if (log.isDebugEnabled())
581:                    log.debug("Start UPDATE action for " + getIdentity());
582:                performLinkEntries();
583:                getBroker().store(getObject(), getIdentity(),
584:                        getClassDescriptor(), false, true);
585:            }
586:
587:            public void doInsert() {
588:                if (log.isDebugEnabled())
589:                    log.debug("Start INSERT action for " + getIdentity());
590:                performLinkEntries();
591:                getBroker().store(getObject(), getIdentity(),
592:                        getClassDescriptor(), true, true);
593:                Identity oldOid = refreshIdentity();
594:                buffer.replaceRegisteredIdentity(getIdentity(), oldOid);
595:            }
596:
597:            public void doDelete() {
598:                if (log.isDebugEnabled())
599:                    log.debug("Start DELETE action for " + getIdentity());
600:                getBroker().delete(getObject(), true);
601:            }
602:
603:            public void doEvictFromCache() {
604:                if (log.isDebugEnabled())
605:                    log.debug("Remove from cache " + getIdentity());
606:                getBroker().removeFromCache(getIdentity());
607:            }
608:
609:            public boolean isWriteLocked() {
610:                return writeLocked;
611:            }
612:
613:            public void setWriteLocked(boolean writeLocked) {
614:                this .writeLocked = writeLocked;
615:            }
616:
617:            ClassDescriptor getClassDescriptor() {
618:                return getBroker().getClassDescriptor(
619:                        ProxyHelper.getRealClass(getObject()));
620:            }
621:
622:            void addLinkOneToOne(ObjectReferenceDescriptor ord, boolean unlink) {
623:                LinkEntry entry = new LinkEntryOneToOne(ord, getObject(),
624:                        unlink);
625:                linkEntryList.add(entry);
626:            }
627:
628:            void addLinkOneToN(CollectionDescriptor col, Object source,
629:                    boolean unlink) {
630:                if (col.isMtoNRelation())
631:                    throw new OJBRuntimeException(
632:                            "Expected an 1:n relation, but specified a m:n");
633:                LinkEntry entry = new LinkEntryOneToN(source, col, getObject(),
634:                        unlink);
635:                linkEntryList.add(entry);
636:            }
637:
638:            private void performLinkEntries() {
639:                PersistenceBroker broker = getBroker();
640:                for (int i = 0; i < linkEntryList.size(); i++) {
641:                    LinkEntry linkEntry = (LinkEntry) linkEntryList.get(i);
642:                    linkEntry.execute(broker);
643:                }
644:            }
645:
646:            public void addedOneToOne(ObjectReferenceDescriptor ord,
647:                    Object refObjOrProxy, Identity oid) {
648:                // the main objects needs link/unlink of the FK to 1:1 reference,
649:                // so mark this dirty
650:                setModificationState(getModificationState().markDirty());
651:                // if the object is already registered, OJB knows about
652:                // else lock and register object, get read lock, because we
653:                // don't know if the object is new or moved from an existing other object
654:                ObjectEnvelope oe = buffer.getByIdentity(oid);
655:                if (oe == null) {
656:                    RuntimeObject rt = new RuntimeObject(refObjOrProxy, getTx());
657:                    // we don't use cascade locking, because new reference object
658:                    // will be detected by ObjectEnvelopeTable#cascadeMarkedForInsert()
659:                    getTx().lockAndRegister(rt, TransactionExt.READ, false,
660:                            getTx().getRegistrationList());
661:                }
662:                // in any case we need to link the main object
663:                addLinkOneToOne(ord, false);
664:            }
665:
666:            public void deletedOneToOne(ObjectReferenceDescriptor ord,
667:                    Object refObjOrProxy, Identity oid, boolean needsUnlink) {
668:                // the main objects needs link/unlink of the FK to 1:1 reference,
669:                // so mark this dirty
670:                setModificationState(getModificationState().markDirty());
671:                ObjectEnvelope oldRefMod = buffer.getByIdentity(oid);
672:                // only delete when the reference wasn't assigned with another object
673:                if (!buffer.isNewAssociatedObject(oid)) {
674:                    // if cascading delete is enabled, remove the 1:1 reference
675:                    // because it was removed from the main object
676:                    if (buffer.getTransaction().cascadeDeleteFor(ord)) {
677:                        oldRefMod.setModificationState(oldRefMod
678:                                .getModificationState().markDelete());
679:                    }
680:                    // unlink the main object
681:                    if (needsUnlink)
682:                        addLinkOneToOne(ord, true);
683:                }
684:            }
685:
686:            public void addedXToN(CollectionDescriptor cod,
687:                    Object refObjOrProxy, Identity oid) {
688:                ObjectEnvelope mod = buffer.getByIdentity(oid);
689:                // if the object isn't registered already, it can be 'new' or already 'persistent'
690:                if (mod == null) {
691:                    boolean isNew = getTx().isTransient(null, refObjOrProxy,
692:                            oid);
693:                    mod = buffer.get(oid, refObjOrProxy, isNew);
694:                }
695:                // if the object was deleted in an previous action, mark as new
696:                // to avoid deletion, else mark object as dirty to assign the FK of
697:                // the main object
698:                if (mod.needsDelete()) {
699:                    mod.setModificationState(mod.getModificationState()
700:                            .markNew());
701:                } else {
702:                    /*
703:                    arminw: if the reference is a m:n relation and the object state is
704:                    old clean, no need to update the reference.
705:                     */
706:                    if (!(cod.isMtoNRelation() && mod.getModificationState()
707:                            .equals(StateOldClean.getInstance()))) {
708:                        mod.setModificationState(mod.getModificationState()
709:                                .markDirty());
710:                    }
711:                }
712:                // buffer this object as "new" in a list to prevent deletion
713:                // when object was moved from one collection to another
714:                buffer.addNewAssociatedIdentity(oid);
715:                // new referenced object found, so register all m:n relation for "linking"
716:                if (cod.isMtoNRelation()) {
717:                    buffer.addM2NLinkEntry(cod, getObject(), refObjOrProxy);
718:                } else {
719:                    // we have to link the new object
720:                    mod.addLinkOneToN(cod, getObject(), false);
721:                }
722:                if (mod.needsInsert()) {
723:                    buffer.addForInsertDependent(mod);
724:                }
725:            }
726:
727:            public void deletedXToN(CollectionDescriptor cod,
728:                    Object refObjOrProxy, Identity oid) {
729:                ObjectEnvelope mod = buffer.getByIdentity(oid);
730:                // if this object is associated with another object it's
731:                // not allowed to remove it, thus nothing will change
732:                if (!buffer.isNewAssociatedObject(oid)) {
733:                    if (mod != null) {
734:                        boolean cascade = buffer.getTransaction()
735:                                .cascadeDeleteFor(cod);
736:                        if (cascade) {
737:                            mod.setModificationState(mod.getModificationState()
738:                                    .markDelete());
739:                            buffer.addForDeletionDependent(mod);
740:                        }
741:                        if (cod.isMtoNRelation()) {
742:                            buffer.addM2NUnlinkEntry(cod, getObject(),
743:                                    refObjOrProxy);
744:                        } else {
745:                            // when cascade 'true' we remove all dependent objects, so no need
746:                            // to unlink, else we have to unlink all referenced objects of this
747:                            // object
748:                            if (!cascade) {
749:                                mod.setModificationState(mod
750:                                        .getModificationState().markDirty());
751:                                mod.addLinkOneToN(cod, getObject(), true);
752:                            }
753:                        }
754:                    } else {
755:                        throw new Image.ImageException(
756:                                "Unexpected behaviour, unregistered object to delete: "
757:                                        + oid + ", main object is "
758:                                        + getIdentity()
759:                                        + ", envelope object is "
760:                                        + this.toString());
761:                    }
762:                }
763:            }
764:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.