KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > oracle > toplink > essentials > descriptors > DescriptorEvent


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the "License"). You may not use this file except
5  * in compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * glassfish/bootstrap/legal/CDDLv1.0.txt or
9  * https://glassfish.dev.java.net/public/CDDLv1.0.html.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * HEADER in each file and include the License file at
15  * glassfish/bootstrap/legal/CDDLv1.0.txt. If applicable,
16  * add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your
18  * own identifying information: Portions Copyright [yyyy]
19  * [name of copyright owner]
20  */

21 // Copyright (c) 1998, 2005, Oracle. All rights reserved.
22
package oracle.toplink.essentials.descriptors;
23
24 import java.util.*;
25 import oracle.toplink.essentials.mappings.DatabaseMapping;
26 import oracle.toplink.essentials.exceptions.ValidationException;
27 import oracle.toplink.essentials.exceptions.DescriptorException;
28 import oracle.toplink.essentials.queryframework.*;
29 import oracle.toplink.essentials.internal.sessions.*;
30 import oracle.toplink.essentials.sessions.Record;
31 import oracle.toplink.essentials.internal.sessions.AbstractRecord;
32 import oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl;
33 import oracle.toplink.essentials.internal.sessions.AbstractSession;
34
35 /**
36  * <p><b>Purpose</b>: Encapsulate the information provided with descriptor events.
37  * This is used as the argument to any event raised by the descriptor.
38  * Events can be registered for, through two methods, the first is by providing a method
39  * to be called on the object that a paticular operation is being performed on.
40  * The second is by registering an event listener to be notified when any event occurs
41  * for that descriptor. The second method is more similar to the java beans event model
42  * and requires the registered listener to implement the DescriptorEventListener interface.
43  *
44  * @see DescriptorEventManager
45  * @see DescriptorEventListener
46  * @see DescriptorEventAdapter
47  */

48 public class DescriptorEvent extends EventObject {
49     /**
50      * The code of the descriptor event being raised.
51      * This is an integer constant value from DescriptorEventManager.
52      */

53     protected int eventCode;
54
55     /** The query causing the event. */
56     protected DatabaseQuery query;
57
58     /** Optionally a database row may be provided on some events, (such as aboutToUpdate). */
59     protected Record record;
60     protected ClassDescriptor descriptor;
61
62     /**
63      * The source object represents the object the event is being raised on,
64      * some events also require a second object, for example the original object in a postClone.
65      */

66     protected Object JavaDoc originalObject;
67
68     /** For the post merge event it is possible that there has been a change set generated.
69      * This attribute will store the changeSet for the object just merged
70      */

71     protected ObjectChangeSet changeSet;
72
73     /** The session in which the event is raised. */
74     protected AbstractSession session;
75
76     /** Event names for toString() */
77     protected static String JavaDoc[] eventNames;
78
79     /** Initialize the values */
80     static {
81         eventNames = new String JavaDoc[DescriptorEventManager.NumberOfEvents];
82
83         eventNames[DescriptorEventManager.PreWriteEvent] = "PreWriteEvent";
84         eventNames[DescriptorEventManager.PostWriteEvent] = "PostWriteEvent";
85         eventNames[DescriptorEventManager.PreDeleteEvent] = "PostDeleteEvent";
86         eventNames[DescriptorEventManager.PostDeleteEvent] = "PostDeleteEvent";
87         eventNames[DescriptorEventManager.PreInsertEvent] = "PreInsertEvent";
88         eventNames[DescriptorEventManager.PostInsertEvent] = "PostInsertEvent";
89         eventNames[DescriptorEventManager.PreUpdateEvent] = "PreUpdateEvent";
90         eventNames[DescriptorEventManager.PostUpdateEvent] = "PostUpdateEvent";
91         eventNames[DescriptorEventManager.PostBuildEvent] = "PostBuildEvent";
92         eventNames[DescriptorEventManager.PostRefreshEvent] = "PostRefreshEvent";
93         eventNames[DescriptorEventManager.PostCloneEvent] = "PostCloneEvent";
94         eventNames[DescriptorEventManager.PostMergeEvent] = "PostMergeEvent";
95         eventNames[DescriptorEventManager.AboutToInsertEvent] = "AboutToInsertEvent";
96         eventNames[DescriptorEventManager.AboutToUpdateEvent] = "AboutToUpdateEvent";
97     }
98
99     /**
100      * PUBLIC:
101      * Most events are trigger from queries, so this is a helper method.
102      */

103     public DescriptorEvent(int eventCode, ObjectLevelModifyQuery query) {
104         this(query.getObject());
105         this.query = query;
106         this.eventCode = eventCode;
107         this.session = query.getSession();
108         this.descriptor = query.getDescriptor();
109     }
110
111     /**
112      * PUBLIC:
113      * All events require a source object.
114      */

115     public DescriptorEvent(Object JavaDoc sourceObject) {
116         super(sourceObject);
117     }
118
119     /**
120      * PUBLIC:
121      * Re-populate the database row with the values from the source object based upon the
122      * attribute's mapping. Provided as a helper method for modifying the row during event
123      * handling.
124      */

125     public void applyAttributeValuesIntoRow(String JavaDoc attributeName) {
126         ClassDescriptor descriptor = getSession().getDescriptor(getSource());
127         DatabaseMapping mapping = descriptor.getMappingForAttributeName(attributeName);
128
129         if (mapping == null) {
130             throw ValidationException.missingMappingForAttribute(descriptor, attributeName, this.toString());
131         }
132         if (getRecord() != null) {
133             mapping.writeFromObjectIntoRow(getSource(), (AbstractRecord)getRecord(), getSession());
134         }
135     }
136
137     /**
138      * PUBLIC:
139      * Returns the Object changeSet if available
140      */

141     public ObjectChangeSet getChangeSet() {
142         return changeSet;
143     }
144
145     /**
146      * PUBLIC:
147      * The source descriptor of the event.
148      */

149     public ClassDescriptor getDescriptor() {
150         return descriptor;
151     }
152
153     /**
154      * PUBLIC:
155      * The source descriptor of the event.
156      */

157     public ClassDescriptor getClassDescriptor() {
158         ClassDescriptor desc = getDescriptor();
159         if (desc instanceof ClassDescriptor) {
160             return (ClassDescriptor)desc;
161         } else {
162             throw ValidationException.cannotCastToClass(desc, desc.getClass(), ClassDescriptor.class);
163         }
164     }
165
166     /**
167      * PUBLIC:
168      * The code of the descriptor event being raised.
169      * This is an integer constant value from DescriptorEventManager.
170      */

171     public int getEventCode() {
172         return eventCode;
173     }
174
175     /**
176      * PUBLIC:
177      * Synanym for source.
178      */

179     public Object JavaDoc getObject() {
180         return getSource();
181     }
182
183     /**
184      * PUBLIC:
185      * The source object represents the object the event is being raised on,
186      * some events also require a second object, for example the original object in a postClone.
187      *
188      * @see EventObject#getSource()
189      */

190     public Object JavaDoc getOriginalObject() {
191         // Compute the original for unit of work writes.
192
if ((originalObject == null) && getSession().isUnitOfWork() && (getQuery() != null) && (getQuery().isObjectLevelModifyQuery())) {
193             setOriginalObject(((UnitOfWorkImpl)getSession()).getOriginalVersionOfObject(getSource()));
194         }
195         return originalObject;
196     }
197
198     /**
199      * PUBLIC:
200      * The query causing the event.
201      */

202     public DatabaseQuery getQuery() {
203         return query;
204     }
205
206     /**
207      * PUBLIC:
208      * Return the record that is associated with some events,
209      * such as postBuild, and aboutToUpdate.
210      */

211     public Record getRecord() {
212         return record;
213     }
214
215     /**
216      * PUBLIC:
217      * The session in which the event is raised.
218      */

219     public AbstractSession getSession() {
220         return session;
221     }
222
223     /**
224      * INTERNAL:
225      * Sets the Change set in the event if the change Set is available
226      */

227     public void setChangeSet(ObjectChangeSet newChangeSet) {
228         changeSet = newChangeSet;
229     }
230
231     /**
232      * INTERNAL:
233      * The source descriptor of the event.
234      */

235     public void setDescriptor(ClassDescriptor descriptor) {
236         this.descriptor = descriptor;
237     }
238
239     /**
240      * INTERNAL:
241      * The code of the descriptor event being raised.
242      * This is an integer constant value from DescriptorEventManager.
243      */

244     public void setEventCode(int eventCode) {
245         this.eventCode = eventCode;
246     }
247
248     /**
249      * INTERNAL:
250      * The source object represents the object the event is being raised on,
251      * some events also require a second object, for example the original object in a postClone.
252      */

253     public void setOriginalObject(Object JavaDoc originalObject) {
254         this.originalObject = originalObject;
255     }
256
257     /**
258      * INTERNAL:
259      * The query causing the event.
260      */

261     public void setQuery(DatabaseQuery query) {
262         this.query = query;
263     }
264
265     /**
266      * INTERNAL:
267      * Optionally a database row may be provided on some events, (such as aboutToUpdate).
268      */

269     public void setRecord(Record record) {
270         this.record = record;
271     }
272
273     /**
274      * INTERNAL:
275      * The session in which the event is raised.
276      */

277     public void setSession(AbstractSession session) {
278         this.session = session;
279     }
280
281     /**
282      * INTERNAL:
283      */

284     public String JavaDoc toString() {
285         String JavaDoc eventName = "UnkownEvent";
286
287         if ((getEventCode() >= 0) && (getEventCode() < DescriptorEventManager.NumberOfEvents)) {
288             eventName = eventNames[getEventCode()];
289         }
290
291         return eventName + "(" + getSource().getClass() + ")";
292     }
293
294     /**
295      * ADVANCED:
296      * Use this method when updating object attribute values, with unmapped objects Integer, String or others. in events to ensure that all
297      * required objects are updated. TopLink will automaticaly update all objects and changesets
298      * envolved. TopLink will update the field, in the row, to have the new value for the field
299      * that this mapping maps to.
300      */

301     public void updateAttributeWithObject(String JavaDoc attributeName, Object JavaDoc value) {
302         DatabaseMapping mapping = this.query.getDescriptor().getMappingForAttributeName(attributeName);
303         if (mapping == null) {
304             throw DescriptorException.mappingForAttributeIsMissing(attributeName, getDescriptor());
305         }
306
307         Object JavaDoc clone = this.getObject();
308         Object JavaDoc cloneValue = value;
309         Object JavaDoc original = null;
310
311         //only set the original object if we need to update it, ie before the merge takes place
312
if ((this.eventCode == DescriptorEventManager.PostCloneEvent) || (this.eventCode == DescriptorEventManager.PostMergeEvent)) {
313             original = this.getOriginalObject();
314         }
315         Object JavaDoc originalValue = value;
316         ObjectChangeSet eventChangeSet = this.getChangeSet();
317         Object JavaDoc valueForChangeSet = value;
318
319         if ((this.query != null) && this.query.isObjectLevelModifyQuery()) {
320             clone = ((ObjectLevelModifyQuery)this.query).getObject();
321             eventChangeSet = ((ObjectLevelModifyQuery)this.query).getObjectChangeSet();
322         }
323         ClassDescriptor descriptor = getSession().getDescriptor(value.getClass());
324
325         if (descriptor != null) {
326             //There is a descriptor for the value being passed in so we must be carefull
327
// to convert the value before assigning it.
328
if (eventChangeSet != null) {
329                 valueForChangeSet = descriptor.getObjectBuilder().createObjectChangeSet(value, (UnitOfWorkChangeSet)eventChangeSet.getUOWChangeSet(), getSession());
330             }
331             if (original != null) {
332                 // must be a unitOfWork because only the postMerge, and postClone events set this attribute
333
originalValue = ((UnitOfWorkImpl)getSession()).getOriginalVersionOfObject(value);
334             }
335         }
336         if (clone != null) {
337             mapping.setRealAttributeValueInObject(clone, cloneValue);
338         }
339         if (original != null) {
340             mapping.setRealAttributeValueInObject(original, originalValue);
341         }
342         if (getRecord() != null) {
343             AbstractRecord tempRow = getDescriptor().getObjectBuilder().createRecord();
344
345             // pass in temp Row because most mappings use row.add() not row.put() for
346
// perf reasons. We are using writeFromObjectIntoRow in order to support
347
// a large number of types.
348
mapping.writeFromObjectIntoRow(clone, tempRow, getSession());
349             ((AbstractRecord)getRecord()).mergeFrom(tempRow);
350         }
351         if (eventChangeSet != null) {
352             eventChangeSet.removeChange(attributeName);
353             eventChangeSet.addChange(mapping.compareForChange(clone, ((UnitOfWorkImpl)getSession()).getBackupClone(clone), eventChangeSet, getSession()));
354         }
355     }
356
357     /**
358     * ADVANCED:
359     * Use this method when updating object attribute values, with unmapped objects Integer, String or others. in events to ensure that all
360     * required objects are updated. TopLink will automaticaly update all objects and changesets
361     * envolved. TopLink will update the field, in the row, to have the new value for the field
362     * that this mapping maps to. If the attribute being updated is within an aggregate then pass the updated aggregate
363     * and the attribute of the aggregate mapping into this method.
364     */

365     public void updateAttributeAddObjectToCollection(String JavaDoc attributeName, Object JavaDoc mapKey, Object JavaDoc value) {
366         DatabaseMapping mapping = this.query.getDescriptor().getMappingForAttributeName(attributeName);
367         if (mapping == null) {
368             throw DescriptorException.mappingForAttributeIsMissing(attributeName, getDescriptor());
369         }
370
371         Object JavaDoc clone = this.getObject();
372         Object JavaDoc cloneValue = value;
373         Object JavaDoc original = null;
374
375         //only set the original object if we need to update it, ie before the merge takes place
376
if ((this.eventCode == DescriptorEventManager.PostCloneEvent) || (this.eventCode == DescriptorEventManager.PostMergeEvent)) {
377             original = this.getOriginalObject();
378         }
379         Object JavaDoc originalValue = value;
380         ObjectChangeSet eventChangeSet = this.getChangeSet();
381         Object JavaDoc valueForChangeSet = value;
382
383         if ((this.query != null) && this.query.isObjectLevelModifyQuery()) {
384             clone = ((ObjectLevelModifyQuery)this.query).getObject();
385             eventChangeSet = ((ObjectLevelModifyQuery)this.query).getObjectChangeSet();
386         }
387         ClassDescriptor descriptor = getSession().getDescriptor(value.getClass());
388
389         if (descriptor != null) {
390             //There is a descriptor for the value being passed in so we must be carefull
391
// to convert the value before assigning it.
392
if (eventChangeSet != null) {
393                 valueForChangeSet = descriptor.getObjectBuilder().createObjectChangeSet(value, (UnitOfWorkChangeSet)eventChangeSet.getUOWChangeSet(), getSession());
394             }
395             if (original != null) {
396                 // must be a unitOfWork because only the postMerge, and postClone events set this attribute
397
originalValue = ((UnitOfWorkImpl)getSession()).getOriginalVersionOfObject(value);
398             }
399         }
400
401         if (clone != null) {
402             Object JavaDoc collection = mapping.getRealCollectionAttributeValueFromObject(clone, getSession());
403             mapping.getContainerPolicy().addInto(mapKey, cloneValue, collection, getSession());
404         }
405         if (original != null) {
406             Object JavaDoc collection = mapping.getRealCollectionAttributeValueFromObject(original, getSession());
407             mapping.getContainerPolicy().addInto(mapKey, originalValue, collection, getSession());
408         }
409         if (getRecord() != null) {
410             AbstractRecord tempRow = getDescriptor().getObjectBuilder().createRecord();
411
412             // pass in temp Row because most mappings use row.add() not row.put() for
413
// perf reasons. We are using writeFromObjectIntoRow in order to support
414
// a large number of types.
415
mapping.writeFromObjectIntoRow(clone, tempRow, getSession());
416             ((AbstractRecord)getRecord()).mergeFrom(tempRow);
417         }
418         if (eventChangeSet != null) {
419             mapping.simpleAddToCollectionChangeRecord(mapKey, valueForChangeSet, eventChangeSet, getSession());
420         }
421     }
422
423     /**
424     * ADVANCED:
425     * Use this method when updating object attribute values, with unmapped objects Integer, String or others. in events to ensure that all
426     * required objects are updated. TopLink will automaticaly update all objects and changesets
427     * envolved. TopLink will update the field, in the row, to have the new value for the field
428     * that this mapping maps to.
429     */

430     public void updateAttributeRemoveObjectFromCollection(String JavaDoc attributeName, Object JavaDoc mapKey, Object JavaDoc value) {
431         DatabaseMapping mapping = this.query.getDescriptor().getMappingForAttributeName(attributeName);
432         if (mapping == null) {
433             throw DescriptorException.mappingForAttributeIsMissing(attributeName, getDescriptor());
434         }
435
436         Object JavaDoc clone = this.getObject();
437         Object JavaDoc cloneValue = value;
438         Object JavaDoc original = null;
439
440         //only set the original object if we need to update it, ie before the merge takes place
441
if ((this.eventCode == DescriptorEventManager.PostCloneEvent) || (this.eventCode == DescriptorEventManager.PostMergeEvent)) {
442             original = this.getOriginalObject();
443         }
444         Object JavaDoc originalValue = value;
445         ObjectChangeSet eventChangeSet = this.getChangeSet();
446         Object JavaDoc valueForChangeSet = value;
447
448         if ((this.query != null) && this.query.isObjectLevelModifyQuery()) {
449             clone = ((ObjectLevelModifyQuery)this.query).getObject();
450             eventChangeSet = ((ObjectLevelModifyQuery)this.query).getObjectChangeSet();
451         }
452         ClassDescriptor descriptor = getSession().getDescriptor(value.getClass());
453
454         if (descriptor != null) {
455             //There is a descriptor for the value being passed in so we must be carefull
456
// to convert the value before assigning it.
457
if (eventChangeSet != null) {
458                 valueForChangeSet = descriptor.getObjectBuilder().createObjectChangeSet(value, (UnitOfWorkChangeSet)eventChangeSet.getUOWChangeSet(), getSession());
459             }
460             if (original != null) {
461                 // must be a unitOfWork because only the postMerge, and postClone events set this attribute
462
originalValue = ((UnitOfWorkImpl)getSession()).getOriginalVersionOfObject(value);
463             }
464         }
465         if (clone != null) {
466             Object JavaDoc collection = mapping.getRealCollectionAttributeValueFromObject(clone, getSession());
467             mapping.getContainerPolicy().removeFrom(mapKey, cloneValue, collection, getSession());
468         }
469         if (original != null) {
470             Object JavaDoc collection = mapping.getRealCollectionAttributeValueFromObject(original, getSession());
471             mapping.getContainerPolicy().removeFrom(mapKey, originalValue, collection, getSession());
472         }
473         if (getRecord() != null) {
474             AbstractRecord tempRow = getDescriptor().getObjectBuilder().createRecord();
475
476             // pass in temp Row because most mappings use row.add() not row.put() for
477
// perf reasons. We are using writeFromObjectIntoRow in order to support
478
// a large number of types.
479
mapping.writeFromObjectIntoRow(clone, tempRow, getSession());
480             ((AbstractRecord)getRecord()).mergeFrom(tempRow);
481         }
482         if (eventChangeSet != null) {
483             mapping.simpleRemoveFromCollectionChangeRecord(mapKey, valueForChangeSet, eventChangeSet, getSession());
484         }
485     }
486 }
487
Popular Tags