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

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


001:        /**********************************************************************
002:        Copyright (c) 2007 Andy Jefferson and others. All rights reserved.
003:        Licensed under the Apache License, Version 2.0 (the "License");
004:        you may not use this file except in compliance with the License.
005:        You may obtain a copy of the License at
006:
007:            http://www.apache.org/licenses/LICENSE-2.0
008:
009:        Unless required by applicable law or agreed to in writing, software
010:        distributed under the License is distributed on an "AS IS" BASIS,
011:        WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012:        See the License for the specific language governing permissions and
013:        limitations under the License.
014:
015:        Contributors:
016:            ...
017:         **********************************************************************/package org.jpox.state;
018:
019:        import java.util.ArrayList;
020:        import java.util.Collection;
021:        import java.util.HashMap;
022:        import java.util.Iterator;
023:        import java.util.Map;
024:        import java.util.Set;
025:
026:        import org.jpox.ClassLoaderResolver;
027:        import org.jpox.ObjectManager;
028:        import org.jpox.StateManager;
029:        import org.jpox.exceptions.JPOXUserException;
030:        import org.jpox.metadata.AbstractClassMetaData;
031:        import org.jpox.metadata.AbstractMemberMetaData;
032:        import org.jpox.metadata.Relation;
033:        import org.jpox.sco.SCOCollection;
034:        import org.jpox.util.JPOXLogger;
035:        import org.jpox.util.Localiser;
036:        import org.jpox.util.StringUtils;
037:
038:        /**
039:         * Manager for relationships of a class.
040:         * Performs management of (bidirectional) relations.
041:         * If one side is set yet the other isnt, corrects the other side.
042:         * 
043:         * @version $Revision$
044:         */
045:        public class RelationshipManager {
046:            /** Localiser for messages. */
047:            protected static final Localiser LOCALISER = Localiser
048:                    .getInstance("org.jpox.Localisation");
049:
050:            /** StateManager for the object we are managing the relationships for. */
051:            final StateManager ownerSM;
052:
053:            /** Object being managed. */
054:            final Object pc;
055:
056:            /**
057:             * Map of bidirectional field "changes". 
058:             * For 1-1, N-1 fields the "change" is actually the original value (for later comparison).
059:             * For 1-N, M-N fields the "change" is an ArrayList of RelationChange objects.
060:             */
061:            final Map fieldChanges;
062:
063:            /**
064:             * Constructor.
065:             * @param sm StateManager for the object that we are managing relations for.
066:             */
067:            public RelationshipManager(StateManager sm) {
068:                this .ownerSM = sm;
069:                this .pc = sm.getObject();
070:                this .fieldChanges = new HashMap();
071:
072:                // Mark the StateManager as having its relations managed
073:                ownerSM.getObjectManager().markManagedRelationDirty(sm);
074:            }
075:
076:            private static final int ADD_OBJECT = 1; // Element added to a collection
077:            private static final int REMOVE_OBJECT = 2; // Element removed from a collection
078:
079:            /**
080:             * Definition of a change in a relation.
081:             * @version $Revision$
082:             */
083:            private class RelationChange {
084:                int type;
085:                Object value;
086:
087:                public RelationChange(int type, Object val) {
088:                    this .type = type;
089:                    this .value = val;
090:                }
091:            }
092:
093:            /**
094:             * Convenience method to clear all fields from being managed.
095:             */
096:            public void clearFields() {
097:                fieldChanges.clear();
098:            }
099:
100:            /**
101:             * Method that is called when the user calls setXXX() on a field.
102:             * @param fieldNumber Number of the field
103:             * @param oldValue The old value
104:             * @param newValue The new value
105:             */
106:            public void relationChange(int fieldNumber, Object oldValue,
107:                    Object newValue) {
108:                if (ownerSM.getObjectManager().isManagingRelations()) {
109:                    return;
110:                }
111:
112:                Integer fieldKey = new Integer(fieldNumber);
113:                if (!fieldChanges.containsKey(fieldKey)) {
114:                    // Store the original value only - only good for PC fields really
115:                    AbstractClassMetaData cmd = ownerSM.getClassMetaData();
116:                    AbstractMemberMetaData mmd = cmd
117:                            .getMetaDataForManagedMemberAtAbsolutePosition(fieldNumber);
118:                    int relationType = mmd.getRelationType(ownerSM
119:                            .getObjectManager().getClassLoaderResolver());
120:                    if (relationType == Relation.ONE_TO_ONE_BI
121:                            || relationType == Relation.MANY_TO_ONE_BI) {
122:                        // Only allow for set of PC field (ignore set of Collection fields)
123:                        fieldChanges.put(fieldKey, oldValue);
124:                    }
125:                }
126:            }
127:
128:            /**
129:             * Method to register a change in the contents of a container field, with an object being added.
130:             * @param fieldNumber Number of the field
131:             * @param val Value being added
132:             */
133:            public void relationAdd(int fieldNumber, Object val) {
134:                if (ownerSM.getObjectManager().isManagingRelations()) {
135:                    return;
136:                }
137:
138:                AbstractClassMetaData cmd = ownerSM.getClassMetaData();
139:                AbstractMemberMetaData mmd = cmd
140:                        .getMetaDataForManagedMemberAtAbsolutePosition(fieldNumber);
141:                int relationType = mmd.getRelationType(ownerSM
142:                        .getObjectManager().getClassLoaderResolver());
143:                if (relationType != Relation.ONE_TO_MANY_BI
144:                        && relationType != Relation.MANY_TO_MANY_BI) {
145:                    return;
146:                }
147:
148:                Integer fieldKey = new Integer(fieldNumber);
149:                Object changes = fieldChanges.get(fieldKey);
150:                ArrayList changeList = null;
151:                if (changes == null) {
152:                    changeList = new ArrayList();
153:                } else {
154:                    // Assume we have an ArrayList
155:                    changeList = (ArrayList) changes;
156:                }
157:                RelationChange change = new RelationChange(ADD_OBJECT, val);
158:                changeList.add(change);
159:                fieldChanges.put(fieldKey, changeList);
160:            }
161:
162:            /**
163:             * Method to register a change in the contents of a container field, with an object being removed.
164:             * @param fieldNumber Number of the field
165:             * @param val Value being removed
166:             */
167:            public void relationRemove(int fieldNumber, Object val) {
168:                if (ownerSM.getObjectManager().isManagingRelations()) {
169:                    return;
170:                }
171:
172:                AbstractClassMetaData cmd = ownerSM.getClassMetaData();
173:                AbstractMemberMetaData mmd = cmd
174:                        .getMetaDataForManagedMemberAtAbsolutePosition(fieldNumber);
175:                int relationType = mmd.getRelationType(ownerSM
176:                        .getObjectManager().getClassLoaderResolver());
177:                if (relationType != Relation.ONE_TO_MANY_BI
178:                        && relationType != Relation.MANY_TO_MANY_BI) {
179:                    return;
180:                }
181:
182:                Integer fieldKey = new Integer(fieldNumber);
183:                Object changes = fieldChanges.get(fieldKey);
184:                ArrayList changeList = null;
185:                if (changes == null) {
186:                    changeList = new ArrayList();
187:                } else {
188:                    changeList = (ArrayList) changes;
189:                }
190:                RelationChange change = new RelationChange(REMOVE_OBJECT, val);
191:                changeList.add(change);
192:            }
193:
194:            /**
195:             * Accessor for whether a field is being managed.
196:             * @param fieldNumber Number of the field
197:             * @return Whether it is currently managed
198:             */
199:            private boolean managesField(int fieldNumber) {
200:                return fieldChanges.containsKey(new Integer(fieldNumber));
201:            }
202:
203:            /**
204:             * Method to check for consistency the managed relations of this object with the related objects.
205:             */
206:            public void checkConsistency() {
207:                Set entries = fieldChanges.entrySet();
208:                Iterator iter = entries.iterator();
209:                AbstractClassMetaData cmd = ownerSM.getClassMetaData();
210:                ObjectManager om = ownerSM.getObjectManager();
211:                while (iter.hasNext()) {
212:                    Map.Entry entry = (Map.Entry) iter.next();
213:                    int fieldNumber = ((Integer) entry.getKey()).intValue();
214:                    AbstractMemberMetaData mmd = cmd
215:                            .getMetaDataForManagedMemberAtAbsolutePosition(fieldNumber);
216:                    ClassLoaderResolver clr = om.getClassLoaderResolver();
217:                    Object oldValue = entry.getValue();
218:                    int relationType = mmd.getRelationType(clr);
219:                    if (relationType == Relation.ONE_TO_ONE_BI) {
220:                        // 1-1 bidirectional
221:                        Object newValue = ownerSM.provideField(fieldNumber);
222:                        checkOneToOneBidirectionalRelation(mmd, clr, om,
223:                                oldValue, newValue);
224:                    } else if (relationType == Relation.MANY_TO_ONE_BI) {
225:                        // N-1 bidirectional
226:                        Object newValue = ownerSM.provideField(fieldNumber);
227:                        checkManyToOneBidirectionalRelation(mmd, clr, om,
228:                                oldValue, newValue);
229:                    } else if (relationType == Relation.ONE_TO_MANY_BI) {
230:                        // 1-N bidirectional
231:                        ArrayList changes = (ArrayList) oldValue;
232:                        checkOneToManyBidirectionalRelation(mmd, clr, om,
233:                                changes);
234:                    } else if (relationType == Relation.MANY_TO_MANY_BI) {
235:                        // M-N bidirectional
236:                        ArrayList changes = (ArrayList) oldValue;
237:                        checkManyToManyBidirectionalRelation(mmd, clr, om,
238:                                changes);
239:                    }
240:                }
241:            }
242:
243:            /**
244:             * Method to process the (bidirectional) relations for this object.
245:             */
246:            public void process() {
247:                Set entries = fieldChanges.entrySet();
248:                Iterator iter = entries.iterator();
249:                AbstractClassMetaData cmd = ownerSM.getClassMetaData();
250:                ObjectManager om = ownerSM.getObjectManager();
251:                while (iter.hasNext()) {
252:                    Map.Entry entry = (Map.Entry) iter.next();
253:                    int fieldNumber = ((Integer) entry.getKey()).intValue();
254:                    AbstractMemberMetaData mmd = cmd
255:                            .getMetaDataForManagedMemberAtAbsolutePosition(fieldNumber);
256:                    ClassLoaderResolver clr = om.getClassLoaderResolver();
257:                    Object oldValue = entry.getValue();
258:                    int relationType = mmd.getRelationType(clr);
259:                    if (relationType == Relation.ONE_TO_ONE_BI) {
260:                        // 1-1 bidirectional
261:                        Object newValue = ownerSM.provideField(fieldNumber);
262:                        processOneToOneBidirectionalRelation(mmd, clr, om,
263:                                oldValue, newValue);
264:                    } else if (relationType == Relation.MANY_TO_ONE_BI) {
265:                        // N-1 bidirectional
266:                        Object newValue = ownerSM.provideField(fieldNumber);
267:                        processManyToOneBidirectionalRelation(mmd, clr, om,
268:                                oldValue, newValue);
269:                    } else if (relationType == Relation.ONE_TO_MANY_BI) {
270:                        // 1-N bidirectional
271:                        ArrayList changes = (ArrayList) oldValue;
272:                        processOneToManyBidirectionalRelation(mmd, clr, om,
273:                                changes);
274:                    } else if (relationType == Relation.MANY_TO_MANY_BI) {
275:                        // M-N bidirectional
276:                        ArrayList changes = (ArrayList) oldValue;
277:                        processManyToManyBidirectionalRelation(mmd, clr, om,
278:                                changes);
279:                    }
280:                }
281:            }
282:
283:            /**
284:             * Method to check the consistency of the passed field as 1-1.
285:             * Processes the case where we had a 1-1 field set at this side previously to some value and now to
286:             * some other value. We need to make sure that all of the affected objects are now related consistently.
287:             * Taking an example <pre>a.b = b1; a.b = b2;</pre> so A's b field is changed from b1 to b2.
288:             * The following changes are likely to be necessary
289:             * <ul>
290:             * <li>b1.a = null - so we null out the old related objects link back to this object</li>
291:             * <li>b2.oldA = null - if b2 was previously related to a different A, null out that objects link to b2</li>
292:             * <li>b2.a = a - set the link from b2 back to a so it is bidirectional</li>
293:             * </ul>
294:             * @param mmd MetaData for the field
295:             * @param clr ClassLoader resolver
296:             * @param om ObjectManager
297:             * @param oldValue The old value
298:             * @param newValue The new value
299:             */
300:            protected void checkOneToOneBidirectionalRelation(
301:                    AbstractMemberMetaData mmd, ClassLoaderResolver clr,
302:                    ObjectManager om, Object oldValue, Object newValue) {
303:                if (newValue != null) {
304:                    // Previously had "a.b = b1"; Now have "a.b = b2"
305:                    // Check that the new value hasnt been assigned to something other than this object
306:                    AbstractMemberMetaData relatedMmd = mmd
307:                            .getRelatedMemberMetaDataForObject(clr, pc,
308:                                    newValue);
309:                    org.jpox.StateManager newSM = om.findStateManager(newValue);
310:                    if (newSM != null && relatedMmd != null) {
311:                        newSM.loadField(relatedMmd.getAbsoluteFieldNumber());
312:                        Object newValueFieldValue = newSM
313:                                .provideField(relatedMmd
314:                                        .getAbsoluteFieldNumber());
315:                        if (newValueFieldValue != pc) {
316:                            RelationshipManager newRelMgr = newSM
317:                                    .getRelationshipManager();
318:                            if (newRelMgr != null
319:                                    && newRelMgr.managesField(relatedMmd
320:                                            .getAbsoluteFieldNumber())) {
321:                                // New value has had its side of the relation changed to a different value altogether!
322:                                if (newValueFieldValue == null) {
323:                                    String msg = LOCALISER.msg("013003",
324:                                            StringUtils.toJVMIDString(pc), mmd
325:                                                    .getName(), StringUtils
326:                                                    .toJVMIDString(newValue),
327:                                            relatedMmd.getName());
328:                                    JPOXLogger.PERSISTENCE.error(msg);
329:                                    throw new JPOXUserException(msg);
330:                                } else {
331:                                    String msg = LOCALISER
332:                                            .msg(
333:                                                    "013002",
334:                                                    StringUtils
335:                                                            .toJVMIDString(pc),
336:                                                    mmd.getName(),
337:                                                    StringUtils
338:                                                            .toJVMIDString(newValue),
339:                                                    relatedMmd.getName(),
340:                                                    StringUtils
341:                                                            .toJVMIDString(newValueFieldValue));
342:                                    JPOXLogger.PERSISTENCE.error(msg);
343:                                    throw new JPOXUserException(msg);
344:                                }
345:                            }
346:                        }
347:                    }
348:                }
349:            }
350:
351:            /**
352:             * Method to check the consistency of the passed field as 1-N.
353:             * @param mmd MetaData for the field
354:             * @param clr ClassLoader resolver
355:             * @param om ObjectManager
356:             * @param changes List of changes to the collection
357:             */
358:            protected void checkOneToManyBidirectionalRelation(
359:                    AbstractMemberMetaData mmd, ClassLoaderResolver clr,
360:                    ObjectManager om, ArrayList changes) {
361:                Iterator iter = changes.iterator();
362:                while (iter.hasNext()) {
363:                    RelationChange change = (RelationChange) iter.next();
364:                    if (change.type == ADD_OBJECT) {
365:                        if (ownerSM.getObjectManager().getApiAdapter()
366:                                .isDeleted(change.value)) {
367:                            // The element was added but was then the element object was deleted!
368:                            throw new JPOXUserException(LOCALISER.msg("013008",
369:                                    StringUtils.toJVMIDString(pc), mmd
370:                                            .getName(), StringUtils
371:                                            .toJVMIDString(change.value)));
372:                        } else {
373:                            AbstractMemberMetaData relatedMmd = mmd
374:                                    .getRelatedMemberMetaData(clr)[0];
375:                            org.jpox.StateManager newElementSM = om
376:                                    .findStateManager(change.value);
377:                            if (newElementSM != null) {
378:                                newElementSM.loadField(relatedMmd
379:                                        .getAbsoluteFieldNumber());
380:                                RelationshipManager newElementRelMgr = newElementSM
381:                                        .getRelationshipManager();
382:                                if (newElementRelMgr != null
383:                                        && newElementRelMgr
384:                                                .managesField(relatedMmd
385:                                                        .getAbsoluteFieldNumber())) {
386:                                    // Element has had the owner set, so make sure it is set to this object
387:                                    Object newValueFieldValue = newElementSM
388:                                            .provideField(relatedMmd
389:                                                    .getAbsoluteFieldNumber());
390:                                    if (newValueFieldValue != pc
391:                                            && newValueFieldValue != null) {
392:                                        // The element has a different owner than the PC with this collection
393:                                        // This catches cases where the user has set the wrong owner, and also
394:                                        // will catch cases where the user has added it to two collections
395:                                        throw new JPOXUserException(
396:                                                LOCALISER
397:                                                        .msg(
398:                                                                "013009",
399:                                                                StringUtils
400:                                                                        .toJVMIDString(pc),
401:                                                                mmd.getName(),
402:                                                                StringUtils
403:                                                                        .toJVMIDString(change.value),
404:                                                                StringUtils
405:                                                                        .toJVMIDString(newValueFieldValue)));
406:                                    }
407:                                }
408:                            }
409:                        }
410:                    } else if (change.type == REMOVE_OBJECT) {
411:                        if (ownerSM.getObjectManager().getApiAdapter()
412:                                .isDeleted(change.value)) {
413:                            // The element was removed and was then the element object was deleted so do nothing
414:                        } else {
415:                            AbstractMemberMetaData relatedMmd = mmd
416:                                    .getRelatedMemberMetaData(clr)[0];
417:                            org.jpox.StateManager newElementSM = om
418:                                    .findStateManager(change.value);
419:                            if (newElementSM != null) {
420:                                newElementSM.loadField(relatedMmd
421:                                        .getAbsoluteFieldNumber());
422:                                RelationshipManager newElementRelMgr = newElementSM
423:                                        .getRelationshipManager();
424:                                if (newElementRelMgr != null
425:                                        && newElementRelMgr
426:                                                .managesField(relatedMmd
427:                                                        .getAbsoluteFieldNumber())) {
428:                                    // Element has had the owner set, so make sure it is not set to this object
429:                                    Object newValueFieldValue = newElementSM
430:                                            .provideField(relatedMmd
431:                                                    .getAbsoluteFieldNumber());
432:                                    if (newValueFieldValue == pc) {
433:                                        // The element was removed from the collection, but was updated to have its owner
434:                                        // set to the collection owner!
435:                                        throw new JPOXUserException(
436:                                                LOCALISER
437:                                                        .msg(
438:                                                                "013010",
439:                                                                StringUtils
440:                                                                        .toJVMIDString(pc),
441:                                                                mmd.getName(),
442:                                                                StringUtils
443:                                                                        .toJVMIDString(change.value)));
444:                                    }
445:                                }
446:                            }
447:                        }
448:                    }
449:                }
450:            }
451:
452:            /**
453:             * Method to check the consistency of the passed field as N-1.
454:             * Processes the case where we had an N-1 field set at this side previously to some value and now to
455:             * some other value.That is, this object was in some collection/map originally, and now should be in some
456:             * other collection/map. So in terms of an example this object "a" was in collection "b1.as" before and is 
457:             * now in "b2.as". The following changes are likely to be necessary
458:             * <ul>
459:             * <li>b1.getAs().remove(a) - remove it from b1.as if still present</li>
460:             * <li>b2.getAs().add(a) - add it to b1.as if not present</li>
461:             * </ul>
462:             * @param mmd MetaData for the field
463:             * @param clr ClassLoader resolver
464:             * @param om ObjectManager
465:             * @param oldValue The old value
466:             * @param newValue The new value
467:             */
468:            protected void checkManyToOneBidirectionalRelation(
469:                    AbstractMemberMetaData mmd, ClassLoaderResolver clr,
470:                    ObjectManager om, Object oldValue, Object newValue) {
471:                // TODO Implement N-1
472:            }
473:
474:            /**
475:             * Method to check consistency of the passed field as M-N.
476:             * @param mmd MetaData for the field
477:             * @param clr ClassLoader resolver
478:             * @param om ObjectManager
479:             * @param changes List of changes to the collection
480:             */
481:            protected void checkManyToManyBidirectionalRelation(
482:                    AbstractMemberMetaData mmd, ClassLoaderResolver clr,
483:                    ObjectManager om, ArrayList changes) {
484:                // TODO Implement M-N
485:            }
486:
487:            /**
488:             * Method to process all 1-1 bidir fields.
489:             * Processes the case where we had a 1-1 field set at this side previously to some value and now to
490:             * some other value. We need to make sure that all of the affected objects are now related consistently.
491:             * Taking an example <pre>a.b = b1; a.b = b2;</pre> so A's b field is changed from b1 to b2.
492:             * The following changes are likely to be necessary
493:             * <ul>
494:             * <li>b1.a = null - so we null out the old related objects link back to this object</li>
495:             * <li>b2.oldA = null - if b2 was previously related to a different A, null out that objects link to b2</li>
496:             * <li>b2.a = a - set the link from b2 back to a so it is bidirectional</li>
497:             * </ul>
498:             * @param mmd MetaData for the field
499:             * @param clr ClassLoader resolver
500:             * @param om ObjectManager
501:             * @param oldValue The old value
502:             * @param newValue The new value
503:             */
504:            protected void processOneToOneBidirectionalRelation(
505:                    AbstractMemberMetaData mmd, ClassLoaderResolver clr,
506:                    ObjectManager om, Object oldValue, Object newValue) {
507:                if (oldValue != null) {
508:                    // Previously had "a.b = b1"; "a.b" has been changed
509:                    // Need to remove from the other side if still set
510:                    AbstractMemberMetaData relatedMmd = mmd
511:                            .getRelatedMemberMetaDataForObject(clr, pc,
512:                                    oldValue);
513:                    org.jpox.StateManager oldSM = om.findStateManager(oldValue);
514:                    if (oldSM != null) {
515:                        oldSM.loadField(relatedMmd.getAbsoluteFieldNumber());
516:                        Object oldValueFieldValue = oldSM
517:                                .provideField(relatedMmd
518:                                        .getAbsoluteFieldNumber());
519:                        if (oldValueFieldValue == null) {
520:                            // Set to null so nothing to do
521:                        } else if (oldValueFieldValue == pc) {
522:                            // Still set to this object, so null out the other objects relation
523:                            if (JPOXLogger.PERSISTENCE.isDebugEnabled()) {
524:                                JPOXLogger.PERSISTENCE.debug(LOCALISER.msg(
525:                                        "013004", StringUtils
526:                                                .toJVMIDString(oldValue),
527:                                        relatedMmd.getFullFieldName(),
528:                                        StringUtils.toJVMIDString(pc),
529:                                        StringUtils.toJVMIDString(newValue)));
530:                            }
531:                            oldSM.replaceFieldValue(relatedMmd
532:                                    .getAbsoluteFieldNumber(), null);
533:                        }
534:                    }
535:                }
536:                if (newValue != null) {
537:                    // Previously had "a.b = b1"; Now have "a.b = b2"
538:                    // Need to set the other side if not yet set, and unset any related old value on the other side
539:                    AbstractMemberMetaData relatedMmd = mmd
540:                            .getRelatedMemberMetaDataForObject(clr, pc,
541:                                    newValue);
542:                    org.jpox.StateManager newSM = om.findStateManager(newValue);
543:                    if (newSM != null && relatedMmd != null) {
544:                        newSM.loadField(relatedMmd.getAbsoluteFieldNumber());
545:                        Object newValueFieldValue = newSM
546:                                .provideField(relatedMmd
547:                                        .getAbsoluteFieldNumber());
548:                        if (newValueFieldValue == null) {
549:                            // Was set to null so set to our object
550:                            if (JPOXLogger.PERSISTENCE.isDebugEnabled()) {
551:                                JPOXLogger.PERSISTENCE.debug(LOCALISER.msg(
552:                                        "013005", StringUtils
553:                                                .toJVMIDString(newValue),
554:                                        relatedMmd.getFullFieldName(),
555:                                        StringUtils.toJVMIDString(pc)));
556:                            }
557:                            newSM.replaceFieldValue(relatedMmd
558:                                    .getAbsoluteFieldNumber(), pc);
559:                        } else if (newValueFieldValue != pc) {
560:                            // Was set to different object, so null out the other objects relation
561:                            org.jpox.StateManager newValueFieldSM = om
562:                                    .findStateManager(newValueFieldValue);
563:                            if (newValueFieldSM != null) {
564:                                // Null out the field of the related object of the new value
565:                                newValueFieldSM.loadField(mmd
566:                                        .getAbsoluteFieldNumber());
567:                                if (JPOXLogger.PERSISTENCE.isDebugEnabled()) {
568:                                    JPOXLogger.PERSISTENCE
569:                                            .debug(LOCALISER
570:                                                    .msg(
571:                                                            "013004",
572:                                                            StringUtils
573:                                                                    .toJVMIDString(newValueFieldValue),
574:                                                            mmd
575:                                                                    .getFullFieldName(),
576:                                                            StringUtils
577:                                                                    .toJVMIDString(newValue),
578:                                                            StringUtils
579:                                                                    .toJVMIDString(pc)));
580:                                }
581:                                newValueFieldSM.replaceFieldValue(mmd
582:                                        .getAbsoluteFieldNumber(), null);
583:                            }
584:                            // Update the field of the new value to our object
585:                            if (JPOXLogger.PERSISTENCE.isDebugEnabled()) {
586:                                JPOXLogger.PERSISTENCE.debug(LOCALISER.msg(
587:                                        "013005", StringUtils
588:                                                .toJVMIDString(newValue),
589:                                        relatedMmd.getFullFieldName(),
590:                                        StringUtils.toJVMIDString(pc)));
591:                            }
592:                            newSM.replaceFieldValue(relatedMmd
593:                                    .getAbsoluteFieldNumber(), pc);
594:                        }
595:                    }
596:                }
597:            }
598:
599:            /**
600:             * Method to process all 1-N bidir fields.
601:             * @param mmd MetaData for the field
602:             * @param clr ClassLoader resolver
603:             * @param om ObjectManager
604:             * @param changes List of changes to the collection
605:             */
606:            protected void processOneToManyBidirectionalRelation(
607:                    AbstractMemberMetaData mmd, ClassLoaderResolver clr,
608:                    ObjectManager om, ArrayList changes) {
609:                Iterator iter = changes.iterator();
610:                while (iter.hasNext()) {
611:                    RelationChange change = (RelationChange) iter.next();
612:                    if (change.type == ADD_OBJECT) {
613:                    } else if (change.type == REMOVE_OBJECT) {
614:                    }
615:                }
616:                // TODO Implement 1-N
617:            }
618:
619:            /**
620:             * Method to process all N-1 bidir fields.
621:             * Processes the case where we had an N-1 field set at this side previously to some value and now to
622:             * some other value.That is, this object was in some collection/map originally, and now should be in some
623:             * other collection/map. So in terms of an example this object "a" was in collection "b1.as" before and is 
624:             * now in "b2.as". The following changes are likely to be necessary
625:             * <ul>
626:             * <li>b1.getAs().remove(a) - remove it from b1.as if still present</li>
627:             * <li>b2.getAs().add(a) - add it to b1.as if not present</li>
628:             * </ul>
629:             * @param mmd MetaData for the field
630:             * @param clr ClassLoader resolver
631:             * @param om ObjectManager
632:             * @param oldValue The old value
633:             * @param newValue The new value
634:             */
635:            protected void processManyToOneBidirectionalRelation(
636:                    AbstractMemberMetaData mmd, ClassLoaderResolver clr,
637:                    ObjectManager om, Object oldValue, Object newValue) {
638:                if (oldValue != null) {
639:                    // Has been removed from a Collection/Map
640:                    AbstractMemberMetaData relatedMmd = mmd
641:                            .getRelatedMemberMetaDataForObject(clr, pc,
642:                                    oldValue);
643:                    org.jpox.StateManager oldSM = om.findStateManager(oldValue);
644:                    if (oldSM != null && relatedMmd != null) {
645:                        oldSM.loadField(relatedMmd.getAbsoluteFieldNumber());
646:                        Object oldContainerValue = oldSM
647:                                .provideField(relatedMmd
648:                                        .getAbsoluteFieldNumber());
649:                        if (oldContainerValue instanceof  Collection) {
650:                            Collection oldColl = (Collection) oldContainerValue;
651:                            if (oldColl.contains(pc)) {
652:                                if (JPOXLogger.PERSISTENCE.isDebugEnabled()) {
653:                                    JPOXLogger.PERSISTENCE
654:                                            .debug(LOCALISER
655:                                                    .msg(
656:                                                            "013006",
657:                                                            StringUtils
658:                                                                    .toJVMIDString(pc),
659:                                                            mmd
660:                                                                    .getFullFieldName(),
661:                                                            relatedMmd
662:                                                                    .getFullFieldName(),
663:                                                            StringUtils
664:                                                                    .toJVMIDString(oldValue)));
665:                                }
666:
667:                                if (oldColl instanceof  SCOCollection) {
668:                                    // Avoid any cascade deletes that could have been fired by this action
669:                                    ((SCOCollection) oldColl).remove(pc, false);
670:                                } else {
671:                                    oldColl.remove(pc);
672:                                }
673:                            }
674:                        }
675:                    }
676:                }
677:                if (newValue != null) {
678:                    // Has been added to a Collection/Map
679:                    AbstractMemberMetaData relatedMmd = mmd
680:                            .getRelatedMemberMetaDataForObject(clr, pc,
681:                                    newValue);
682:                    org.jpox.StateManager newSM = om.findStateManager(newValue);
683:                    if (newSM != null && relatedMmd != null) {
684:                        newSM.loadField(relatedMmd.getAbsoluteFieldNumber());
685:                        Object newContainerValue = newSM
686:                                .provideField(relatedMmd
687:                                        .getAbsoluteFieldNumber());
688:                        if (newContainerValue instanceof  Collection) {
689:                            Collection newColl = (Collection) newContainerValue;
690:                            if (!newColl.contains(pc)) {
691:                                if (JPOXLogger.PERSISTENCE.isDebugEnabled()) {
692:                                    JPOXLogger.PERSISTENCE
693:                                            .debug(LOCALISER
694:                                                    .msg(
695:                                                            "013007",
696:                                                            StringUtils
697:                                                                    .toJVMIDString(pc),
698:                                                            mmd
699:                                                                    .getFullFieldName(),
700:                                                            relatedMmd
701:                                                                    .getFullFieldName(),
702:                                                            StringUtils
703:                                                                    .toJVMIDString(newValue)));
704:                                }
705:                                newColl.add(pc);
706:                            }
707:                        }
708:                    }
709:                }
710:            }
711:
712:            /**
713:             * Method to process all M-N bidir fields.
714:             * @param mmd MetaData for the field
715:             * @param clr ClassLoader resolver
716:             * @param om ObjectManager
717:             * @param changes List of changes to the collection
718:             */
719:            protected void processManyToManyBidirectionalRelation(
720:                    AbstractMemberMetaData mmd, ClassLoaderResolver clr,
721:                    ObjectManager om, ArrayList changes) {
722:                // TODO Implement M-N
723:            }
724:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.