KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > jac > aspects > persistence > PersistenceWrapper


1 /*
2   Copyright (C) 2002-2003 Laurent Martelli <laurent@aopsys.com>
3
4   This program is free software; you can redistribute it and/or modify
5   it under the terms of the GNU Lesser General Public License as
6   published by the Free Software Foundation; either version 2 of the
7   License, or (at your option) any later version.
8
9   This program is distributed in the hope that it will be useful,
10   but WITHOUT ANY WARRANTY; without even the implied warranty of
11   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12   GNU Lesser General Public License for more details.
13
14   You should have received a copy of the GNU Lesser General Public License
15   along with this program; if not, write to the Free Software
16   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */

17
18 package org.objectweb.jac.aspects.persistence;
19
20 import java.util.Arrays JavaDoc;
21 import java.util.Collection JavaDoc;
22 import java.util.HashMap JavaDoc;
23 import java.util.HashSet JavaDoc;
24 import java.util.Iterator JavaDoc;
25 import java.util.List JavaDoc;
26 import java.util.Map JavaDoc;
27 import java.util.Set JavaDoc;
28 import java.util.Vector JavaDoc;
29 import org.aopalliance.intercept.ConstructorInvocation;
30 import org.aopalliance.intercept.MethodInvocation;
31 import org.apache.log4j.Logger;
32 import org.objectweb.jac.core.AspectComponent;
33 import org.objectweb.jac.core.Interaction;
34 import org.objectweb.jac.core.NameRepository;
35 import org.objectweb.jac.core.Wrappee;
36 import org.objectweb.jac.core.Wrapping;
37 import org.objectweb.jac.core.rtti.ClassItem;
38 import org.objectweb.jac.core.rtti.CollectionItem;
39 import org.objectweb.jac.core.rtti.FieldItem;
40 import org.objectweb.jac.core.rtti.MethodItem;
41 import org.objectweb.jac.util.ExtArrays;
42
43 /**
44  * This wrapper defines persistence extensions for objects that a
45  * defined persitent by a persistent aspect component. */

46
47 public class PersistenceWrapper extends AbstractPersistenceWrapper {
48     static final Logger loggerRef = Logger.getLogger("persistence.ref");
49     static final Logger loggerCol = Logger.getLogger("persistence.col");
50     static final Logger loggerWrap = Logger.getLogger("persistence.wrap");
51
52     public final static String JavaDoc[] toWrapForLists =
53     new String JavaDoc[] {
54         "add",
55         "addAll",
56         "clear",
57         "contains",
58         "get",
59         "remove",
60         "removeRange",
61         "set",
62         "size",
63         "indexOf",
64         "lastIndexOf",
65         "isEmpty",
66         // -- preloads --
67
"toArray", "iterator", "clone" /*"equals"*/
68     };
69
70     public final static String JavaDoc[] toWrapForSets =
71     new String JavaDoc[] { "add", "clear", "contains", "remove", "size", "isEmpty",
72                    // -- preloads --
73
"toArray", "iterator", "clone" /*"equals"*/
74     };
75
76     public final static String JavaDoc[] toWrapForMaps =
77     new String JavaDoc[] {
78         "clear",
79         "isEmpty",
80         "size",
81         "containsKey",
82         "containsValue",
83         "get",
84         "put",
85         "remove",
86         // -- preloads --
87
"keySet", "entrySet", "values", "clone" /*"equals"*/
88     };
89
90     public PersistenceWrapper(AspectComponent ac) {
91         super(ac);
92     }
93
94     boolean doStatics = false;
95
96     public PersistenceWrapper(AspectComponent ac, Boolean JavaDoc doStatics) {
97         super(ac);
98         this.doStatics = doStatics.booleanValue();
99     }
100
101     //public static final String ATTR_ADDED = "persistence.added";
102

103     // names of already loaded collections
104
private HashSet JavaDoc loadedVectors = new HashSet JavaDoc();
105     // names of already loaded references
106
private HashSet JavaDoc loadedReferences = new HashSet JavaDoc();
107     // oids of not yet loaded references (FieldItem -> oid)
108
private HashMap JavaDoc notloadedReferences = new HashMap JavaDoc();
109
110     static boolean isWrapped(Wrappee wrappee, FieldItem field) {
111         Object JavaDoc value = field.get(wrappee);
112         if (value instanceof Wrappee
113             && Wrapping.isExtendedBy(
114                 (Wrappee) value,
115                 null,
116                 CollectionWrapper.class)) {
117             logger.debug(field + " is wrapped");
118             return true;
119         } else {
120             logger.debug(field + " is not wrapped");
121             return false;
122         }
123     }
124
125     /**
126      * This wrapping method is called on static objects constructors as
127      * defined by the pointcut of <code>PersistenceAC</code>.
128      *
129      * @see PersistenceAC#registerStatics
130      */

131     public Object JavaDoc handleStatic(Interaction interaction) {
132         logger.debug("handle static "+interaction.wrappee.getClass().getName());
133         Object JavaDoc ret = interaction.proceed();
134         //wrap(null,true);
135
try {
136             String JavaDoc name = NameRepository.get().getName(interaction.wrappee);
137             ClassItem cli = cr.getClass(interaction.wrappee);
138             Storage storage = getStorage(cli);
139             OID oid = storage.getOIDFromName(name);
140             if (oid == null) {
141                 oid = storage.createObject(cli.getName());
142                 setOID(interaction.wrappee, oid);
143                 storage.bindOIDToName(oid, name);
144                 logger.debug(interaction.wrappee.getClass().getName() + " isNew");
145                 CollectionItem[] array = new CollectionItem[0];
146                 wrapCollections(interaction.wrappee, oid, true);
147                 initAllFields(interaction.wrappee, oid);
148             } else {
149                 setOID(interaction.wrappee, oid);
150                 // Call loadAllFields before wrapCollections so that it
151
// preloads the OID of collections
152
loadAllFields(interaction.wrappee, oid);
153                 wrapCollections(interaction.wrappee, oid, false);
154             }
155         } catch (Exception JavaDoc e) {
156             logger.error("handleStatic "+interaction,e);
157         }
158         return ret;
159     }
160
161     /**
162      * Makes an object persistent if it is not already. Is is assigned
163      * an OID, and its members are saved in the storage.
164      * @param wrappee the object to make persistent
165      */

166     public OID makePersistent(Wrappee wrappee) throws Exception JavaDoc {
167         OID oid = null;
168             
169         logger.debug("makePersistent(" + wrappee + ")");
170         oid = getOID(wrappee);
171         if (oid!=null) {
172             logger.debug(wrappee + " is already persistent");
173         } else {
174             ClassItem cli = cr.getClass(wrappee);
175             Storage storage = getStorage(cli);
176             oid = storage.createObject(cli.getName());
177             setOID(wrappee, oid);
178             storage.bindOIDToName(
179                 oid,
180                 NameRepository.get().getName(wrappee));
181             logger.debug(wrappee + " isNew");
182
183             // Initialize loadedVectors and loadedReferences.
184
// It's important to do this as early as possible, in case
185
// someone accesses them.
186

187             FieldItem[] refs = cli.getReferences();
188             for (int i = 0; i < refs.length; i++) {
189                 loadedReferences.add(refs[i].getName());
190             }
191             CollectionItem[] colls = cli.getCollections();
192             for (int i = 0; i < colls.length; i++) {
193                 loadedVectors.add(colls[i].getName());
194             }
195
196             wrapCollections(wrappee, oid, true);
197             initAllFields(wrappee, oid);
198         }
199
200         return oid;
201     }
202
203     /**
204      * Load all the fields of an object from the storage and initialize
205      * the object.
206      *
207      * @param wrappee the object
208      */

209
210     public void loadAllFields(Wrappee wrappee, OID oid) throws Exception JavaDoc {
211         logger.debug("loadAllFields(" + oid + ")");
212         String JavaDoc lClassID = wrappee.getClass().getName();
213
214         // Load all fields from the storage
215
ClassItem cli = cr.getClass(lClassID);
216
217         // this should be faster because only one call to the storage is done
218
FieldItem[] fields = cli.getFields();
219         if (fields.length > 0) {
220             Storage storage = oid.getStorage();
221             StorageField[] values = storage.getFields(oid, cli, fields);
222             for (int i = 0; i < values.length; i++) {
223                 if (values[i] != null) {
224                     FieldItem field = values[i].fieldID;
225                     if (field.getActualField() != null) {
226                         try {
227                             boolean force =
228                                 PersistenceAC.isFieldPreloaded(field);
229                             if (field.isPrimitive()
230                                 && values[i].value != null) {
231                                 // TODO: preload for primitive fields here
232
if (field.setConvert(wrappee, values[i].value)) {
233                                     logger.warn(oid+"."+field.getName()+
234                                                 " value converted from "+values[i].value.getClass()+
235                                                 " to "+field.getType());
236                                     storage.updateField(oid, field, field.get(wrappee));
237                                 }
238                             } else if (field.isReference()) {
239                                 if (!field.hasAccessingMethods()) {
240                                     // load a reference if it has no getter
241
getReference(wrappee, oid, field);
242                                 } else {
243                                     // test if reference must be loaded here
244
// instead of being loaded when accessed
245
if (force) {
246                                         getReference(wrappee, oid, field);
247                                     } else {
248                                         logger.debug("storing OID for reference "
249                                                      + field
250                                                      + "="
251                                                      + values[i].value);
252                                         notloadedReferences.put(
253                                             field,
254                                             values[i].value);
255                                     }
256                                 }
257                             } else if (field instanceof CollectionItem) {
258                                 if (!((CollectionItem) field)
259                                     .isWrappable(wrappee)) {
260                                     logger.debug("loadAllFields -> invoking getCollection for "
261                                                  + field);
262                                     Wrapping.invokeRoleMethod(
263                                         wrappee,
264                                         "getCollection",
265                                         new Object JavaDoc[] { field });
266                                 } else {
267                                     // test if collection must be loaded here
268
// instead of being loaded when accessed
269
if (force) {
270                                         getCollection(
271                                             wrappee, oid,
272                                             (CollectionItem) field);
273                                     } else {
274                                         logger.debug("storing OID for collection "
275                                                      + field
276                                                      + "="
277                                                      + values[i].value);
278                                         notloadedReferences.put(
279                                             field,
280                                             values[i].value);
281                                     }
282                                 }
283                             }
284                         } catch (Exception JavaDoc e) {
285                             logger.error(
286                                 "Failed to load field "+ field.getLongName()
287                                 + " for " + oid,
288                                 e);
289                         }
290                     }
291                 }
292             }
293         }
294     }
295
296     /**
297      * This role method wraps all the collection of the current wrappee
298      * so that they will trigger the needed loads from the storage when
299      * they are accessed.
300      *
301      * @param wrappee the object whose collections to wrap
302      * @param oid the oid of wrappee
303      * @param isNew must true if the object is newly created, false if
304      * loaded from storage
305      */

306     public void wrapCollections(Wrappee wrappee, OID oid, boolean isNew) {
307         logger.debug("wrapCollections("
308                      + wrappee.getClass().getName()
309                      + "), isNew=" + isNew);
310         // Wrap collections
311
try {
312             ClassItem cli = cr.getClass(wrappee);
313             Vector JavaDoc collectionsToInit = new Vector JavaDoc();
314             CollectionItem[] collections = cli.getCollections();
315             Storage storage = oid.getStorage();
316             for (int i = 0; i < collections.length; i++) {
317                 CollectionItem collection = collections[i];
318                 if (collection.isTransient())
319                     continue;
320                 Object JavaDoc coll_value = collections[i].get(wrappee);
321                 Class JavaDoc collType = collections[i].getType();
322                 if (coll_value == null) {
323                     logger.warn(
324                         "uninitialized collection " +collections[i].getLongName()+
325                         ". Do you have a constructor with no parameters?");
326                     // uninitialized field
327
if (collType.isArray()) {
328                         coll_value =
329                             java.lang.reflect.Array.newInstance(
330                                 collType.getComponentType(),
331                                 0);
332                     } else {
333                         try {
334                             // This will fail if the declared type of the
335
// attribute is an interface
336
if (!collType.isInterface()) {
337                                 coll_value = collType.newInstance();
338                             }
339                         } catch (Exception JavaDoc e) {
340                             logger.error("wrapCollections "+wrappee+"("+oid+")",e);
341                         }
342                     }
343                     collections[i].set(wrappee, coll_value);
344                 }
345                 Class JavaDoc actualCollType = coll_value.getClass();
346                 if (//isWrapped(collections[i]) ||
347
actualCollType
348                     == org.objectweb.jac.lib.java.util.Vector.class
349                     || actualCollType
350                         == org.objectweb.jac.lib.java.util.HashMap.class
351                     || actualCollType
352                         == org.objectweb.jac.lib.java.util.Hashtable.class
353                     || actualCollType
354                         == org.objectweb.jac.lib.java.util.HashSet.class) {
355                     OID coll_oid;
356                     if (isNew) {
357                         coll_oid =
358                             storage.createObject(
359                                 collections[i].getType().getName());
360                     } else {
361                         coll_oid =
362                             (OID) notloadedReferences.get(collections[i]);
363                         if (coll_oid == null)
364                             coll_oid =
365                                 (OID) storage.getField(
366                                     oid,
367                                     collections[i]);
368                         else
369                             notloadedReferences.remove(collections[i]);
370                         // classes may change after objects were created and
371
// made persistent
372
if (coll_oid == null) {
373                             coll_oid = initCollection(wrappee, oid, collections[i]);
374                             logger.debug(
375                                       "OID of new collection "+collections[i]+": "+coll_oid);
376                         }
377                     }
378
379                     logger.debug(collections[i] + " -> " + coll_oid);
380
381                     boolean preloaded =
382                         PersistenceAC.isFieldPreloaded(collections[i]);
383                     String JavaDoc[] toWrap;
384                     CollectionWrapper wrapper;
385                     if (collections[i].isList()) {
386                         // lists
387
logger.debug(
388                             "wrapping List "+ collections[i].getName()
389                             + " " + System.identityHashCode(coll_value));
390                         wrapper =
391                             new ListWrapper(getAspectComponent(),
392                                             wrappee,
393                                             collection,
394                                             preloaded);
395                         toWrap = toWrapForLists;
396                     } else if (collections[i].isSet()) {
397                         // sets
398
logger.debug("wrapping Set " + collections[i].getName());
399                         wrapper =
400                             new SetWrapper(getAspectComponent(),
401                                            wrappee,
402                                            collection,
403                                            preloaded);
404                         toWrap = toWrapForSets;
405                     } else if (collections[i].isMap()) {
406                         // maps
407
logger.debug("wrapping Map " + collections[i].getName());
408                         wrapper =
409                             new MapWrapper(getAspectComponent(),
410                                            wrappee,
411                                            collection,
412                                            preloaded);
413                         toWrap = toWrapForMaps;
414                     } else {
415                         throw new Exception JavaDoc("unsuported collection type");
416                     }
417
418                     Wrappee coll = (Wrappee) coll_value;
419                     setOID(coll, coll_oid);
420                     if (coll != null) {
421                         Wrapping.wrap(coll, null, wrapper);
422                         Wrapping.wrap(coll, wrapper, toWrap);
423                         //Wrapping.wrap(map,wrapper,"memorizeUseDate",preloads);
424
} else {
425                         logger.warn(
426                             "Collection "
427                                 + cli.getName() + "." + collections[i].getName()
428                                 + " is null, not wrapped");
429                     }
430                 }
431             }
432         } catch (Exception JavaDoc e) {
433             logger.error("wrapCollections "+wrappee+"("+oid+")",e);
434         }
435     }
436
437     /**
438      * This wrapping method apply the persistence aspect for a given
439      * call on a persistent object.
440      *
441      * <p>It uses the RTTI aspect to determine the accessed and written
442      * field types.<p>
443      *
444      * Default behavior is:<p>
445      *
446      * <ul>
447      * <li>get the fields that are accessed for reading by this wrapped
448      * method
449      * <li>if the field is a collection, get the collection from the
450      * storage
451      * <li>if the field is a reference, get the referenced object from
452      * the storage
453      * <li>proceed the wrappee (and other wrappers if needed)
454      * <li>get the fields that were written by this wrapped method
455      * <li>if the field is a collection, update the storage depending
456      * on the wrapped method type (adder or remover)
457      * <li>if the field is a reference, update the storage to change
458      * the referenced object
459      * <li> if the field is a simple field, just update the storage
460      * with its value.
461      * </ul>
462      *
463      * @return the value returned by the wrapped method
464      *
465      * @see org.objectweb.jac.core.rtti.MethodItem#getAccessedFields()
466      * @see #getCollection(Wrappee,OID,CollectionItem)
467      * @see #getReference(Wrappee,OID,FieldItem)
468      * @see #addToCollection(Interaction,OID,CollectionItem,Object)
469      * @see #removeFromCollection(Interaction,OID,CollectionItem,Object)
470      * @see #setReference(Wrappee,OID,FieldItem,Wrappee)
471      * @see #setField(Wrappee,OID,FieldItem)
472      * @see org.objectweb.jac.core.rtti.MethodItem#getWrittenFields()
473      * @see org.objectweb.jac.core.rtti
474      */

475     public Object JavaDoc applyPersistence(Interaction interaction) throws Exception JavaDoc {
476         if (interaction.method.isStatic()) {
477             return proceed(interaction);
478         }
479         OID oid = getOID(interaction.wrappee);
480         logger.debug(
481             "applyPersistence on "
482                 + oid + "(" + interaction.wrappee + ")."
483                 + interaction.method);
484         MethodItem method = (MethodItem) interaction.method;
485         FieldItem[] fields;
486
487         // the object may be wrapped but not persistent yet
488
if (oid != null) {
489
490             ClassItem cli =
491                 cr.getClass(interaction.wrappee.getClass());
492             // preload accessed fields and collections
493
fields = method.getAccessedFields();
494             for (int i = 0; fields != null && i < fields.length; i++) {
495                 FieldItem field = fields[i];
496
497                 if (!field.isTransient() && !field.isFinal()) {
498                     if (field instanceof CollectionItem
499                         && !isWrapped(interaction.wrappee, field)) {
500                         getCollection(
501                             interaction.wrappee, oid,
502                             (CollectionItem) field);
503                     } else if (field.isReference()) {
504                         getReference(interaction.wrappee, oid, field);
505                     }
506                 }
507             }
508         }
509
510         Object JavaDoc result = proceed(interaction);
511
512         oid = getOID(interaction.wrappee);
513         if (oid != null) {
514
515             // save written fields
516
fields = method.getWrittenFields();
517             for (int i = 0; fields!=null && i<fields.length; i++) {
518                 FieldItem field = fields[i];
519                 if (!field.isTransient()) {
520                     logger.debug("Save written field in "
521                             + interaction.method + " : "
522                             + field.getName());
523                     if (field.isReference()) {
524                         setReference(
525                             interaction.wrappee, oid,
526                             field,
527                             (Wrappee) field.get(interaction.wrappee));
528                     } else if (field instanceof CollectionItem) {
529                         // Nothing to do if the collection is wrapped
530
// BUT THE COLLECTION MUST BE SAVED IN THE CASE OF ARRAYS
531
// storage.updateCollection(collection);
532
CollectionItem collection = (CollectionItem) field;
533                         if (collection.isArray()
534                             && ((MethodItem) interaction.method)
535                                 .getCollectionIndexArgument()
536                                 != -1) {
537                             updateCollection(
538                                 collection,
539                                 ((MethodItem) interaction.method)
540                                     .getCollectionIndexArgument());
541                         }
542                     } else {
543                         setField(interaction.wrappee, oid, field);
544                     }
545                 }
546             }
547
548             // handle added collections (adder)
549
CollectionItem[] collections = method.getAddedCollections();
550             for (int i = 0;
551                 collections != null && i < collections.length;
552                 i++) {
553                 if (!collections[i].isTransient()
554                     && !isWrapped(interaction.wrappee, collections[i])) {
555                     addToCollection(
556                         interaction,
557                         oid,
558                         collections[i],
559                         interaction.args[0]);
560                 }
561             }
562             // handle removed collections (remover)
563
collections = method.getRemovedCollections();
564             for (int i = 0;
565                 collections != null && i < collections.length;
566                 i++) {
567                 if (!collections[i].isTransient()
568                     && !isWrapped(interaction.wrappee, collections[i])) {
569                     removeFromCollection(
570                         interaction,
571                         oid,
572                         collections[i],
573                         interaction.args[0]);
574                 }
575             }
576
577             // UNCOMMENT THIS WHEN UNWRAP WILL BE THREAD-SAFE!!!
578
// unwrap the method if it was only a getter
579
//if ( ! method.hasAddedCollections() &&
580
// ! method.hasRemovedCollections() &&
581
// ! method.hasWrittenFields() )
582
//{
583
// logger.debug("persistence.ref","unwrapping "+getOID()+" "+method);
584
// Wrapping.unwrap(interaction.wrappee,this,"applyPersistence",method);
585
//}
586
}
587         return result;
588     }
589
590     /**
591      * This method loads alls the persistent objects that are contained
592      * in this collection from the storage.
593      *
594      * <p>If the collection has already been loaded from the storage,
595      * do nothing.<p>
596      *
597      * @param collection the collection to load */

598
599     public void getCollection(Wrappee wrappee, OID oid, CollectionItem collection)
600         throws Exception JavaDoc
601     {
602         logger.debug(oid + ".getCollection(" + collection.getName() + ")");
603         if (!loadedVectors.contains(collection.getName())) {
604             String JavaDoc classID = collection.getParent().getName();
605             List JavaDoc vector = null;
606             Map JavaDoc map = null;
607             Storage storage = oid.getStorage();
608             OID cid = storage.getCollectionID(oid, collection);
609             loggerCol.debug("cid=" + cid);
610             if (cid == null) {
611                 // Handle the case of a new collection added in the model
612
initCollection(wrappee, oid, collection);
613             }
614             if (collection.isList() || collection.isArray()) {
615                 vector = storage.getList(oid, collection);
616             } else if (collection.isSet()) {
617                 vector = storage.getSet(oid, collection);
618             } else if (collection.isMap()) {
619                 map = storage.getMap(oid, collection);
620             } else {
621                 logger.error(
622                     "unhandled collection type : " + collection.getType());
623                 logger.error(
624                     "please see the JAC programming guidelines for more details");
625                 //new Exception().printStackTrace();
626
return;
627             }
628
629             collection.clear(wrappee);
630
631             if (collection.isMap()) {
632                 Iterator JavaDoc it = map.entrySet().iterator();
633                 while (it.hasNext()) {
634                     Map.Entry JavaDoc entry = (Map.Entry JavaDoc) it.next();
635                     attrdef(ATTR_ADDED, "true");
636                     collection.add(
637                         wrappee,
638                         normalizeOutput(entry.getValue()),
639                         normalizeOutput(entry.getKey()));
640                     attrdef(ATTR_ADDED, null);
641                 }
642             } else {
643                 for (int i = 0; i < vector.size(); i++) {
644                     attrdef(ATTR_ADDED, "true");
645                     loggerCol.debug(
646                         "adding "
647                             + normalizeOutput(vector.get(i))
648                             + " to " + collection
649                             + "(wrappee=" + wrappee + ")");
650                     collection.add(
651                         wrappee,
652                         normalizeOutput(vector.get(i)),
653                         null);
654                     attrdef(ATTR_ADDED, null);
655                 }
656             }
657             loadedVectors.add(collection.getName());
658         }
659     }
660
661     /**
662      * This method stores the persistent object that is added to the
663      * collection into the storage.<p>
664      *
665      * @param interaction the current interaction
666      * @param oid the oid of the object holding the collection
667      * @param collection the collection to add to
668      * @param value the value to add to the collection
669      *
670      * @see #removeFromCollection(Interaction,OID,CollectionItem,Object)
671      * @see #getCollection(Wrappee,OID,CollectionItem)
672      */

673     protected void addToCollection(Interaction interaction,
674                                    OID oid,
675                                    CollectionItem collection,
676                                    Object JavaDoc value)
677         throws Exception JavaDoc
678     {
679         logger.debug(oid + ".addToCollection: "
680                      + interaction.method + Arrays.asList(interaction.args));
681
682         if (interaction.args.length == 1) {
683             // the method's arguments look correct
684
value = normalizeInput(value);
685             Storage storage = oid.getStorage();
686             OID cid =
687                 storage.getCollectionID(oid,collection);
688             if (collection.isList() || collection.isArray()) {
689                 storage.addToList(cid, value);
690             } else if (collection.isSet()) {
691                 storage.addToSet(cid, value);
692             } else {
693                 logger.error(
694                     "unhandled collection type : " + collection.getType(),new Exception JavaDoc());
695             }
696
697         } else {
698             logger.error("NOT IMPLEMENTED YET !!!");
699             // the method's arguments are weird, so let's diff
700
// storage.updateCollection(collection);
701
}
702     }
703
704     /**
705      * This method delete the persistent object that is removed from
706      * the collection from the storage.<p>
707      *
708      * @param interaction the current interaction
709      * @param oid the oid of the object holding the collection
710      * @param collection the collection to remove from
711      * @param value the value to remove from the collection
712      *
713      * @see #addToCollection(Interaction,OID,CollectionItem,Object)
714      * @see #getCollection(Wrappee,OID,CollectionItem)
715      */

716     protected void removeFromCollection(Interaction interaction,
717                                         OID oid,
718                                         CollectionItem collection,
719                                         Object JavaDoc value)
720         throws Exception JavaDoc
721     {
722         logger.debug(oid + ".removeFromCollection " + interaction.method);
723
724         value = normalizeInput(value);
725         Storage storage = oid.getStorage();
726         OID cid =
727             storage.getCollectionID(oid, collection);
728         if (collection.isList() || collection.isArray()) {
729             storage.removeFromList(cid, value);
730         } else if (collection.isSet()) {
731             storage.removeFromSet(cid, value);
732         } else {
733             logger.error(
734                 "unhandled collection type : " + collection.getType(), new Exception JavaDoc());
735         }
736     }
737
738     /**
739      * Update the element of a collection at a gievn position
740      */

741     public void updateCollection(CollectionItem collection, int position)
742         throws Exception JavaDoc {
743         /*
744         checkOid();
745         logger.debug(
746                   getOID()+".updateCollection: "+method()+Arrays.asList(args()));
747         
748         if (isPersistent())
749         {
750            // the method's arguments look correct
751            value = normalizeInput(value);
752            OID cid = getStorage().getCollectionID(getOID(), collection);
753            if ( collection.isList() || collection.isArray() ) {
754               Object value = collection.get(wrappee(),position);
755               getStorage().setListItem(cid, position, value);
756            } else {
757               logger.error("unhandled collection type : "+collection.getType());
758            }
759         }
760         */

761     }
762
763     /**
764      * This method loads the persistent object that is pointed by the
765      * reference from the storage.<p>
766      *
767      * If the reference has already been loaded from the storage, do
768      * nothing.<p>
769      *
770      * @param reference the reference to load
771      *
772      * @see #setReference(Wrappee,OID,FieldItem,Wrappee)
773      */

774     public void getReference(Wrappee wrappee, OID oid, FieldItem reference)
775         throws Exception JavaDoc
776     {
777         try {
778
779             loggerRef.debug(
780                 oid + "[" + this + "].getReference("
781                 + reference.getName() + ")");
782             //System.out.println("GETREF: "+loadedReferences+" : "+notloadedReferences);
783

784             if (!loadedReferences.contains(reference.getName())) {
785                 OID lOid = (OID) notloadedReferences.get(reference);
786                 if (lOid == null)
787                     lOid = (OID)oid.getStorage().getField(oid,reference);
788                 else
789                     notloadedReferences.remove(reference);
790                 loggerRef.debug(
791                     oid + "." + reference.getName()
792                     + " -> " + lOid
793                     + " (" + wrappee.getClass().getName() + ")");
794                 Object JavaDoc obj = null;
795                 if (lOid != null) {
796                     // What the hell is this ??? It bugs if a reference
797
// is initialized by the default constructor
798
//obj=getAC().getObject(lOid,reference.get(wrappee));
799
obj = getAC().getObject(lOid, null);
800                 }
801                 attrdef(ATTR_ADDED, "true");
802                 try {
803                     reference.set(wrappee, obj);
804                 } catch (IllegalArgumentException JavaDoc illegal) {
805                     // This may happen if the type of the reference has been changed
806
logger.error(
807                         "Incompatible types "
808                         + reference.getType() + " and " + obj);
809                 } finally {
810                     attrdef(ATTR_ADDED, null);
811                 }
812                 loadedReferences.add(reference.getName());
813             } else {
814                 loggerRef.debug(
815                     oid + "." + reference.getName()
816                     + " already loaded");
817             }
818         } catch (Exception JavaDoc e) {
819             logger.error("getReference "+oid+"."+reference.getName(),e);
820         }
821     }
822
823     /**
824      * This method stores the persistent object that is pointed by the
825      * reference into the storage.<p>
826      *
827      * @param reference the reference to store
828      *
829      * @see #getReference(Wrappee,OID,FieldItem)
830      */

831     protected void setReference(Wrappee wrappee,
832                                 OID oid,
833                                 FieldItem reference,
834                                 Wrappee value)
835         throws Exception JavaDoc
836     {
837         if (value != null) {
838             OID valoid = (OID)Wrapping.invokeRoleMethod(
839                 value,
840                 "makePersistent",
841                 ExtArrays.emptyObjectArray);
842             oid.getStorage().updateField(oid,reference,valoid);
843         } else {
844             oid.getStorage().updateField(oid, reference, null);
845         }
846         // We won't need to load the reference now
847
loadedReferences.add(reference.getName());
848         notloadedReferences.remove(reference);
849     }
850
851     /**
852      * This method stores the field into the storage.<p>
853      *
854      * @param field the field to store
855      */

856     protected void setField(Wrappee wrappee, OID oid, FieldItem field)
857         throws Exception JavaDoc
858     {
859         Object JavaDoc value = field.get(wrappee);
860         if (value instanceof Wrappee) {
861             value = Wrapping.invokeRoleMethod(
862                 (Wrappee)value,
863                 "makePersistent",
864                 ExtArrays.emptyObjectArray);
865             
866         }
867         oid.getStorage().updateField(oid,field,value);
868     }
869
870     public void initCollections(Wrappee wrappee, OID oid, CollectionItem[] collections)
871         throws Exception JavaDoc
872     {
873         logger.debug("wrappee = " + wrappee.getClass().getName());
874         logger.debug("collections = " + Arrays.asList(collections));
875         for (int i=0; i<collections.length; i++) {
876             if (!collections[i].isTransient()) {
877                 logger.debug("collections[" + i + "] = " + collections[i]);
878                 initCollection(wrappee, oid, collections[i]);
879             }
880         }
881     }
882
883     OID initCollection(Wrappee wrappee, OID oid, CollectionItem collection)
884         throws Exception JavaDoc
885     {
886         logger.debug("Init collection " + collection.getName());
887         loadedVectors.add(collection.getName());
888         Storage storage = oid.getStorage();
889         OID cid = null;
890         if (collection.isList()
891             || collection.isSet()
892             || collection.isArray())
893         {
894             if (isWrapped(wrappee, collection)) {
895                 cid = getOID((Wrappee) collection.get(wrappee));
896             } else {
897                 cid = storage.createObject(collection.getType().getName());
898                 logger.debug(" new id = " + cid);
899             }
900             storage.setField(oid, collection, cid);
901             Collection JavaDoc coll = collection.getActualCollection(wrappee);
902             logger.debug(" Coll value = " + coll);
903             if (coll == null) {
904                 logger.warn(
905                     "uninitialized collection "+collection.getLongName()+
906                     ". Do you have a constructor with no parameters?");
907                 return cid;
908             }
909             // iterator() is wrapped method, so it triggers the
910
// loading of the collection from the storage, which is bad
911
Iterator JavaDoc it = coll.iterator();
912             while (it.hasNext()) {
913                 Object JavaDoc value = normalizeInput(it.next());
914                 logger.debug(" Coll elt value = " + value);
915                 if (value != null) {
916                     if (collection.isList() || collection.isArray()) {
917                         storage.addToList(cid, value);
918                     } else {
919                         storage.addToSet(cid, value);
920                     }
921                 }
922             }
923         } else if (collection.isMap()) {
924             if (isWrapped(wrappee, collection)) {
925                 cid = getOID((Wrappee) collection.get(wrappee));
926             } else {
927                 cid = storage.createObject(collection.getType().getName());
928             }
929             storage.setField(oid, collection, cid);
930             Map JavaDoc map = (Map JavaDoc) collection.get(wrappee);
931             Set JavaDoc entries = map.entrySet();
932             Iterator JavaDoc it = entries.iterator();
933             while (it.hasNext()) {
934                 Map.Entry JavaDoc entry = (Map.Entry JavaDoc) it.next();
935                 storage.putInMap(
936                     cid,
937                     normalizeInput(entry.getKey()),
938                     normalizeInput(entry.getValue()));
939             }
940         } else {
941             logger.error("unhandled collection type : " + collection.getType(),
942                          new Exception JavaDoc());
943         }
944         logger.debug(" End of init collection " + collection.getName());
945         return cid;
946     }
947
948     /**
949      * Initialize all fields of an object in the storage.
950      *
951      * <p>This method is called when a new object is made persistent. The
952      * references and collections are also recursively saved into the
953      * storage.<p>
954      *
955      * @param wrappee the initialized object
956      */

957     public void initAllFields(Wrappee wrappee, OID oid) throws Exception JavaDoc {
958         if (oid==null)
959             throw new InvalidOidException("oid is NULL");
960         String JavaDoc classID = wrappee.getClass().getName();
961         logger.debug("initAllfields(" + oid + ") : " + classID);
962         ClassItem cli = cr.getClass(classID);
963         FieldItem[] fields = cli.getPrimitiveFields();
964         Storage storage = oid.getStorage();
965         storage.startTransaction();
966         try {
967             // fields
968
for (int i = 0; i < fields.length; i++) {
969                 if (!fields[i].isTransient()
970                     && !fields[i].isStatic()
971                     && !fields[i].isFinal())
972                 {
973                     Object JavaDoc fieldValue = fields[i].get(wrappee);
974                     logger.debug("Init field "
975                             + fields[i].getName()+ "->" + fieldValue);
976                     if (fieldValue != null) {
977                         if (fieldValue instanceof Wrappee)
978                             storage.setField(oid,fields[i],getOID((Wrappee)fieldValue));
979                         else
980                             storage.setField(oid,fields[i],fieldValue);
981                     }
982                 }
983             }
984
985             FieldItem[] references = cli.getReferences();
986
987             // references
988
for (int i = 0; i < references.length; i++) {
989                 if (!references[i].isTransient()
990                     && !references[i].isStatic()
991                     && !references[i].isFinal()) {
992                     logger.debug("Init reference " + references[i].getName());
993                     Wrappee obj =
994                         (Wrappee) references[i].getActualField().get(wrappee);
995                     logger.debug("Ref value = "
996                             + (obj != null ? obj.getClass().getName() : "null"));
997
998                     loadedReferences.add(references[i].getName());
999                     if (obj != null) {
1000                        OID objoid =
1001                            (OID)Wrapping.invokeRoleMethod(
1002                                obj,
1003                                "makePersistent",
1004                                ExtArrays.emptyObjectArray);
1005                        if (objoid == null) {
1006                            // this should never happen
1007
logger.error(
1008                                "wrapper.oid is NULL in initAllFields, reference = "
1009                                    + references[i].getName());
1010                        } else {
1011                            logger.debug("Ref value = " + objoid);
1012                            storage.setField(oid,references[i],objoid);
1013                            logger.debug("Ref saved");
1014                        }
1015                    }
1016                }
1017
1018                // UNCOMMENT THIS WHEN UNWRAP WILL BE THREAD-SAFE!!!
1019
// unwrap the reference's getter because it won't need to be
1020
// reloaded from the storage
1021
//MethodItem getter = references[i].getGetter();
1022
//if (getter!=null) {
1023
// Wrapping.unwrap(interaction.wrappee,this,"applyPersistence",getter);
1024
//}
1025
}
1026
1027            initCollections(wrappee, oid, cli.getCollections());
1028            storage.commit();
1029        } catch (Exception JavaDoc e) {
1030            storage.rollback();
1031            throw e;
1032        }
1033    }
1034
1035    public static class InvalidOidException extends RuntimeException JavaDoc {
1036        public InvalidOidException(String JavaDoc msg) {
1037            super(msg);
1038        }
1039    }
1040
1041    public Object JavaDoc invoke(MethodInvocation invocation) throws Throwable JavaDoc {
1042        return applyPersistence((Interaction) invocation);
1043    }
1044
1045    public Object JavaDoc construct(ConstructorInvocation invocation)
1046        throws Throwable JavaDoc
1047    {
1048        return handleStatic((Interaction) invocation);
1049    }
1050}
1051
1052// Local Variables: ***
1053
// c-basic-offset:4 ***
1054
// End: ***
1055
Popular Tags