KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > mdr > storagemodel > MdrStorage


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19 package org.netbeans.mdr.storagemodel;
20
21 import org.netbeans.mdr.NBMDRepositoryImpl;
22 import org.netbeans.mdr.handlers.BaseObjectHandler;
23 import org.netbeans.mdr.persistence.*;
24 import org.netbeans.mdr.util.*;
25 import javax.jmi.model.ModelElement;
26 import javax.jmi.model.ModelPackage;
27 import javax.jmi.model.NameNotFoundException;
28 import javax.jmi.model.Namespace;
29 import javax.jmi.reflect.*;
30 import java.io.IOException JavaDoc;
31 import java.lang.ref.ReferenceQueue JavaDoc;
32 import java.lang.ref.WeakReference JavaDoc;
33 import java.lang.ref.Reference JavaDoc;
34 import java.lang.reflect.Constructor JavaDoc;
35 import java.util.*;
36
37 /**
38  * Instances of <code>MdrStorage</code> create and wrap {@link
39  * org.netbeans.mdr.persistence.Storage storages}. The latter are generic
40  * indexed object databases, the former add MDR specific functionality.
41  * An instance of <code>MdrStorage</code> mediates between one or more storages and
42  * a {@link org.netbeans.mdr.NBMDRepositoryImpl repository}. It creates and
43  * manages all the indices specific for MDR repositories.
44  *
45  * <p>There is one boot storage. Further storages may be mounted and unmounted
46  * additionally.
47  *
48  * @author Petr Hrebejk, Pavel Buzek, Martin Matula
49  * @version
50  */

51
52 public class MdrStorage implements MOFConstants, ObjectResolver {
53     
54     /* -------------------------------------------------------------------- */
55     /* -- Private static constants ---------------------------------------- */
56     /* -------------------------------------------------------------------- */
57
58     private static final int STORAGE_VERSION = 26;
59     
60     // names of global storage indexes
61
static final String JavaDoc IDX_OBJECTS_BY_CLASSES = "ObjectsByClasses";
62     private static final String JavaDoc IDX_MDR_STORAGE_PROPERTIES = "Properties";
63     private static final String JavaDoc IDX_CONTEXTS = "Contexts";
64     
65     // prefixes for context-specific indexes
66
private static final String JavaDoc PREFIX_ATTR_INDEX = "ai:";
67     private static final String JavaDoc PREFIX_ATTR_INDEXES_BY_NAME = "aibn:";
68     private static final String JavaDoc PREFIX_ATTR_INDEXES_CLASS_PROXY = "aicp:";
69     private static final String JavaDoc PREFIX_ASSOC_END = "ae:";
70     
71     /** name of storage property which holds MOFID of outermost package
72      * representing the first meta layer (MOF) */

73     public static final String JavaDoc MOF_TOP_PACKAGE = "TOPMOST_PACKAGE";
74     /** name of storage property which holds ID of cached values */
75     public static final String JavaDoc VALUES_ID = "VALUES_ID";
76     
77     /** instances of MdrStorage by storage ID */
78     private static final Hashtable instances = new Hashtable();
79
80     private InstanceMap externalObjects = null;
81
82 // private static MdrStorage currentMdrStorage = null;
83
// private static Storage currentStorage = null;
84

85     /* -------------------------------------------------------------------- */
86     /* -- Static methods -------------------------------------------------- */
87     /* -------------------------------------------------------------------- */
88     
89     /** Returns instance wrapping the given storage
90      * @param storage
91      * @return <code>MdrStorage</code> wrapping <code>storage</code>
92      */

93     public static MdrStorage getInstance(Storage storage) {
94         MdrStorage result = (MdrStorage) instances.get(storage);
95 // if (result == null) result = currentMdrStorage;
96
return result;
97     }
98
99     public void registerExternal(StorableBaseObject storable) {
100         if (externalObjects == null) {
101             externalObjects = new InstanceMap();
102         }
103         externalObjects.put(storable.getMofId(), storable);
104     }
105
106     public void removeExternal(StorableBaseObject storable) {
107         if (externalObjects != null) {
108             externalObjects.remove(storable.getMofId());
109         }
110     }
111
112     private StorableBaseObject getExternal(MOFID mofId) {
113         StorableBaseObject result = null;
114         if (externalObjects != null) {
115             result = (StorableBaseObject) externalObjects.get(mofId);
116         }
117         return result;
118     }
119
120     /* -------------------------------------------------------------------- */
121     /* -- Private attributes ---------------------------------------------- */
122     /* -------------------------------------------------------------------- */
123     
124     /** reference to implementation of Storage interface (the "real" storage) */
125     // private Storage storage;
126
/** reference to implementation of {@link org.netbeans.mdr.persistence.Storage}
127      * interface (the "real" boot storage) */

128     private Storage bootStorage;
129     private org.netbeans.mdr.persistence.MOFID bootNullMofId;
130     
131     /** Boot storage and all partition storages used by
132      * this MdrStorage instance, hashed by storageId
133      */

134     private HashMap storages;
135     
136     /** cached value of storage's NULL MOFID */
137     // private String nullMofId;
138
private HashMap nullMofId;
139     
140     // references to global storage indexes
141
// primary index
142
// private SinglevaluedIndex objects;
143
/** HashMap containing the primary indices,
144      * storing the objects to make them accessible by ID.
145      * This are the only indices having objects as values, all other indices
146      * have IDs as values.
147      */

148     private HashMap objects;
149     
150     // IDX_OBJECTS_BY_CLASSES
151
// private MultivaluedIndex objByCls;
152
/** Multi-valued indices making instance IDs accessible by class proxy ID. */
153     private HashMap objByCls;
154     
155     // IDX_CONTEXTS
156
// private SinglevaluedIndex contexts;
157
/** Singe-valued indices making contexts (references to outermost
158      * package extents) accessible by name. */

159     private HashMap contexts;
160     
161     // IDX_MDR_STORAGE_PROPERTIES
162
// private SinglevaluedIndex properties;
163
/** Single-valued indices making property IDs accessible by name. */
164     private HashMap properties;
165     
166     // IDX_END1_CLASSES_BY_ASSOCIATIONS
167
// private SinglevaluedIndex associationsEnd1;
168
// IDX_END2_CLASSES_BY_ASSOCIATIONS
169
// private SinglevaluedIndex associationsEnd2;
170

171     //private ValuesObject valuesObject; // Should be stored into the storage where the metamodel is stored
172
/**
173      *
174      */

175     private HashMap valuesObjects;
176     // to ensure that all the partitions see it.
177

178     /**
179      * The repository.
180      */

181     private final NBMDRepositoryImpl repository;
182     
183     /** Mutex for transaction locks. */
184     private final TransactionMutex repositoryMutex;
185     /** Mutex for transaction locks. */
186     private final EventNotifier eventNotifier;
187     
188     /* -- Transient support ---*/
189     private org.netbeans.mdr.storagemodel.transientimpl.TransientStorage transientStorage;
190     
191     /* -- boot specific stuff --------------------------------------------- */
192     
193     /**
194      * Determines whether the storage is ready or not.
195      */

196     private boolean booting;
197     /** boot class proxies */
198     private Collection bootClasses = null;
199     /** boot instances */
200     private Collection bootObjects = null;
201     /** boot association proxies */
202     private Collection bootAssociations = null;
203     
204     private volatile boolean silent = false;
205     
206     /* -------------------------------------------------------------------- */
207     /* -- Setters/Getters (public) ---------------------------------------- */
208     /* -------------------------------------------------------------------- */
209     
210     public TransactionMutex getRepositoryMutex() {
211         return repositoryMutex;
212     }
213     
214     public EventNotifier getEventNotifier() {
215         return eventNotifier;
216     }
217     
218     public NBMDRepositoryImpl getRepository() {
219         return repository;
220     }
221     
222     /**
223      * Announce that this storage is being booted. Only the storage which holds
224      * the MOF metamodel should be called with `true' as argument.
225      */

226     public void setBooting(boolean flag) {
227         this.booting = flag;
228     }
229     
230     public boolean isBooting() {
231         return this.booting;
232     }
233     
234     public void enableEvents() {
235         silent = false;
236     }
237     
238     public void disableEvents() {
239         silent = true;
240     }
241     
242     public boolean eventsEnabled() {
243         return !silent;
244     }
245     
246     /* -------------------------------------------------------------------- */
247     /* -- Constructor (public) -------------------------------------------- */
248     /* -------------------------------------------------------------------- */
249     
250     /** Creates a new <code>MdrStorage</code> using factory <code>storageClass</code>
251      * and parameters <code>properties</code>. Creates a default storage, if the
252      * <code>storageClass</code> is not a
253      * {@link org.netbeans.mdr.persistence.StorageFactory} or cannot be instantiated.
254      *
255      * @param repository
256      * @param storageClass fully qualified name of class implementing
257      * {@link org.netbeans.mdr.persistence.StorageFactory}
258      * @param properties parameters for storage creation
259      * @exception DebugException if the storage cannot be created
260      */

261     public MdrStorage(NBMDRepositoryImpl repository, String JavaDoc storageClass, Map properties) {
262         this.storages = new HashMap();
263         this.nullMofId = new HashMap();
264         this.objects = new HashMap();
265         this.objByCls = new HashMap();
266         this.contexts = new HashMap();
267         this.properties = new HashMap();
268         this.valuesObjects = new HashMap();
269         
270         this.repository = repository;
271         StorageFactory storageFactory = null;
272         try {
273             // try to instantiate storage factory (its class name was passed as storageClass argument)
274
Class JavaDoc storageFactoryClass = Class.forName(storageClass);
275             // does the class implement StorageFactory interface?
276
if (StorageFactory.class.isAssignableFrom(storageFactoryClass)) {
277                 // yes - create new instance
278
storageFactory = (StorageFactory) storageFactoryClass.newInstance();
279             } else {
280                 // no - throw exception
281
// (this exception will not be propagated - it will be caught immediately - see following lines)
282
throw new Exception JavaDoc("class "+storageClass+" does not implement StorageFactory");
283             }
284         } catch (Exception JavaDoc e) {
285             // in case the passed StorageFactory class could not be created, create default implementation
286
// of StorageFactory interface
287
Logger.getDefault().notify(Logger.INFORMATIONAL, e);
288             Logger.getDefault().log("using: org.netbeans.mdr.persistence.memoryimpl.StorageFactoryImpl");
289             storageFactory = new org.netbeans.mdr.persistence.memoryimpl.StorageFactoryImpl();
290         }
291         
292         try {
293             // create storage passing the parameters to the factory method
294
this.bootStorage = storageFactory.createStorage(properties);
295             // cache the NULL MOFID of the boot storage
296
this.bootNullMofId = storageFactory.createNullMOFID();
297         } catch (StorageException e) {
298             throw (DebugException) Logger.getDefault().annotate(new DebugException("Failed accessing storage factory."), e);
299         }
300         
301         // create the utilities for storage management
302
eventNotifier = new EventNotifier();
303         
304         String JavaDoc mutexClass = (String JavaDoc) properties.get("mutexClass");
305         TransactionMutex mutex = null;
306         
307         if (mutexClass != null) {
308             try {
309                 Constructor JavaDoc mutexConstructor = BaseObjectHandler.resolveImplementation(mutexClass).getConstructor(new Class JavaDoc[] {Object JavaDoc.class, Object JavaDoc.class, Object JavaDoc.class});
310                 mutex = (TransactionMutex) mutexConstructor.newInstance(new Object JavaDoc[] {this, eventNotifier, repository});
311             } catch (Exception JavaDoc e) {
312                 Logger.getDefault().notify(Logger.INFORMATIONAL, e);
313             }
314         }
315         
316         if (mutex == null) {
317             mutex = new MultipleReadersMutex(this, eventNotifier, repository);
318         }
319         
320         repositoryMutex = mutex;
321     }
322     
323     /* -------------------------------------------------------------------- */
324     /* -- (Un)mounting additional storages -------------------------------- */
325     /* -------------------------------------------------------------------- */
326     
327     /**
328      * Mounts a new storage, adding it to the collection of all storages
329      * managed by this <code>MdrStorage</code>.
330      *
331      * @param storageFactoryClass the name of factory class
332      * @param properties the storage creation parameter
333      * @return the storage ID of the newly created storages or <code>null</code>
334      * of <code>storageFactoryClass</code> does not implement {@link
335      * org.netbeans.mdr.persistence.Storage}
336      * @exception StorageException
337      * @exception InstantiationException
338      * @exception IllegalAccessException
339      * @exception ClassNotFoundException if <code>storageFactoryClass</code> is
340      * not a valid class name
341      */

342     public String JavaDoc mountStorage(String JavaDoc storageFactoryClass, Map properties) throws StorageException, InstantiationException JavaDoc, ClassNotFoundException JavaDoc, IllegalAccessException JavaDoc {
343         return this.mountStorage(Class.forName(storageFactoryClass), properties);
344     }
345     
346     /**
347      * Mounts a new storage, adding it to the collection of all storages
348      * managed by this <code>MdrStorage</code>.
349      *
350      * @param storageFactoryClass the factory class
351      * @param properties the storage creation parameter
352      * @return the storage ID of the newly created storages or <code>null</code>
353      * of <code>storageFactoryClass</code> does not implement {@link
354      * org.netbeans.mdr.persistence.Storage}
355      * @exception StorageException
356      * @exception InstantiationException
357      * @exception IllegalAccessException
358      */

359     public String JavaDoc mountStorage(Class JavaDoc storageFactoryClass, Map properties) throws StorageException, InstantiationException JavaDoc, IllegalAccessException JavaDoc {
360         if (StorageFactory.class.isAssignableFrom(storageFactoryClass)) {
361             StorageFactory storageFactory = (StorageFactory) storageFactoryClass.newInstance();
362             Storage st = storageFactory.createStorage(properties);
363             org.netbeans.mdr.persistence.MOFID nullMofId = storageFactory.createNullMOFID();
364             this.init(st,nullMofId, false);
365             return st.getStorageId();
366         }
367         return null;
368     }
369     
370     /**
371      * Unmounts the storage with ID <code>storageId</code>. Does nothing
372      * if <code>storageId</code> is not a valid storage ID.
373      *
374      * @param storageId the storage to be unmounted
375      * @exception StorageException
376      */

377     public void unmountStorage(String JavaDoc storageId) throws StorageException {
378         Storage selStorage = (Storage) this.storages.get(storageId);
379         if (selStorage == null)
380             return;
381         selStorage.shutDown();
382         this.instances.remove(selStorage);
383         this.nullMofId.remove(storageId);
384         this.objects.remove(storageId);
385         this.objByCls.remove(storageId);
386         this.contexts.remove(storageId);
387         this.storages.remove(storageId);
388         this.properties.remove(storageId);
389         this.valuesObjects.remove(storageId);
390     }
391     
392     /* -------------------------------------------------------------------- */
393     /* -- Methods for initialization and reinitialization (public/private) */
394     /* -------------------------------------------------------------------- */
395     
396     
397     /** Initializes MdrStorage instance.
398      * This method is called by the {@link org.netbeans.mdr.NBMDRepositoryImpl repository}
399      * during its initialization. It initializes resp. creates the boot storage.
400      *
401      * @return returns <code>true</code> if the storage file exists; <code>false</code>
402      * if the storage is new and needs to be booted
403      * @throws StorageException unexpected problem in storage
404      * @see #init(Storage, String, boolean)
405      */

406     public boolean init() throws StorageException {
407         return this.init(this.bootStorage, this.bootNullMofId, true);
408     }
409     
410     /**
411      * Initializes the {@link org.netbeans.mdr.persistence.Storage}
412      * <code>storage</code>.
413      *
414      * <p>Storage initialization consists in:
415      * <ol>
416      * <li>the storage is opened</li>
417      * <li>the indices are initialized</li>
418      * <li><code>true</code> is returned to indicate that the storage is
419      * ready</li>
420      * </ol>
421      *
422      * <p>Storage creation consists in:
423      * <ol>
424      * <li>the storage is created resp. recreated (the latter, if it was
425      * corrupted)</li>
426      * <li>the indices are created</li>
427      * <li>the properties are initialized</li>
428      * <li><code>false</code> is returned to indicate the need to boot the
429      * storage</li>
430      * </ol>
431      *
432      * @param storage the storage to be initialized
433      * @param nullMofId
434      * @param defaultStorage <code>true</code>, if the boot storage is
435      * to be initialized, <code>false</code> otherwise
436      * @return returns <code>false</code>
437      * if the storage is new and needs to be booted
438      * @throws StorageException unexpected problem in storage
439      */

440     public boolean init(Storage storage, org.netbeans.mdr.persistence.MOFID nullMofId, boolean defaultStorage) throws StorageException {
441         // NOTE: no synchronization is needed in this method, it will be invoked as a part of synchronized code
442
// (whole storage initialization and boot will be synchronized in upper level:
443
// synchronized void NBMDRepository.initCheck())
444
// QUESTION: how is NBMDRepository.mountStorage(..) synchronized ?
445
boolean result;
446         String JavaDoc storageId = null;
447         try {
448             // try to open the storage (if open fails, exception is thrown and program continues in catch block
449
// currentMdrStorage = this;
450
// currentStorage = storage;
451
storage.open(false, this);
452 // currentStorage = null;
453
// currentMdrStorage = null;
454
storageId = storage.getStorageId();
455             // read indexes
456
initializeIndexes(storage, defaultStorage, false);
457             // everything succeeded -> return true
458
result = true;
459         } catch (Exception JavaDoc e) {
460             Logger.getDefault().log("Rebooting storage. Reason: " + e);
461             // storage not found or corrupted -> create new one
462
try {
463                 // in case the storage is already open, try to close it
464
storage.close();
465             } catch (StorageException ex) {
466             }
467
468             // create a new storage
469
storage.create(true, this);
470             storageId = storage.getStorageId();
471             // get the primary index
472
SinglevaluedIndex objectsIndex = storage.getPrimaryIndex();
473             objects.put(storageId, objectsIndex);
474             // create all global indexes
475
contexts.put(storageId, storage.createSinglevaluedIndex(IDX_CONTEXTS + STORAGE_VERSION, Storage.EntryType.STRING, Storage.EntryType.MOFID));
476             objByCls.put(storageId, storage.createMultivaluedIndex(IDX_OBJECTS_BY_CLASSES, Storage.EntryType.MOFID, Storage.EntryType.MOFID, false)); // it is not effective to set this index as unique, although it is
477
SinglevaluedIndex propertiesIndex = storage.createSinglevaluedIndex(IDX_MDR_STORAGE_PROPERTIES, Storage.EntryType.STRING, Storage.EntryType.MOFID);
478             propertiesIndex.put(MODEL_ASSOCIATION_END, nullMofId);
479             propertiesIndex.put(MODEL_ATTRIBUTE, nullMofId);
480             propertiesIndex.put(MODEL_REFERENCE, nullMofId);
481             propertiesIndex.put(MODEL_OPERATION, nullMofId);
482             MOFID valuesID = new MOFID (storage);
483             propertiesIndex.put(VALUES_ID, valuesID);
484             this.properties.put(storageId, propertiesIndex);
485             ValuesObject valuesObject = new ValuesObject(storage, valuesID);
486             this.valuesObjects.put(storageId, valuesObject);
487             objectsIndex.add(valuesID, valuesObject);
488             storage.objectStateChanged(valuesID);
489             // storage has to be booted -> return false
490
result = ! defaultStorage;
491         }
492         // register this storage instance into the table of instances
493
instances.put(storage, this);
494         this.nullMofId.put(storageId, nullMofId);
495         this.storages.put(storageId, storage);
496         return result;
497     }
498     
499     /**
500      * Initializes the references to global storage indices.
501      *
502      * @throws DebugExceptions if any of the global indices was not found or
503      *
504      */

505     private void initializeIndexes(Storage storage, boolean defaultStorage, boolean rollBack) {
506         try {
507             // get the primary index
508
String JavaDoc storageId = storage.getStorageId();
509             SinglevaluedIndex objectsIndex = storage.getPrimaryIndex();
510             MultivaluedIndex objByClsIndex = storage.getMultivaluedIndex(IDX_OBJECTS_BY_CLASSES);
511             SinglevaluedIndex contextsIndex = storage.getSinglevaluedIndex(IDX_CONTEXTS + STORAGE_VERSION);
512             if (objByClsIndex==null || objectsIndex==null || contextsIndex==null) {
513                 throw new DebugException("Missing storage files or different storage version.");
514             }
515             if (!defaultStorage && !rollBack && !silent) {
516                 // Fire events for adding all extents
517
for (Iterator it = contextsIndex.keySet().iterator(); it.hasNext();) {
518                     String JavaDoc extentName = (String JavaDoc) it.next();
519                     org.netbeans.api.mdr.events.ExtentEvent event = new org.netbeans.api.mdr.events.ExtentEvent(this.repository,
520                     org.netbeans.api.mdr.events.ExtentEvent.EVENT_EXTENT_CREATE, extentName,
521                     null, null,false);
522                     this.getEventNotifier().REPOSITORY.firePlannedChange(this, event);
523                 }
524             }
525             this.objects.put(storageId, objectsIndex);
526             this.contexts.put(storageId, contextsIndex);
527             this.objByCls.put(storageId, objByClsIndex);
528             SinglevaluedIndex props = storage.getSinglevaluedIndex(IDX_MDR_STORAGE_PROPERTIES);
529             if (props == null) {
530                 throw new DebugException("Different storage version.");
531             }
532             this.properties.put(storageId, props);
533             this.valuesObjects.put(storageId, objectsIndex.get(props.get(VALUES_ID)));
534         } catch (StorageException e) {
535             throw new DebugException("Missing storage files or different storage version.");
536         }
537     }
538     
539     /* -------------------------------------------------------------------- */
540     /* -- Transaction related methods (public) ---------------------------- */
541     /* -------------------------------------------------------------------- */
542     
543     /**
544      * Commits (saves) storage changes.
545      */

546     public void commit() throws StorageException {
547         save();
548     }
549     
550     /**
551      * Rolls back storage changes.
552      */

553     public synchronized void rollback() throws StorageException {
554         for (Iterator it = this.storages.values().iterator(); it.hasNext();) {
555             Storage storage = (Storage) it.next();
556             // it.remove();
557
storage.rollBackChanges();
558             // reinitialize the global indices
559
if (storage != transientStorage)
560                 initializeIndexes(storage, storage == this.bootStorage, true);
561         }
562     }
563     
564     /** Commits changes to the storage.
565      * @throws StorageException problem in storage
566      */

567     public synchronized void save() throws StorageException {
568         /*
569         synchronized (valuesObject) {
570             storage.objectStateChanged(getProperty(VALUES_ID));
571         }
572          */

573         for (Iterator it = this.storages.values().iterator(); it.hasNext();) {
574             Storage storage = (Storage) it.next();
575             // it.remove ();
576
storage.commitChanges();
577         }
578     }
579     
580     /**
581      * Notifies storage about shutDown.
582      * @throws StorageException problem in storage
583      */

584     public void shutDown() throws StorageException {
585         try {
586             for (Iterator it = this.storages.values().iterator(); it.hasNext();) {
587                 Storage s = (Storage)it.next();
588                 s.shutDown();
589                 repository.notifyShutdownStep();
590             }
591         } finally {
592             eventNotifier.shutdown();
593             repository.notifyShutdownStep();
594         }
595     }
596     
597     public int getShutdownSteps() {
598         return storages.size() + 1;
599     }
600     
601     /* -------------------------------------------------------------------- */
602     /* -- Storage properties accessors & mutators ------------------------- */
603     /* -------------------------------------------------------------------- */
604     
605     /** Returns value of the specified boot storage property.
606      * @param key property name
607      * @return value of property of the specified name (an MOF ID)
608      */

609     org.netbeans.mdr.persistence.MOFID getProperty(String JavaDoc key) {
610         return this.getProperty(this.bootStorage.getStorageId(),key);
611     }
612     
613     /** Returns value of the specified storage property.
614      * @param storageId the ID of the {@link
615      * org.netbeans.mdr.persistence.Storage} a property of which has to be
616      * returned
617      * @param key property name
618      * @return value of property of the specified name (an MOF ID)
619      * @exception DebugException if there is not storage with the given ID
620      */

621     org.netbeans.mdr.persistence.MOFID getProperty(String JavaDoc storageId, String JavaDoc key) {
622         try {
623             SinglevaluedIndex propertiesIndex = this.getPropertiesIndexByStorageId(storageId);
624             if (propertiesIndex == null)
625                 throw new DebugException("No such storage");
626             return (org.netbeans.mdr.persistence.MOFID) propertiesIndex.get(key);
627         } catch (StorageException e) {
628             throw (DebugException) Logger.getDefault().annotate(new DebugException(), e);
629         }
630     }
631     
632     /** Sets value of the specified property in the boot storage.
633      * @param key property name
634      * @param value new property value (an MOF ID)
635      */

636     void setProperty(String JavaDoc key, org.netbeans.mdr.persistence.MOFID value) {
637         this.setProperty(this.bootStorage.getStorageId(), key, value);
638     }
639     
640     /** Sets value of the specified property.
641      * @param storageId the ID of the {@link
642      * org.netbeans.mdr.persistence.Storage} a property of which has to be
643      * set
644      * @param key property name
645      * @param value new property value (an MOF ID)
646      * @exception DebugException if there is not storage with the given ID
647      */

648     void setProperty(String JavaDoc storageId, String JavaDoc key, org.netbeans.mdr.persistence.MOFID value) {
649         try {
650             SinglevaluedIndex propertiesIndex = this.getPropertiesIndexByStorageId(storageId);
651             if (propertiesIndex == null)
652                 throw new DebugException("No such storage");
653             propertiesIndex.put(key, value);
654         } catch (StorageException e) {
655             throw (DebugException) Logger.getDefault().annotate(new DebugException(), e);
656         }
657     }
658     
659     /**
660      * @return */

661     /*
662     SinglevaluedIndex properties {
663         return properties;
664     }
665      */

666     
667     /* -------------------------------------------------------------------- */
668     /* -- ValuesObject accessors ------------------------------------------- */
669     /* -------------------------------------------------------------------- */
670     
671     public ValuesObject values(org.netbeans.mdr.persistence.MOFID mofId) {
672         String JavaDoc storageId = getStorageIdFromMofId(mofId);
673         return this.storageValues(storageId);
674     }
675     
676     public ValuesObject storageValues(String JavaDoc storageId) {
677         if (storageId == null) {
678             storageId = this.bootStorage.getStorageId();
679         }
680         return (ValuesObject) valuesObjects.get(storageId);
681     }
682     
683     /* -------------------------------------------------------------------- */
684     /* -- Primary index accessors ------------------------------------------- */
685     /* -------------------------------------------------------------------- */
686     
687     /** Gets object from primary index.
688      * @param mofid MOFID of object to be found or <code>null</code>
689      * @return object with specified mofid or <code>null</code> if no MOF ID was
690      * given (method called with <code>null</code> argument)
691      * @throws StorageException object with specified MOFID was not found or other problem in storage
692      */

693     public StorableBaseObject getObject(org.netbeans.mdr.persistence.MOFID mofid) throws StorageException {
694         if (mofid == null)
695             return null;
696         StorableBaseObject result = getExternal(mofid);
697         if (result == null) {
698             SinglevaluedIndex objectsIndex = getObjectsIndexByMofId(mofid);
699             if (objectsIndex == null)
700                 return null; // Partition was not found
701
synchronized (getStorageById(mofid.getStorageID())) {
702                 result = (StorableBaseObject) objectsIndex.getIfExists(mofid);
703             }
704         }
705         return result;
706     }
707     
708     /** Gets object from a singlevalued index using primary index.
709      * @param index singlevalued index containing reference to object to be returned
710      * @param key key under which the reference is stored in the index
711      * @throws StorageException problem in storage
712      * @return searched object
713      */

714     public StorableBaseObject getObjectFromIndexIfExists(SinglevaluedIndex index, Object JavaDoc key) throws StorageException {
715         Object JavaDoc mofId = index.getIfExists(key);
716         if (!(mofId instanceof org.netbeans.mdr.persistence.MOFID))
717             return null;
718         else
719             return getObject((org.netbeans.mdr.persistence.MOFID) mofId);
720     }
721
722     /** Retrieves collection of objects from a multivalued index using primary index.
723      * @param index multivalued index to be searched in
724      * @param key key under which the searched collection is stored
725      * @throws StorageException problem in storage
726      * @return collection of objects corresponding to the supplied key
727      */

728     public Collection getObjectsFromIndex(MultivaluedIndex index, Object JavaDoc key) throws StorageException {
729         SinglevaluedIndex objectsIndex = this.getObjectsIndexByMofId((org.netbeans.mdr.persistence.MOFID)key);
730         if (objectsIndex == null)
731             throw new DebugException("Invalid key");
732         synchronized (getStorageById(((org.netbeans.mdr.persistence.MOFID) key).getStorageID())) {
733             if (index instanceof MultivaluedOrderedIndex) {
734                 return ((MultivaluedOrderedIndex) index).getObjectsOrdered(key, objectsIndex);
735             }
736             else {
737                 return index.getObjects(key, objectsIndex);
738             }
739         }
740     }
741     
742     /** Adds object to the primary index using its MOF ID.
743      * @param object object to be added
744      * @throws StorageException problem in the storage
745      */

746     void addObject (StorableBaseObject object) throws StorageException {
747         org.netbeans.mdr.persistence.MOFID mofId = object.getMofId();
748         SinglevaluedIndex objectsIndex = getObjectsIndexByMofId(mofId);
749         if (objectsIndex == null) {
750             throw new DebugException("Storage not found");
751         }
752         objectsIndex.add(mofId, object);
753     }
754     
755     /**
756      * Removes object from the primary index.
757      * @param object the object to be removed
758      */

759     void removeObject(StorableBaseObject object) throws StorageException {
760         org.netbeans.mdr.persistence.MOFID mofId = object.getMofId();
761         this.removeObject (mofId);
762     }
763     
764     
765     void removeObject (org.netbeans.mdr.persistence.MOFID mofId) throws StorageException {
766         SinglevaluedIndex objectsIndex = (SinglevaluedIndex) this.getObjectsIndexByMofId(mofId);
767         if (objectsIndex == null) {
768             throw new DebugException("Storage not found");
769         }
770         objectsIndex.remove(mofId);
771     }
772     
773     /** Adds object to the primary index and associates the object with its
774      * class proxy.
775      * @param object object to be added
776      * @throws StorageException problem in the storage
777      */

778     void addInstance(StorableObject object) throws StorageException {
779         addObject(object);
780         org.netbeans.mdr.persistence.MOFID mofId = object.getMofId();
781         String JavaDoc storageId = getStorageIdFromMofId(mofId);
782         if (storageId == null) {
783             throw new DebugException("Invalid MOF ID");
784         }
785         MultivaluedIndex objByClsIndex = (MultivaluedIndex) objByCls.get(storageId);
786         if (objByClsIndex == null) {
787             throw new DebugException("Storage not found");
788         }
789         objByClsIndex.add(object.getClassProxyId(), mofId);
790     }
791     
792     /**
793      * Removes object from the primary index and dissolves the association with
794      * its class proxy.
795      * @param object the object to be removed
796      */

797     void removeInstance(StorableObject object) throws StorageException {
798         org.netbeans.mdr.persistence.MOFID mofId = object.getMofId();
799         org.netbeans.mdr.persistence.MOFID classProxyMofId = object.getClassProxyId();
800         this.removeInstance (mofId, classProxyMofId);
801     }
802     
803     void removeInstance (org.netbeans.mdr.persistence.MOFID mofId, org.netbeans.mdr.persistence.MOFID classProxyMofId) throws StorageException {
804         removeObject(mofId);
805         MultivaluedIndex objByClsIndex = this.getObjectsByClassesByMofId (mofId);
806         if (objByClsIndex == null) {
807             throw new DebugException("Storage not found");
808         }
809         objByClsIndex.remove( classProxyMofId, mofId);
810     }
811     
812     /**
813      * Returns the index associating class proxy IDs with instance IDs.
814      *
815      * @param classProxy a class proxy of the storage owning the index
816      * requested
817      */

818     public MultivaluedIndex getInstancesIndex(StorableClass classProxy) {
819         return this.getInstancesIndex(classProxy.getMofId());
820     }
821     
822     /**
823      * Returns the index associating class proxy IDs with instance IDs.
824      *
825      * @param classProxyId the MOF ID a class proxy of the storage owning the index
826      * requested
827      */

828     public MultivaluedIndex getInstancesIndex(org.netbeans.mdr.persistence.MOFID classProxyId) {
829         String JavaDoc storageId = getStorageIdFromMofId(classProxyId);
830         if (storageId == null) {
831             throw new DebugException("Invalid MOF ID");
832         }
833         MultivaluedIndex objByClsIndex = (MultivaluedIndex) objByCls.get(storageId);
834         if (objByClsIndex == null) {
835             throw new DebugException("Storage not found");
836         }
837         return objByClsIndex;
838     }
839     
840     /**
841      * Returns the instances for the class proxy with the given ID.
842      *
843      * @param classID the ID of a class proxy
844      */

845     public Collection getInstancesIds(org.netbeans.mdr.persistence.MOFID classProxyId) throws StorageException {
846         String JavaDoc storageId = getStorageIdFromMofId(classProxyId);
847         if (storageId == null) {
848             throw new DebugException("Invalid MOF ID");
849         }
850         MultivaluedIndex objByClsIndex = (MultivaluedIndex) objByCls.get(storageId);
851         if (objByClsIndex == null) {
852             throw new DebugException("Storage not found");
853         }
854         return objByClsIndex.getItems(classProxyId);
855     }
856     
857     // CONTEXT MANIPULATION METHODS ////////////////////////////////////////////////
858

859     /** Creates a new context (reference to outermost package extent).
860      * This includes creation of context specific indexes needed for the new context.
861      * @param name name of the new context
862      * @param mofId MOF ID of the outermost package in the context
863      * @throws StorageException problem in storage
864      */

865     void createContext(String JavaDoc name, org.netbeans.mdr.persistence.MOFID mofId) throws StorageException {
866         
867         String JavaDoc storageId = getStorageIdFromMofId(mofId);
868         if (storageId == null) {
869             throw new DebugException("Invalid MOF ID");
870         }
871         Storage storage = (Storage) this.storages.get(storageId);
872         if (storage == null) {
873             throw new DebugException("Storage not found");
874         }
875         // create set of context specific indexes
876
storage.createSinglevaluedIndex(PREFIX_ATTR_INDEXES_BY_NAME + mofId.getSerialNumber(), Storage.EntryType.STRING, Storage.EntryType.STRING);
877         storage.createSinglevaluedIndex(PREFIX_ATTR_INDEXES_CLASS_PROXY + mofId.getSerialNumber(), Storage.EntryType.STRING, Storage.EntryType.MOFID);
878         
879         // add context to the index of contexts
880
if (name != null) {
881             SinglevaluedIndex contextsIndex = (SinglevaluedIndex) this.contexts.get(storageId);
882             if (contextsIndex == null) {
883                 throw new DebugException("Storage not found");
884             }
885             contextsIndex.put(name, mofId);
886         }
887     }
888     
889     /** Deletes the specified context (reference to outermost package extent) from the storage.
890      * This includes deletion of all context indexes and objects contained in these indexes.
891      * @param name name of context to be deleted
892      * @throws StorageException
893      */

894     void dropContext(String JavaDoc name, org.netbeans.mdr.persistence.MOFID mofId) throws StorageException {
895         // drop all context attribute indexes
896
String JavaDoc storageId = getStorageIdFromMofId(mofId);
897         if (storageId == null) {
898             throw new DebugException("Invalid MOF ID");
899         }
900         Storage storage = (Storage) this.storages.get(storageId);
901         if (storage == null) {
902             throw new DebugException("Storage not found");
903         }
904         for (Iterator it = storage.getSinglevaluedIndex(PREFIX_ATTR_INDEXES_BY_NAME + mofId.getSerialNumber()).values().iterator(); it.hasNext();) {
905             storage.dropIndex(getAdditionalIndexName(mofId, (String JavaDoc) it.next()));
906         }
907         
908         // drop the rest of context indexes
909
storage.dropIndex(PREFIX_ATTR_INDEXES_BY_NAME + mofId.getSerialNumber());
910         storage.dropIndex(PREFIX_ATTR_INDEXES_CLASS_PROXY + mofId.getSerialNumber());
911         
912         // delete context
913
if (name != null) {
914             SinglevaluedIndex contextsIndex = (SinglevaluedIndex) this.contexts.get(storageId);
915             if (contextsIndex == null) {
916                 throw new DebugException("Storage not found");
917             }
918             contextsIndex.remove(name);
919         }
920     }
921     
922     /** Returns all contexts references to outermost package extent) in the
923      * boot storage.
924      * @throws StorageException problem in storage
925      * @return collection of context names
926      */

927     public Collection getContexts() throws StorageException {
928         HashSet result = new HashSet();
929         for (Iterator it = contexts.values().iterator(); it.hasNext();) {
930             SinglevaluedIndex sv = (SinglevaluedIndex) it.next();
931             result.addAll(sv.keySet());
932         }
933         return result;
934     }
935     
936     /** Returns all contexts references to outermost package extent) in the
937      * the storage with the given ID.
938      *
939      * @param storageId
940      * @throws StorageException problem in storage
941      * @return collection of context names
942      */

943     public Collection getContexts(String JavaDoc storageId) throws StorageException {
944         SinglevaluedIndex context = (SinglevaluedIndex) this.contexts.get(storageId);
945         if (context == null)
946             throw new IllegalArgumentException JavaDoc();
947         HashSet result = new HashSet();
948         result.addAll(context.keySet());
949         return result;
950     }
951     
952     public boolean renameContext(MOFID mofId, String JavaDoc newName) throws StorageException {
953         SinglevaluedIndex context = (SinglevaluedIndex) this.contexts.get(mofId.getStorageID());
954         if (context == null) throw new IllegalArgumentException JavaDoc();
955         for (Iterator it = context.keySet().iterator(); it.hasNext();) {
956             String JavaDoc oldName = (String JavaDoc) it.next();
957             if (context.get(oldName).equals(mofId)) {
958                 context.remove(oldName);
959                 context.add(newName, mofId);
960                 return true;
961             }
962         }
963         return false;
964     }
965     
966     /**
967      * Returns the outermost package proxy for the given context name.
968      *
969      * @param context name of a context (reference to outermost package extent)
970      * @return the outermost package proxy named by <code>context</code> or
971      * <code>null</code> if there is no such context
972      */

973     public StorablePackage getContextOutermostPackage(String JavaDoc context) throws StorageException {
974         Object JavaDoc id = null;
975         for (Iterator it = this.contexts.values().iterator(); it.hasNext();) {
976             SinglevaluedIndex contextsIndex = (SinglevaluedIndex) it.next();
977             id = contextsIndex.getIfExists(context);
978             if (id != null) {
979                 return (StorablePackage) getObject((org.netbeans.mdr.persistence.MOFID) id);
980             }
981         }
982         return null;
983     }
984     
985     // ADDITIONAL INDEXING SUPPORT /////////////////////////////////////////////////
986

987     /**
988      * Creates new additional index in the given context.
989      *
990      * @param context
991      * @param attrMofId identifies the attribute
992      * @param indexName names the index to be created
993      * @throws StorageException
994      */

995     public void createAdditionalIndex(org.netbeans.mdr.persistence.MOFID context, String JavaDoc indexName, org.netbeans.mdr.persistence.MOFID proxyId) throws StorageException {
996         Storage storage = getStorageByMofId(context);
997         if (storage == null) {
998             throw new DebugException("Storage not found");
999         }
1000        // the following two indexes can be merged if index is able to return 'key iterator'
1001
storage.getSinglevaluedIndex(PREFIX_ATTR_INDEXES_BY_NAME + context.getSerialNumber()).put(indexName, indexName);
1002        storage.getSinglevaluedIndex(PREFIX_ATTR_INDEXES_CLASS_PROXY + context.getSerialNumber()).put(indexName, proxyId);
1003        storage.createMultivaluedIndex(getAdditionalIndexName(context, indexName), Storage.EntryType.STRING, Storage.EntryType.MOFID, false);
1004    }
1005    
1006    /**
1007     * Returns index for attribte <code>attrMofId</code> in the given context
1008     * or <code>null</code> if there is no such index.
1009     *
1010     * @param context
1011     * @param indexName
1012     * @return the index for the given attribute or <code>null</code> */

1013    private MultivaluedIndex getAdditionalIndex(org.netbeans.mdr.persistence.MOFID context, String JavaDoc indexName) {
1014        try {
1015            Storage storage = getStorageByMofId(context);
1016            if (storage == null) {
1017                throw new DebugException("Storage not found");
1018            }
1019            return storage.getMultivaluedIndex(getAdditionalIndexName(context, indexName));
1020        } catch (StorageException e) {
1021            return null;
1022        }
1023    }
1024    
1025    private StorableClass getIndexClassProxy (org.netbeans.mdr.persistence.MOFID context, String JavaDoc indexName) {
1026        try {
1027            Storage storage = getStorageByMofId(context);
1028            if (storage == null) {
1029                throw new DebugException("Storage not found");
1030            }
1031            return (StorableClass) getObject((org.netbeans.mdr.persistence.MOFID)storage.getSinglevaluedIndex(PREFIX_ATTR_INDEXES_CLASS_PROXY + context.getSerialNumber()).get(indexName));
1032        } catch (StorageException e) {
1033            return null;
1034        }
1035    }
1036    
1037    /**
1038     * The same as {@link #getAdditionalIndex(String, String)}.
1039     *
1040     * <p>[PENDING] Probably this method should be removed.
1041     */

1042    MultivaluedIndex acquireAdditionalIndex(org.netbeans.mdr.persistence.MOFID context, String JavaDoc indexName) {
1043        MultivaluedIndex result = getAdditionalIndex(context, indexName);
1044        return result;
1045    }
1046    
1047    /**
1048     * Currently does nothing.
1049     */

1050    void releaseAdditionalIndex() {
1051    }
1052    
1053    /**
1054     * This method is for internal usage only (NamespaceImpl) !
1055     */

1056    public Collection objectsFromAdditionalIndex(org.netbeans.mdr.persistence.MOFID context, String JavaDoc indexName, String JavaDoc value) {
1057        try {
1058            SinglevaluedIndex objectsIndex = getObjectsIndexByMofId (context);
1059            return getAdditionalIndex (context, resolveAttrMofId(context, indexName)).getObjects (value, objectsIndex);
1060        } catch (StorageException e) {
1061            return null;
1062        }
1063    }
1064    
1065    /**
1066     * @param context mof id of related outermost package extent
1067     * @param indexName name of the queried index
1068     * @param value queried key value, can be used only in case of one-field indexes
1069     * @return
1070     */

1071    public Collection getItemsFromAdditionalIndex(org.netbeans.mdr.persistence.MOFID context, String JavaDoc indexName, Object JavaDoc value) {
1072        try {
1073            StorableClass sc = getIndexClassProxy (context, indexName);
1074            if (sc == null) {
1075                throw new DebugException ("Index " + indexName + " does not exist in the specified context.");
1076            }
1077            StorableClass.IndexDescriptor desc = sc.getAdditionalIndex (indexName);
1078            String JavaDoc valueToString = StorableObject.valueToKey (value, desc.getFields());
1079            return getAdditionalIndex(context, resolveAttrMofId(context, indexName)).getItems(valueToString);
1080        } catch (StorageException e) {
1081            return null;
1082        }
1083    }
1084    
1085    /**
1086     * @param context mof id of related outermost package extent
1087     * @param indexName name of the queried index
1088     * @param value queried key value, can be used only in case of one-field indexes
1089     * @return
1090     */

1091    public Collection getObjectsFromAdditionalIndex(org.netbeans.mdr.persistence.MOFID context, String JavaDoc indexName, Object JavaDoc value) {
1092        try {
1093            StorableClass sc = getIndexClassProxy (context, indexName);
1094            if (sc == null) {
1095                throw new DebugException ("Index " + indexName + " does not exist in the specified context.");
1096            }
1097            StorableClass.IndexDescriptor desc = sc.getAdditionalIndex (indexName);
1098            String JavaDoc valueToString = StorableObject.valueToKey (value, desc.getFields());
1099            SinglevaluedIndex objectsIndex = getObjectsIndexByMofId (context);
1100            return getAdditionalIndex (context, resolveAttrMofId(context, indexName)).getObjects (valueToString, objectsIndex);
1101        } catch (StorageException e) {
1102            return null;
1103        }
1104    }
1105
1106    /**
1107     * @param context mof id of related outermost package extent
1108     * @param indexName name of the queried index
1109     * @param prefix key prefix
1110     * @return
1111     */

1112    public Collection getObjectsFromAIByPrefix(org.netbeans.mdr.persistence.MOFID context, String JavaDoc indexName, String JavaDoc prefix) {
1113        try {
1114            StorableClass sc = getIndexClassProxy (context, indexName);
1115            if (sc == null) {
1116                throw new DebugException ("Index " + indexName + " does not exist in the specified context.");
1117            }
1118            StorableClass.IndexDescriptor desc = sc.getAdditionalIndex (indexName);
1119            SinglevaluedIndex objectsIndex = getObjectsIndexByMofId (context);
1120            return getAdditionalIndex (context, resolveAttrMofId(context, indexName)).queryByKeyPrefix(prefix, objectsIndex);
1121        } catch (StorageException e) {
1122            return null;
1123        }
1124    }
1125    
1126    /**
1127     * @param context mof id of related outermost package extent
1128     * @param indexName name of the queried index
1129     * @param map map of pairs (field name, queried value)
1130     * @return
1131     */

1132    public Collection queryAdditionalIndex(org.netbeans.mdr.persistence.MOFID context, String JavaDoc indexName, Map map) {
1133        try {
1134            StorableClass sc = getIndexClassProxy (context, indexName);
1135            if (sc == null) {
1136                throw new DebugException ("Index " + indexName + " does not exist in the specified context.");
1137            }
1138            StorableClass.IndexDescriptor desc = sc.getAdditionalIndex (indexName);
1139            String JavaDoc valueToString = StorableObject.valuesToKey (map, desc.getFields());
1140            SinglevaluedIndex objectsIndex = getObjectsIndexByMofId (context);
1141            return getAdditionalIndex (context, resolveAttrMofId(context, indexName)).getObjects (valueToString, objectsIndex);
1142        } catch (StorageException e) {
1143            return null;
1144        }
1145    }
1146    
1147    /**
1148     * @param context
1149     * @param indexName
1150     * @throws StorageException
1151     * @return
1152     */

1153    private String JavaDoc resolveAttrMofId(org.netbeans.mdr.persistence.MOFID context, String JavaDoc indexName) throws StorageException {
1154        Storage storage = this.getStorageByMofId(context);
1155        return (String JavaDoc) storage.getSinglevaluedIndex(PREFIX_ATTR_INDEXES_BY_NAME + context.getSerialNumber()).get(indexName);
1156    }
1157    
1158    /**
1159     * @param context
1160     * @param indexName
1161     * @return
1162     */

1163    private String JavaDoc getAdditionalIndexName(org.netbeans.mdr.persistence.MOFID context, String JavaDoc indexName) {
1164        return PREFIX_ATTR_INDEX + context.getSerialNumber() + ":" + indexName;
1165    }
1166    
1167    // BOOT SUPPORT ////////////////////////////////////////////////////////////////
1168

1169    // NOTE: following methods don't have to be synchronized - whole boot sequence is synchronized
1170

1171    /**
1172     * @param mofId
1173     */

1174    void addBootObject(org.netbeans.mdr.persistence.MOFID mofId) {
1175        if (bootObjects == null) {
1176            bootObjects = new ArrayList();
1177        }
1178        bootObjects.add(mofId);
1179    }
1180    
1181    /**
1182     * @param mofId
1183     */

1184    void addBootClass(org.netbeans.mdr.persistence.MOFID mofId) {
1185        addBootObject(mofId);
1186        if (bootClasses == null) {
1187            bootClasses = new ArrayList();
1188        }
1189        bootClasses.add(mofId);
1190    }
1191    
1192    /**
1193     * @param mofId
1194     */

1195    void addBootAssociation(org.netbeans.mdr.persistence.MOFID mofId) {
1196        addBootObject(mofId);
1197        if (bootAssociations == null) {
1198            bootAssociations = new ArrayList();
1199        }
1200        bootAssociations.add(mofId);
1201    }
1202    
1203    /**
1204     * @throws StorageException
1205     */

1206    void dropBoot() throws StorageException {
1207        String JavaDoc name = NBMDRepositoryImpl.BOOT_MOF;
1208        org.netbeans.mdr.persistence.MOFID extent = getContextOutermostPackage(name).getMofId();
1209        org.netbeans.mdr.persistence.MOFID mofId;
1210        
1211        String JavaDoc storageId = getStorageIdFromMofId(extent);
1212        MultivaluedIndex objByClsIndex = (MultivaluedIndex) this.objByCls.get(storageId);
1213        SinglevaluedIndex objectsIndex = (SinglevaluedIndex) this.objects.get(storageId);
1214        SinglevaluedIndex contextsIndex = (SinglevaluedIndex) this.contexts.get(storageId);
1215        Storage storage = (Storage) this.storages.get(storageId);
1216        if (objByClsIndex == null || objectsIndex == null || contextsIndex == null || storage == null)
1217            throw new DebugException("Illegal MdrStorage state");
1218        
1219        for (Iterator it = bootClasses.iterator(); it.hasNext();) {
1220            objByClsIndex.remove((org.netbeans.mdr.persistence.MOFID) it.next());
1221        }
1222        
1223        for (Iterator it = bootObjects.iterator(); it.hasNext();) {
1224            objectsIndex.remove(it.next ());
1225        }
1226        
1227        for (Iterator it = bootAssociations.iterator(); it.hasNext();) {
1228            mofId = (org.netbeans.mdr.persistence.MOFID) it.next();
1229            storage.dropIndex(getContextAssocEndIndexName(extent, mofId, 1));
1230            storage.dropIndex(getContextAssocEndIndexName(extent, mofId, 2));
1231        }
1232        
1233        storage.dropIndex(PREFIX_ATTR_INDEXES_BY_NAME + extent.getSerialNumber());
1234        storage.dropIndex(PREFIX_ATTR_INDEXES_CLASS_PROXY + extent.getSerialNumber());
1235        contextsIndex.remove(name);
1236        
1237        bootObjects = null;
1238        bootClasses = null;
1239        
1240        getRepository().freeCache();
1241    }
1242    
1243    /**
1244     * @param table
1245     * @param object
1246     * @throws StorageException
1247     */

1248    void replaceMeta(Hashtable table, RefBaseObject object) throws StorageException {
1249        StorableBaseObject sObject = this.getObject(((BaseObjectHandler)object)._getDelegate().getMofId());
1250        sObject.replaceValues(table);
1251    }
1252    
1253    /**
1254     * @param pkg
1255     * @param qualifiedName
1256     * @return */

1257    private RefObject qnToObject(RefPackage pkg, List qualifiedName) {
1258        ModelPackage mofPackage = (ModelPackage) pkg;
1259        RefClass pc = mofPackage.getMofPackage();
1260        Iterator it = qualifiedName.iterator();
1261        ModelElement object = getPackageElement(pc, (String JavaDoc)it.next() );
1262        try {
1263            while (it.hasNext()) {
1264                object = ((Namespace) object).lookupElement((String JavaDoc) it.next());
1265            }
1266        } catch (NameNotFoundException e) {
1267            object = null;
1268        }
1269        return object;
1270    }
1271    
1272    /**
1273     * @param pc
1274     * @param name
1275     * @return */

1276    private ModelElement getPackageElement(RefClass pc, String JavaDoc name) {
1277        ModelElement object = null;
1278        ModelElement result = null;
1279        Iterator it = pc.refAllOfClass().iterator();
1280        result = (ModelElement) it.next();
1281        for (;it.hasNext();){
1282            object = (ModelElement)it.next();
1283            if (name.equals( object.getName() ) ) {
1284                result = object;
1285                break;
1286            }
1287        }
1288        return result;
1289    }
1290    
1291    /**
1292     * @param object
1293     * @return */

1294    private List objectToQN(RefObject object) {
1295        return ((ModelElement) object).getQualifiedName();
1296    }
1297    
1298    public void rebuildMofContext() {
1299        try {
1300            RefPackage bootMOF = (RefPackage) getRepository().getHandler(getContextOutermostPackage(NBMDRepositoryImpl.BOOT_MOF));
1301            RefPackage pureMOF = (RefPackage) getRepository().getHandler(getContextOutermostPackage(NBMDRepositoryImpl.PURE_MOF));
1302            RefClass classProxy;
1303            RefObject pureObject;
1304            RefObject bootObject;
1305            Hashtable fromTo = new Hashtable();
1306            
1307            fromTo.put(((BaseObjectHandler)bootMOF)._getDelegate().getMofId(), ((BaseObjectHandler)pureMOF)._getDelegate().getMofId());
1308            
1309            // create a conversion table
1310
for (Iterator classes = pureMOF.refAllClasses().iterator(); classes.hasNext();) {
1311                classProxy = (RefClass) classes.next();
1312                for (Iterator instances = classProxy.refAllOfClass().iterator(); instances.hasNext();) {
1313                    pureObject = (RefObject) instances.next();
1314                    bootObject = qnToObject(bootMOF, objectToQN(pureObject));
1315                    if (bootObject != null) {
1316                        fromTo.put(((BaseObjectHandler)bootObject)._getDelegate().getMofId(), ((BaseObjectHandler)pureObject)._getDelegate().getMofId());
1317                    }
1318                }
1319            }
1320            // make a conversion for the package
1321
replaceMeta(fromTo, pureMOF);
1322            
1323            // replace class proxy metas
1324
for (Iterator classes = pureMOF.refAllClasses().iterator(); classes.hasNext();) {
1325                classProxy = (RefClass) classes.next();
1326                replaceMeta(fromTo, classProxy);
1327                // replace instance metas
1328
for (Iterator instances = classProxy.refAllOfClass().iterator(); instances.hasNext();) {
1329                    pureObject = (RefObject) instances.next();
1330                    replaceMeta(fromTo, pureObject);
1331                }
1332            }
1333            
1334            for (Iterator associations = pureMOF.refAllAssociations().iterator(); associations.hasNext();) {
1335                replaceMeta(fromTo, (RefAssociation) associations.next());
1336            }
1337            
1338            rebuildMetas(NBMDRepositoryImpl.PURE_MOF, fromTo);
1339            dropBoot();
1340        } catch (Exception JavaDoc e) {
1341            throw (DebugException) Logger.getDefault().annotate(new DebugException(), e);
1342        }
1343    }
1344    
1345    /**
1346     * @param mofContext
1347     * @param table
1348     * @throws StorageException */

1349    void rebuildMetas(String JavaDoc mofContext, Map table) throws StorageException {
1350        /*
1351        Hashtable temp = new Hashtable();
1352        Object key;
1353        String extent = getContextOutermostPackage(mofContext).getMofId();
1354        
1355        // rebuild attribute indexes
1356        SinglevaluedIndex attributeIndexes = bootStorage.getSinglevaluedIndex(PREFIX_ATTR_INDEXES_BY_NAME + extent);
1357        String oldValue;
1358        String newValue;
1359        MultivaluedIndex oldAttributeIndex, newAttributeIndex;
1360        for (Iterator it = new HashSet(attributeIndexes.keySet()).iterator(); it.hasNext();) {
1361            key = it.next();
1362            oldValue = (String) attributeIndexes.get(key);
1363            newValue = (String) table.get(oldValue);
1364            createContextAttrIndex(mofContext, newValue, (String) key);
1365            newAttributeIndex = getContextAttrIndex(extent, newValue);
1366            oldAttributeIndex = getContextAttrIndex(extent, oldValue);
1367            for (Iterator it2 = oldAttributeIndex.keySet().iterator(); it2.hasNext();) {
1368                key = it2.next();
1369                for (Iterator it3 = oldAttributeIndex.getItems(key).iterator(); it3.hasNext();) {
1370                    newAttributeIndex.add(key, it3.next());
1371                }
1372            }
1373            bootStorage.dropIndex(oldAttributeIndex.getName());
1374        }
1375        */

1376        
1377        Object JavaDoc key;
1378        org.netbeans.mdr.persistence.MOFID newValue;
1379        org.netbeans.mdr.persistence.MOFID value;
1380        
1381        for (Iterator it = new HashSet(((SinglevaluedIndex)properties.get(this.bootStorage.getStorageId())).keySet()).iterator(); it.hasNext();) {
1382            key = it.next();
1383            value = getProperty((String JavaDoc) key);
1384            if (this.bootNullMofId.equals(value)) {
1385                newValue = (org.netbeans.mdr.persistence.MOFID) table.get(key);
1386            }
1387            else {
1388                newValue = (org.netbeans.mdr.persistence.MOFID) table.get(value);
1389            }
1390            if (newValue != null) {
1391                setProperty((String JavaDoc) key, newValue);
1392            }
1393        }
1394    }
1395    
1396    // /**
1397
// * @param isEndA
1398
// * @throws StorageException
1399
// * @return
1400
// */
1401
// Collection getUnrelatedItems(String assocId, int end, Index endIndex) throws StorageException {
1402
// SinglevaluedIndex assocIndex;
1403
// if (end == 1) {
1404
// assocIndex = associationsEnd2;
1405
// } else {
1406
// assocIndex = associationsEnd1;
1407
// }
1408
//
1409
// try { piMutex.enter(false); assocMutex.enter(false);
1410
// HashSet result = new HashSet();
1411
// collectObjects((StorableClass) assocIndex.getObject(assocId, objects), new HashSet(), result);
1412
//
1413
// for (Iterator it = endIndex.keySet().iterator(); it.hasNext();) {
1414
// result.remove(it.next());
1415
// }
1416
//
1417
// return result;
1418
// } finally {
1419
// assocMutex.leave();
1420
// piMutex.leave();
1421
// }
1422
// }
1423
//
1424
///**
1425
// * @param classProxy
1426
// * @param visited
1427
// * @param result
1428
// * @throws StorageException */
1429
// private void collectObjects(StorableClass classProxy, Set visited, Set result) throws StorageException {
1430
// visited.add(classProxy.getMofId());
1431
//
1432
// try { objByClsMutex.enter(false);
1433
// result.addAll(objByCls.getItems(classProxy.getMofId()));
1434
// } finally {
1435
// objByClsMutex.leave();
1436
// }
1437
//
1438
// String subclass;
1439
// for (Iterator it = classProxy.getSubclasses().iterator(); it.hasNext();) {
1440
// subclass = (String) it.next();
1441
// if (!visited.contains(subclass)) {
1442
// collectObjects((StorableClass) objects.get(subclass), visited, result);
1443
// }
1444
// }
1445
// }
1446
//
1447
// private StorableObject lookupByName(StorableObject object, String name) {
1448
// try {
1449
// Collection contents = (Collection) object.getReference(SH_MODEL_NAMESPACE_CONTENTS);
1450
// StorableObject result = findNamed(contents, name);
1451
//
1452
// if (result == null) {
1453
// Collection supertypes = (Collection) object.getReference(SH_MODEL_GENERALIZABLE_ELEMENT_SUPERTYPES);
1454
// for (Iterator it = supertypes.iterator(); it.hasNext();) {
1455
// result = lookupByName((StorableObject) it.next(), name);
1456
// if (result != null) {
1457
// break;
1458
// }
1459
// }
1460
// }
1461
//
1462
// return result;
1463
// } catch (java.lang.Exception e) {
1464
// throw Logger.getDefault().annotate(new DebugException(), e);
1465
// }
1466
// }
1467
//
1468
// private StorableObject findNamed(Collection objects, String featureName) throws StorageException {
1469
// for( Iterator it = objects.iterator(); it.hasNext(); ) {
1470
// StorableObject so = (StorableObject) it.next();
1471
// String objectName = (String) so.getAttribute(SH_MODEL_MODEL_ELEMENT_NAME);
1472
// if ( objectName != null && objectName.equals( featureName ) ) {
1473
// return so;
1474
// }
1475
// }
1476
//
1477
// return null;
1478
// }
1479

1480    ////////////////////////////////////////////////////////////////////////////////
1481

1482    /* -------------------------------------------------------------------- */
1483    /* -- Wrappers for org.netbeans.mdr.persistence.Storage methods ------- */
1484    /* -------------------------------------------------------------------- */
1485
1486    public MOFID generateMOFID (MOFID immediatePackageId) throws StorageException {
1487        if (immediatePackageId == null) {
1488            return this.generateMOFID(this.bootStorage);
1489        }
1490        else {
1491            return this.generateMOFID(getStorageByMofId(immediatePackageId));
1492        }
1493    }
1494    
1495    public MOFID generateMOFID (String JavaDoc storageId) throws StorageException {
1496        Storage st = (Storage) this.storages.get(storageId);
1497        if (st == null && org.netbeans.mdr.storagemodel.transientimpl.TransientStorage.STORAGE_ID.equals(storageId)) {
1498            st = this.getTransientStorage ();
1499        }
1500        return this.generateMOFID (st);
1501    }
1502    
1503    private org.netbeans.mdr.persistence.MOFID generateMOFID(Storage storage) throws StorageException {
1504        if (storage == null) {
1505            throw new IllegalArgumentException JavaDoc("Wrong storage id"); //NOI18N
1506
}
1507        return new org.netbeans.mdr.persistence.MOFID (storage);
1508    }
1509    
1510    public void objectStateWillChange(org.netbeans.mdr.persistence.MOFID mofId) throws StorageException {
1511        Storage storage = this.getStorageByMofId(mofId);
1512        if (storage == null) {
1513            throw new DebugException("Storage not found");
1514        }
1515        storage.objectStateWillChange(mofId);
1516    }
1517    
1518    public void objectStateChanged(org.netbeans.mdr.persistence.MOFID mofId) throws StorageException {
1519        Storage storage = this.getStorageByMofId(mofId);
1520        if (storage == null) {
1521            throw new DebugException("Storage not found");
1522        }
1523        storage.objectStateChanged(mofId);
1524    }
1525    
1526    
1527    public Index getIndex(org.netbeans.mdr.persistence.MOFID context, org.netbeans.mdr.persistence.MOFID assocMofId, int end ) throws StorageException {
1528        Storage storage = getStorageByMofId(context);
1529        if (storage == null) {
1530            throw new DebugException("Storage not found");
1531        }
1532        String JavaDoc indexName = getContextAssocEndIndexName(context, assocMofId, end);
1533        return storage.getIndex(indexName);
1534    }
1535    
1536    /** Create index that holds exactly one value for each key.
1537     * @return created index
1538     * @param name name of the index
1539     * @param keyType type of keys in the index
1540     * @param valueType type of values in the index (any type except STREAMABLE)
1541     */

1542    SinglevaluedIndex createSinglevaluedIndex(org.netbeans.mdr.persistence.MOFID context, org.netbeans.mdr.persistence.MOFID assocMofId, int end, Storage.EntryType keyType, Storage.EntryType valueType) throws StorageException {
1543        Storage storage = getStorageByMofId(context);
1544        if (storage == null) {
1545            throw new DebugException("Storage not found");
1546        }
1547        String JavaDoc indexName = getContextAssocEndIndexName(context, assocMofId, end);
1548        return storage.createSinglevaluedIndex(indexName, keyType, valueType);
1549    }
1550    
1551    /** Create index that holds sorted set of values for each key.
1552     * @return created index
1553     * @param name name of the index
1554     * @param keyType type of keys in the index
1555     * @param valueType type of values in the index (any type except STREAMABLE)
1556     * @param unique true if values associated with one key do not contain duplicates
1557     */

1558    MultivaluedOrderedIndex createMultivaluedOrderedIndex(org.netbeans.mdr.persistence.MOFID context, org.netbeans.mdr.persistence.MOFID assoccMofId, int end, Storage.EntryType keyType, Storage.EntryType valueType, boolean unique) throws StorageException {
1559        Storage storage = getStorageByMofId(context);
1560        if (storage == null) {
1561            throw new DebugException("Storage not found");
1562        }
1563        String JavaDoc indexName = getContextAssocEndIndexName(context, assoccMofId, end);
1564        return storage.createMultivaluedOrderedIndex(indexName, keyType, valueType, unique);
1565    }
1566    
1567    /** Create index that hold a set of values for each key. Elements in one Multivalued are
1568     * not sorted. Set does not contain duplicate values.
1569     * @return created index
1570     * @param name name of the index
1571     * @param keyType type of keys in the index
1572     * @param valueType type of values in the index (any type except STREAMABLE)
1573     * @param unique true if values associated with one key do not contain duplicates
1574     */

1575    MultivaluedIndex createMultivaluedIndex(org.netbeans.mdr.persistence.MOFID context, org.netbeans.mdr.persistence.MOFID assoccMofId, int end, Storage.EntryType keyType, Storage.EntryType valueType, boolean unique) throws StorageException {
1576        Storage storage = getStorageByMofId(context);
1577        if (storage == null) {
1578            throw new DebugException("Storage not found");
1579        }
1580        String JavaDoc indexName = getContextAssocEndIndexName(context, assoccMofId, end);
1581        return storage.createMultivaluedIndex(indexName, keyType, valueType, unique);
1582    }
1583    
1584    void dropIndex(org.netbeans.mdr.persistence.MOFID context, org.netbeans.mdr.persistence.MOFID assoccMofId, int end) throws StorageException {
1585        Storage storage = getStorageByMofId (context);
1586        if (storage == null) {
1587            throw new DebugException("Storage not found");
1588        }
1589        String JavaDoc indexName = getContextAssocEndIndexName(context, assoccMofId, end);
1590        storage.dropIndex(indexName);
1591    }
1592    
1593    /* -------------------------------------------------------------------- */
1594    /* -- ------- */
1595    /* -------------------------------------------------------------------- */
1596    
1597    /**
1598     * @param context
1599     * @param assocMofId
1600     * @param end
1601     * @return
1602     */

1603    private String JavaDoc getContextAssocEndIndexName (org.netbeans.mdr.persistence.MOFID context, org.netbeans.mdr.persistence.MOFID assocMofId, int end) {
1604        return PREFIX_ASSOC_END + context.getSerialNumber() + ":" + assocMofId.getSerialNumber() + ":" + end;
1605    }
1606
1607    public Storage getStorageByMofId (org.netbeans.mdr.persistence.MOFID mofId) {
1608        String JavaDoc storageId = getStorageIdFromMofId (mofId);
1609        return getStorageById(storageId);
1610    }
1611    
1612    public Storage getStorageById(String JavaDoc storageId) {
1613        if (storageId == null) {
1614            return null;
1615        }
1616        Storage result = (Storage) this.storages.get(storageId);
1617// if (result == null) result = currentStorage;
1618
return result;
1619    }
1620    
1621    private SinglevaluedIndex getObjectsIndexByMofId (org.netbeans.mdr.persistence.MOFID mofId) {
1622        String JavaDoc storageId = getStorageIdFromMofId(mofId);
1623        if (storageId == null) {
1624            return null;
1625        }
1626        SinglevaluedIndex result = (SinglevaluedIndex) this.objects.get(storageId);
1627// if (result == null) {
1628
// Storage s = getStorageById(mofId.getStorageID());
1629
// if (s != null) try {
1630
// result = s.getPrimaryIndex();
1631
// } catch (StorageException e) {
1632
// result = null;
1633
// }
1634
// }
1635
return result;
1636    }
1637    
1638    private MultivaluedIndex getObjectsByClassesByMofId (org.netbeans.mdr.persistence.MOFID mofId) {
1639        String JavaDoc storageId = getStorageIdFromMofId (mofId);
1640        if (storageId == null) {
1641            return null;
1642        }
1643        return (MultivaluedIndex) this.objByCls.get (storageId);
1644    }
1645    
1646    private SinglevaluedIndex getPropertiesIndexByStorageId (String JavaDoc storageId) {
1647        return (SinglevaluedIndex) this.properties.get(storageId);
1648    }
1649    
1650    public static String JavaDoc getStorageIdFromMofId(org.netbeans.mdr.persistence.MOFID mofId) {
1651        return mofId.getStorageID ();
1652    }
1653    
1654    /* -------------------------------------------------------------------- */
1655    /* -- Implementation of org.netbeans.mdr.persistence.ObjectResolver --- */
1656    /* -------------------------------------------------------------------- */
1657    
1658    /** Resolves object specified by storage id and key.
1659     * @param uuid of storage, where an object resides
1660     * @param key key
1661     * @return resolved object
1662     */

1663    public Object JavaDoc resolve(String JavaDoc storageID, Object JavaDoc key) throws StorageException {
1664        SinglevaluedIndex objectsIndex = (SinglevaluedIndex) this.objects.get(storageID);
1665        if (objectsIndex == null)
1666            return null;
1667        synchronized (getStorageById(storageID)) {
1668            return objectsIndex.get(key);
1669        }
1670    }
1671    
1672    public synchronized Storage getTransientStorage () throws StorageException {
1673        if (this.transientStorage == null) {
1674            this.transientStorage = new org.netbeans.mdr.storagemodel.transientimpl.TransientStorage ("TransientStorage");
1675            this.transientStorage.create(false, this);
1676            this.objects.put (org.netbeans.mdr.storagemodel.transientimpl.TransientStorage.STORAGE_ID, transientStorage.getPrimaryIndex ());
1677            this.objByCls.put (org.netbeans.mdr.storagemodel.transientimpl.TransientStorage.STORAGE_ID, transientStorage.createMultivaluedIndex (IDX_OBJECTS_BY_CLASSES, Storage.EntryType.MOFID, Storage.EntryType.MOFID, false));
1678            this.transientStorage.commitChanges (); // Commit indexes creation, it is save to call commit on the storage, because it was not used before
1679
this.storages.put (org.netbeans.mdr.storagemodel.transientimpl.TransientStorage.STORAGE_ID, transientStorage);
1680        }
1681        return this.transientStorage;
1682    }
1683    
1684    public static boolean isTransientMofId(org.netbeans.mdr.persistence.MOFID mofId) {
1685        String JavaDoc storageID = getStorageIdFromMofId(mofId);
1686        return org.netbeans.mdr.storagemodel.transientimpl.TransientStorage.STORAGE_ID.equals(storageID);
1687    }
1688    
1689    /* -------------------------------------------------------------------- */
1690    /* -- MdrStorage.ValuesObject (inner class) --------------------------- */
1691    /* -------------------------------------------------------------------- */
1692    
1693    /**
1694     * A <code>ValuesObject</code> manages a unique list of values.
1695     */

1696    public static class ValuesObject implements Streamable, StorageClient {
1697        private Storage storage;
1698        private org.netbeans.mdr.persistence.MOFID id;
1699        
1700        /** The list of values managed by this object. */
1701        private List list = new ArrayList();
1702        
1703        /** Maps managed objects to their indices in <code>list</code>,
1704         * to monitor uniqueness. */

1705        private final transient Map map = new HashMap();
1706        
1707        /**
1708         * Constructor for the recreation of this object from a stream.
1709         */

1710        public ValuesObject() {
1711        }
1712        
1713        /**
1714         * Constructor for the initial creation of this object.
1715         *
1716         * @param storage the storage for which this object is created
1717         * @param id the id of the object in the storage
1718         */

1719        private ValuesObject(Storage storage, org.netbeans.mdr.persistence.MOFID id) {
1720            this.storage = storage;
1721            this.id = id;
1722        }
1723        
1724        
1725        /**
1726         * Called by the {@link org.netbeans.persistence.Storage} implementation
1727         * when it creates this object.
1728         */

1729        public void setStorage(Storage storage) {
1730            this.storage = storage;
1731        }
1732        
1733        // this is always called from a synchronized section
1734
/**
1735         * Adds <code>value</code> to the list of objects managed by this
1736         * <code>ValuesObject</code>. Returns the index of the newly added
1737         * object. If <code>value</code> is already managed by this object, it
1738         * is not added, only the index is returned.
1739         *
1740         * @param value the object to be added to this <code>ValuesObject</code>
1741         * @return the index of <code>value</code>, always <code>&gt;= 1</code>.
1742         */

1743        public int store(Object JavaDoc value) {
1744            if (value == null) return 0;
1745            try {
1746                storage.objectStateWillChange(id);
1747                Object JavaDoc index = new Integer JavaDoc(map.size());
1748                Object JavaDoc old = map.put(value, index);
1749                if (old != null) {
1750                    map.put(value, old);
1751                    index = old;
1752                } else {
1753                    list.add(value);
1754                    storage.objectStateChanged(id);
1755                }
1756                return ((Integer JavaDoc) index).intValue() + 1;
1757            } catch (StorageException e) {
1758                throw (DebugException) Logger.getDefault().annotate(new DebugException(), e);
1759            }
1760        }
1761        
1762        // this is always called from a synchronized section
1763
/**
1764         * Returns the object with the given index.
1765         *
1766         * @param index an index (<code>&gt;= 1</code>) of a managed object
1767         * or <code>0</code>
1768         * @return the managed object with the given index or <code>null</code>
1769         * for index <code>0</code>
1770         * @throws IndexOutOfBoundsException if <code>index</code> is out of range
1771         */

1772        public Object JavaDoc resolve(int index) {
1773            if (index == 0) return null;
1774            return list.get(index - 1);
1775        }
1776        
1777        // this is always called from a synchronized section
1778
/**
1779         * Returns the index of the managed object <code>value</code>.
1780         *
1781         * @param value the object the index of which has to be returned
1782         * @return the index of <code>value</code> (always <code>&gt;= 1</code>)
1783         * or <code>0</code> if <code>value == null</code>
1784         * @throws Exception if <code>value</code> is neither managed by this
1785         * object nor <code>null</code>
1786         */

1787        public int indexOf(Object JavaDoc value) {
1788            if (value == null) return 0;
1789            Integer JavaDoc result = (Integer JavaDoc) map.get(value);
1790            if (result == null) {
1791                throw new DebugException("Value not found: " + value);
1792            }
1793            return result.intValue() + 1;
1794        }
1795        
1796        /** Restore state of the {@link org.netbeans.mdr.persistence.Streamable}
1797         * object from the stream.
1798         * @param inputStream InputStream that represents an internal representation of fields of a Streamable object
1799         * in which it was written by {@link write } method
1800         */

1801        public void read(java.io.InputStream JavaDoc inputStream) throws StorageException {
1802            try {
1803                id = IOUtils.readMOFID (inputStream, this.storage);
1804                list = (List) IOUtils.read(inputStream);
1805                for (int i = 0; i < list.size(); i++) {
1806                    map.put(list.get(i), new Integer JavaDoc(i));
1807                }
1808            } catch (IOException JavaDoc e) {
1809                throw (DebugException) Logger.getDefault().annotate(new DebugException(), e);
1810            }
1811        }
1812        
1813        /** This method will be used to move changed object from storage cache
1814         * to the persistent part of storage. It writes the object`s state
1815         * (set of attributes) in the stream as an array of bytes, for example
1816         * in textual representation.
1817         * @param outputStream OutputStream that holds value of a
1818         * {@link org.netbeans.mdr.persistence.Streamable} object
1819         */

1820        public void write(java.io.OutputStream JavaDoc outputStream) throws StorageException {
1821            try {
1822                IOUtils.writeMOFID (outputStream, id, this.storage);
1823                IOUtils.write(outputStream, list);
1824            } catch (IOException JavaDoc e) {
1825                throw (DebugException) Logger.getDefault().annotate(new DebugException(), e);
1826            }
1827        }
1828    }
1829
1830    private class InstanceMap extends HashMap {
1831        private final ReferenceQueue JavaDoc queue = new ReferenceQueue JavaDoc();
1832
1833        private class InstanceReference extends WeakReference JavaDoc {
1834            private Object JavaDoc key;
1835
1836            public InstanceReference(Object JavaDoc key, Object JavaDoc instance) {
1837                super(instance, queue);
1838                this.key = key;
1839            }
1840
1841            public Object JavaDoc getKey() {
1842                return key;
1843            }
1844        }
1845
1846        private void cleanUp() {
1847            InstanceMap.InstanceReference reference;
1848
1849            while ((reference = (InstanceMap.InstanceReference) queue.poll()) != null) {
1850// Logger.getDefault().log("Removing: " + reference.getProxyMofId());
1851
Object JavaDoc key = reference.getKey();
1852                Reference JavaDoc currentRef = (Reference JavaDoc) super.remove(key);
1853                if (currentRef != null && currentRef != reference && currentRef.get() != null) {
1854                    super.put(key, currentRef);
1855                }
1856            }
1857        }
1858
1859        public Object JavaDoc put(Object JavaDoc key, Object JavaDoc value) {
1860            cleanUp();
1861            Object JavaDoc result = super.put(key, new InstanceMap.InstanceReference(key, value));
1862            if (result != null) {
1863                return ((InstanceMap.InstanceReference) result).get();
1864            } else {
1865                return result;
1866            }
1867        }
1868
1869        public Object JavaDoc get(Object JavaDoc key) {
1870            cleanUp();
1871            Object JavaDoc result = super.get(key);
1872            if (result != null) {
1873                return ((InstanceMap.InstanceReference) result).get();
1874            } else {
1875                return result;
1876            }
1877        }
1878
1879        public Collection values() {
1880            ArrayList result = new ArrayList();
1881            cleanUp();
1882            for (Iterator it = super.values().iterator(); it.hasNext();) {
1883                result.add(((InstanceMap.InstanceReference) it.next()).get());
1884            }
1885            return result;
1886        }
1887    }
1888}
1889
Popular Tags