KickJava   Java API By Example, From Geeks To Geeks.

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


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 java.util.*;
22 import javax.jmi.reflect.*;
23 import javax.jmi.model.*;
24 import java.io.*;
25
26 import org.netbeans.mdr.handlers.*;
27 import org.netbeans.mdr.persistence.*;
28 import org.netbeans.mdr.util.*;
29 import org.netbeans.mdr.handlers.gen.TagSupport;
30
31 /** Storage object representing association proxy.
32  *
33  * @author Martin Matula, Pavel Buzek
34  * @version 0.2
35  */

36 public class StorableAssociation extends StorableBaseObject implements Streamable {
37
38     /** Storage index for the first end (initialized lazily by <code>getIndex</code> method) */
39     private transient Index aIndex;
40     /** Storage index for the second end (initialized lazily by <code>getIndex</code> method) */
41     private transient Index bIndex;
42     /** name of the first end */
43     private String JavaDoc endA;
44     /** name of the second end */
45     private String JavaDoc endB;
46
47     private org.netbeans.mdr.persistence.MOFID endAId;
48     private org.netbeans.mdr.persistence.MOFID endBId;
49
50     private transient boolean multiValuedA;
51     private transient boolean multiValuedB;
52
53     private int minA, maxA;
54     private int minB, maxB;
55     private transient Class JavaDoc typeA;
56     private transient Class JavaDoc typeB;
57     private int typeANameIndex;
58     private int typeBNameIndex;
59     private boolean orderedA;
60     private boolean orderedB;
61     private boolean aggrA;
62     private boolean aggrB;
63     private boolean indexedA, indexedB;
64     private Class JavaDoc associationSuperclass = null;
65     private final Object JavaDoc superclassMutex = new Object JavaDoc();
66
67     /** Creates new instance of association proxy.
68      * This default constructor is to be called only when deserializing the association proxy.
69      * Calling this constructor should be followed by <code>read</code> method invokation.
70      */

71     public StorableAssociation() {
72         super();
73     }
74
75     /** Replaces MOFIDs using the passed map. (This method is used when rebuilding metaobjects.)
76      * @param table Map of old MOFIDs to new MOFIDs.
77      */

78     protected void replaceValues(Map table) {
79         objectWillChange();
80
81         super.replaceValues(table);
82         endAId = (org.netbeans.mdr.persistence.MOFID) table.get(endAId);
83         endBId = (org.netbeans.mdr.persistence.MOFID) table.get(endBId);
84
85         objectChanged();
86     }
87
88     /** Creates new instance of association proxy providing all needed arguments.
89      * @param mdrStorage parent storage of created association proxy being created
90      * @param immediatePackage MOFID of association proxy immediate package
91      * @param MOFID of meta association proxy meta object
92      * @param endAMofid MOFID of the first association end
93      * @param endBMofid MOFID of the second association end
94      * @param multiValuedA <code>true</code> if the first end is multivalued
95      * @param multiValuedB <code>true</code> if the second end is multivalued
96      * @param orderedA <code>true</code> if the first end is ordered
97      * @param orderedB <code>true</code> if the second end is ordered
98      * @param uniqueA <code>true</code> if the first end is unique
99      * @param uniqueB <code>true</code> if the second end is unique
100      * @param aggrA <code>true</code> if the first end is aggregate
101      * @param aggrB <code>true</code> if the second end is aggregate
102      * @throws StorageException problem in storage occurred during association proxy creation
103      */

104     public StorableAssociation(MdrStorage mdrStorage, org.netbeans.mdr.persistence.MOFID immediatePackage, org.netbeans.mdr.persistence.MOFID meta,
105         String JavaDoc endA, org.netbeans.mdr.persistence.MOFID endAId, String JavaDoc endB, org.netbeans.mdr.persistence.MOFID endBId, Class JavaDoc typeA, Class JavaDoc typeB,
106         int minA, int maxA, int minB, int maxB, boolean orderedA, boolean orderedB,
107         boolean uniqueA, boolean uniqueB, boolean aggrA, boolean aggrB,
108         boolean indexedA, boolean indexedB) throws StorageException {
109
110             super(mdrStorage, immediatePackage, meta);
111
112         //Logger.getDefault().log("association: endA: " + endA + ", endB: " + endB);
113
this.endA = endA;
114         this.endB = endB;
115         this.endAId = endAId;
116         this.endBId = endBId;
117         this.orderedA = orderedA;
118         this.orderedB = orderedB;
119         this.multiValuedA = (maxA != 1);
120         this.multiValuedB = (maxB != 1);
121         this.aggrA = aggrA;
122         this.aggrB = aggrB;
123         this.minA = minA;
124         this.minB = minB;
125         this.maxA = maxA;
126         this.maxB = maxB;
127         this.typeA = typeA;
128         this.typeB = typeB;
129         this.indexedA = indexedA;
130         this.indexedB = indexedB;
131         this.typeANameIndex = mdrStorage.values(this.getMofId()).store(typeA.getName());
132         this.typeBNameIndex = mdrStorage.values(this.getMofId()).store(typeB.getName());
133         aIndex = createIndex(multiValuedA, orderedA, uniqueA, 1);
134         bIndex = createIndex(multiValuedB, orderedB, uniqueB, 2);
135
136         getMdrStorage().addObject(this);
137         initFinished = true;
138     }
139     
140     public Class JavaDoc getAssociationSuperclass() throws StorageException, ClassNotFoundException JavaDoc {
141         if (associationSuperclass == null) {
142             synchronized (superclassMutex) {
143                 if (associationSuperclass == null) {
144                     objectWillChange();
145                     associationSuperclass = resolveAssociationSuperclass();
146                     objectChanged();
147                 }
148             }
149         }
150         return associationSuperclass;
151     }
152     
153     private Class JavaDoc resolveAssociationSuperclass() throws StorageException, ClassNotFoundException JavaDoc {
154         try {
155             return BaseObjectHandler.resolveImplementation(TagSupport.getImplFullName(getMetaObject(), TagSupport.ASSOCIATION));
156         } catch (ClassNotFoundException JavaDoc e) {
157 // if (((Boolean) getMetaObject().getAttribute(MOFConstants.SH_MODEL_ASSOCIATION_IS_DERIVED)).booleanValue())
158
// throw e;
159
return AssociationHandler.class;
160         }
161     }
162
163     public Class JavaDoc getAssociationCustomImpl() {
164         try {
165             Class JavaDoc sup = getAssociationSuperclass();
166             return sup == AssociationHandler.class ? null : sup;
167         } catch (Exception JavaDoc e) {}
168         return null;
169     }
170
171     /** Returns multiplicity of the first association end.
172      * @return <code>true</code> if the upper bound of association end is greater than 1
173      */

174     public boolean isMultivaluedA () {
175         return multiValuedA;
176     }
177
178     /** Returns multiplicity of the second association end.
179      * @return <code>true</code> if the upper bound of association end is greater than 1
180      */

181     public boolean isMultivaluedB () {
182         return multiValuedB;
183     }
184
185     /** Returns <code>true</code> if the first association end is ordered.
186      * @return <code>true</code> if the association end is ordered
187      */

188     public boolean isOrderedA () {
189         return orderedA;
190     }
191
192     /** Returns <code>true</code> if the second association end is ordered.
193      * @return <code>true</code> if the association end is ordered
194      */

195     public boolean isOrderedB () {
196         return orderedB;
197     }
198
199     /**
200      * @return
201      */

202     public boolean isAggregateA() {
203         return aggrA;
204     }
205
206     /**
207      * @return
208      */

209     public boolean isAggregateB() {
210         return aggrB;
211     }
212
213     /** Returns <code>true</code> if the first association end is indexed.
214      * @return <code>true</code> if the association end is indexed
215      */

216     public boolean isIndexedA() {
217         return indexedA;
218     }
219
220     /** Returns <code>true</code> if the second association end is indexed.
221      * @return <code>true</code> if the association end is indexed
222      */

223     public boolean isIndexedB() {
224         return indexedB;
225     }
226
227     /**
228      * @return
229      */

230     public String JavaDoc getEnd1Name() {
231         return this.endA;
232     }
233
234     /**
235      * @return
236      */

237     public String JavaDoc getEnd2Name() {
238         return this.endB;
239     }
240     
241     public org.netbeans.mdr.persistence.MOFID getEnd1Id () {
242         return this.endAId;
243     }
244     
245     public org.netbeans.mdr.persistence.MOFID getEnd2Id () {
246         return this.endBId;
247     }
248
249     /**
250      * @param a
251      * @param b
252      * @throws StorageException
253      * @return
254      */

255     public boolean linkExists (org.netbeans.mdr.persistence.MOFID a, org.netbeans.mdr.persistence.MOFID b) throws StorageException {
256         if (isMultivaluedB()) {
257             return ((MultivaluedIndex) bIndex).getItems(a).contains(b);
258         } else {
259             return b.equals(((SinglevaluedIndex) bIndex).getIfExists(a));
260         }
261     }
262
263     /**
264      * Returns immutable, live collection of all links managed by this association
265      * proxy.
266      *
267      * @throws StorageException
268      * @return immutable, live collection of all links
269      */

270     public Collection getAllLinks() throws StorageException {
271         return new LinkSetCollection();
272     }
273
274     /**
275      * @param endMofid
276      * @param obj
277      * @throws StorageException
278      * @return
279      */

280     public Object JavaDoc queryObjects(String JavaDoc endName, org.netbeans.mdr.persistence.MOFID obj) throws StorageException {
281         //Logger.getDefault().log("query: end: " + endName + ", endA:" + endA + ", endB:" + endB);
282
boolean isEndA = endName.equals(endB);
283         boolean multi = isEndA ? multiValuedA : multiValuedB;
284         boolean order = isEndA ? orderedA : orderedB;
285         Index index = isEndA ? aIndex : bIndex;
286         Index secondIndex = isEndA ? bIndex : aIndex;
287         Class JavaDoc type = isEndA ? typeA : typeB;
288         int max = isEndA ? maxA : maxB;
289         org.netbeans.mdr.persistence.MOFID endId, otherEndId;
290         boolean isIndexed, isOtherIndexed;
291         if (isEndA) {
292             endId = endAId;
293             otherEndId = endBId;
294             isIndexed = indexedA;
295             isOtherIndexed = indexedB;
296         } else {
297             endId = endBId;
298             otherEndId = endAId;
299             isIndexed = indexedB;
300             isOtherIndexed = indexedA;
301         }
302         boolean aggr = isEndA ? aggrA : aggrB;
303         boolean otherAggr = isEndA ? aggrB : aggrA;
304         
305         Object JavaDoc result;
306         if (obj == null) throw new NullPointerException JavaDoc();
307
308         if (multi) {
309             if (order) {
310                 result = new AssocEndIndexUList(this, endId, otherEndId, (MultivaluedOrderedIndex) index, obj, secondIndex, type, max, true, aggr, otherAggr, isIndexed, isOtherIndexed);
311             } else {
312                 result = new AssocEndIndexSet(this, endId, otherEndId, (MultivaluedIndex) index, obj, secondIndex, type, max, true, aggr, otherAggr, isIndexed, isOtherIndexed);
313             }
314         } else {
315             result = getMdrStorage().getObjectFromIndexIfExists((SinglevaluedIndex) index, obj);
316         }
317         return result;
318     }
319     
320     public void verify(Collection violations) throws StorageException {
321         try {
322             if (getAssociationSuperclass() == AssociationHandler.class) {
323                 for (Iterator it = aIndex.keySet().iterator(); it.hasNext();) {
324                     verifyEnd(violations, endB, (org.netbeans.mdr.persistence.MOFID) it.next());
325                 }
326                 for (Iterator it = bIndex.keySet().iterator(); it.hasNext();) {
327                     verifyEnd(violations, endA, (org.netbeans.mdr.persistence.MOFID) it.next());
328                 }
329             }
330         } catch (ClassNotFoundException JavaDoc e) {
331             throw (DebugException) Logger.getDefault().annotate(new DebugException(), e);
332         }
333     }
334     
335     public void verifyEnd(Collection violations, String JavaDoc end, org.netbeans.mdr.persistence.MOFID object) throws StorageException {
336         try {
337             if (getAssociationSuperclass() == AssociationHandler.class) {
338                 int min = end.equals(endB) ? minA : minB;
339                 org.netbeans.mdr.persistence.MOFID endId = end.equals(endB) ? endAId : endBId;
340                 Object JavaDoc result = queryObjects(end, object);
341                 if ((result == null && min > 0) ||
342                     (result instanceof Collection && ((Collection) result).size() < min)) {
343                         violations.add(new WrongSizeException((RefObject) getMdrStorage().getRepository().getHandler(getMdrStorage().getObject(endId)),
344                             "Not enough objects linked to " + object + " at end '" + end + "'."));
345                 }
346             }
347         } catch (ClassNotFoundException JavaDoc e) {
348             throw (DebugException) Logger.getDefault().annotate(new DebugException(), e);
349         }
350     }
351     
352     public void checkType(Object JavaDoc endA, Object JavaDoc endB) {
353         try {
354             if (endA != null && !typeA.isInstance(endA)) {
355                 throw new TypeMismatchException(typeB, endB,
356                     (RefObject) getMdrStorage().getRepository().getHandler(getMdrStorage().getObject(endBId)));
357             } else if (endB != null && !typeB.isInstance(endB)) {
358                 throw new TypeMismatchException(typeB, endB,
359                     (RefObject) getMdrStorage().getRepository().getHandler(getMdrStorage().getObject(endBId)));
360             }
361         } catch (StorageException e) {
362             throw (DebugException) Logger.getDefault().annotate(new DebugException(), e);
363         }
364         throw new DebugException();
365     }
366     
367     /**
368      * @param a
369      * @param b
370      * @throws StorageException
371      */

372     public boolean addLink (org.netbeans.mdr.persistence.MOFID a, org.netbeans.mdr.persistence.MOFID b) throws StorageException {
373         if (multiValuedA) {
374             return ((Collection) queryObjects(endB, b)).add(a);
375         } else if (multiValuedB) {
376             return ((Collection) queryObjects(endA, a)).add(b);
377         } else {
378             try {
379                 StorableObject oA = null, oB = null;
380                 oA = (StorableObject) getMdrStorage().getObject(a);
381                 oB = (StorableObject) getMdrStorage().getObject(b);
382                 if (indexedA) {
383                     oB.removeFromIndex (endAId);
384                 }
385                 if (indexedB) {
386                     oA.removeFromIndex (endBId);
387                 }
388                 // set composites
389
if (aggrA) {
390                     oB.setComposite(oA, a, endAId);
391                 } else if (aggrB) {
392                     oA.setComposite(oB, b, endBId);
393                 }
394                 aIndex.add(b, a);
395                 bIndex.add(a, b);
396                 if (indexedA) {
397                     oB.addToIndex (endAId);
398                 }
399                 if (indexedB) {
400                     oA.addToIndex (endBId);
401                 }
402
403                 return true;
404             } catch (StorageBadRequestException e) {
405                 // ignore
406
return false;
407             }
408         }
409     }
410
411     /**
412      * @param a
413      * @param b
414      * @throws StorageException
415      */

416     public boolean removeLink (org.netbeans.mdr.persistence.MOFID a, org.netbeans.mdr.persistence.MOFID b) throws StorageException {
417         try {
418             StorableObject oA = null, oB = null;
419             oA = (StorableObject) getMdrStorage().getObject(a);
420             oB = (StorableObject) getMdrStorage().getObject(b);
421             if (indexedA) {
422                 oB.removeFromIndex (endAId);
423             }
424             if (indexedB) {
425                 oA.removeFromIndex (endBId);
426             }
427             // remove composites
428
if (aggrA) {
429                 oB.clearComposite();
430             } else if (aggrB) {
431                 oA.clearComposite();
432             }
433             removeLinkEnd(b, a, aIndex, multiValuedA);
434             removeLinkEnd(a, b, bIndex, multiValuedB);
435             if (indexedA) {
436                 oB.addToIndex (endAId);
437             }
438             if (indexedB) {
439                 oA.addToIndex (endBId);
440             }
441             return true;
442         } catch (StorageBadRequestException e) {
443             return false;
444         }
445     }
446
447     protected Index getIndex(String JavaDoc end) throws StorageException {
448         if (end.equals(endA)) {
449             return aIndex;
450         } else if (end.equals(endB)) {
451             return bIndex;
452         } else {
453             return null;
454         }
455     }
456
457     /** Find the appropriate index in the storage.
458     */

459     protected Index findIndex(int end) throws StorageException {
460         return getMdrStorage().getIndex(getOutermostPackageId(), getMofId(), end);
461     }
462
463     /**
464      * @param a
465      * @param b
466      * @param end
467      * @param multi
468      * @param order
469      * @throws StorageException
470      */

471     private void removeLinkEnd (org.netbeans.mdr.persistence.MOFID a, org.netbeans.mdr.persistence.MOFID b, Index index, boolean multi) throws StorageException {
472         if (multi) {
473             ((MultivaluedIndex) index).remove(a, b);
474         } else {
475             ((SinglevaluedIndex) index).remove(a);
476         }
477     }
478
479     /**
480      * @param multi
481      * @param ordered
482      * @param unique
483      * @param end
484      * @throws StorageException
485      * @return
486      */

487     protected Index createIndex (boolean multi, boolean ordered, boolean unique, int end) throws StorageException {
488         if (multi) {
489             if (ordered) {
490                 return getMdrStorage().createMultivaluedOrderedIndex(getOutermostPackageId(), getMofId(), end, Storage.EntryType.MOFID, Storage.EntryType.MOFID, unique);
491             } else {
492                 return getMdrStorage().createMultivaluedIndex(getOutermostPackageId(), getMofId(), end, Storage.EntryType.MOFID, Storage.EntryType.MOFID, unique);
493             }
494         } else {
495             return getMdrStorage().createSinglevaluedIndex (getOutermostPackageId(), getMofId(), end, Storage.EntryType.MOFID, Storage.EntryType.MOFID);
496         }
497     }
498     
499     protected void deleteIndex (org.netbeans.mdr.persistence.MOFID opkgId, org.netbeans.mdr.persistence.MOFID mofId, int index) throws StorageException {
500         getMdrStorage().dropIndex(opkgId, mofId, index);
501     }
502
503     protected void deleteRecursive() throws StorageException {
504         deleteIndex (getOutermostPackageId(), getMofId(), 1);
505         deleteIndex (getOutermostPackageId(), getMofId(), 2);
506         super.deleteRecursive();
507     }
508
509     /**
510      * @param outputStream
511      * @throws StorageException
512      */

513     public void write(java.io.OutputStream JavaDoc outputStream) {
514 // if (endA == null || endB == null || endAId == null || endBId == null) throw new NullPointerException();
515

516         super.write (outputStream);
517
518         try {
519             IOUtils.write (outputStream, meta, this);
520             IOUtils.write (outputStream, immediatePackage, this);
521             IOUtils.writeString(outputStream, endA);
522             IOUtils.writeString(outputStream, endB);
523             IOUtils.write (outputStream, endAId, this);
524             IOUtils.write (outputStream, endBId, this);
525             IOUtils.writeInt(outputStream, minA);
526             IOUtils.writeInt(outputStream, maxA);
527             IOUtils.writeInt(outputStream, minB);
528             IOUtils.writeInt(outputStream, maxB);
529             IOUtils.writeBoolean(outputStream, aggrA);
530             IOUtils.writeBoolean(outputStream, aggrB);
531             IOUtils.writeBoolean(outputStream, orderedA);
532             IOUtils.writeBoolean(outputStream, orderedB);
533             IOUtils.writeInt(outputStream, typeANameIndex);
534             IOUtils.writeInt(outputStream, typeBNameIndex);
535             IOUtils.writeBoolean(outputStream, indexedA);
536             IOUtils.writeBoolean(outputStream, indexedB);
537         } catch (java.io.IOException JavaDoc e) {
538             Logger.getDefault().notify(Logger.INFORMATIONAL, e);
539         }
540     }
541
542     /**
543      * @param inputStream
544      * @throws StorageException
545      */

546     public void read(java.io.InputStream JavaDoc inputStream) {
547         super.read (inputStream);
548         try {
549             meta = (org.netbeans.mdr.persistence.MOFID) IOUtils.read (inputStream,this);
550             immediatePackage = (org.netbeans.mdr.persistence.MOFID) IOUtils.read (inputStream, this);
551
552             endA = IOUtils.readString(inputStream);
553             endB = IOUtils.readString(inputStream);
554             endAId = (org.netbeans.mdr.persistence.MOFID) IOUtils.read (inputStream, this);
555             endBId = (org.netbeans.mdr.persistence.MOFID) IOUtils.read (inputStream, this);
556             minA = IOUtils.readInt(inputStream);
557             maxA = IOUtils.readInt(inputStream);
558             minB = IOUtils.readInt(inputStream);
559             maxB = IOUtils.readInt(inputStream);
560             multiValuedA = (maxA != 1);
561             multiValuedB = (maxB != 1);
562             aggrA = IOUtils.readBoolean(inputStream);
563             aggrB = IOUtils.readBoolean(inputStream);
564             orderedA = IOUtils.readBoolean(inputStream);
565             orderedB = IOUtils.readBoolean(inputStream);
566             typeANameIndex = IOUtils.readInt(inputStream);
567             typeBNameIndex = IOUtils.readInt(inputStream);
568             aIndex = findIndex(1);
569             bIndex = findIndex(2);
570             typeA = BaseObjectHandler.resolveInterface((String JavaDoc) getMdrStorage().values(this.getMofId()).resolve(typeANameIndex));
571             typeB = BaseObjectHandler.resolveInterface((String JavaDoc) getMdrStorage().values(this.getMofId()).resolve(typeBNameIndex));
572             indexedA = IOUtils.readBoolean(inputStream);
573             indexedB = IOUtils.readBoolean(inputStream);
574         } catch (java.io.IOException JavaDoc e) {
575             throw (DebugException) Logger.getDefault().annotate(new DebugException(), e);
576         } catch (StorageException ex) {
577             throw (DebugException) Logger.getDefault().annotate(new DebugException(), ex);
578         } catch (ClassNotFoundException JavaDoc e) {
579             throw (DebugException) Logger.getDefault().annotate(new DebugException(), e);
580         }
581     }
582     
583     /* --------------------------------------------------------------------- */
584     /* -- LinkSetCollection (inner class) ---------------------------------- */
585     /* --------------------------------------------------------------------- */
586     
587     protected class LinkSetCollection extends AbstractCollection {
588         
589         public Iterator iterator() {
590             return new LinkSetIterator();
591         }
592         
593         public int size() {
594             try {
595                 int size = 0;
596                 for (Iterator as = bIndex.keySet().iterator(); as.hasNext();) {
597                     MOFID aID = (MOFID) as.next();
598                     // fetch the first b for the given a, if exists
599
if ( isMultivaluedB() ) {
600                         size += getMdrStorage().getObjectsFromIndex((MultivaluedIndex) bIndex, aID).size();
601                     } else {
602                         size++;
603                     }
604                 }
605                 return size;
606             } catch (StorageException se) {
607                 throw (DebugException) Logger.getDefault().annotate(new DebugException(), se);
608             }
609         }
610     }
611     
612     /* --------------------------------------------------------------------- */
613     /* -- LinkSetIterator (inner class) ------------------------------------ */
614     /* --------------------------------------------------------------------- */
615     
616     protected class LinkSetIterator implements Iterator {
617
618         boolean initialized = false;
619         
620         /**
621          * Iterator through all instances at the a-side of this association or
622          * <code>null</code> before the first access or if a storage problem
623          * occured.
624          */

625         Iterator as = null;
626         
627         /**
628          * MOF ID of the current instance at the a side. <code>null</code>
629          * only before the first call to <code>fetchNext()</code>.
630          */

631         org.netbeans.mdr.persistence.MOFID aID = null;
632         
633         /**
634          * Object with ID <code>aID</code> or <code>null</code> if not yet
635          * retrieved.
636          */

637         StorableObject a = null;
638         
639         /**
640          * If the association if multi-valued at b's end, <code>bs</code>
641          * contains the iterator for the b's associated with the current a.
642          * Shall only be accessed inside <code>fetchNext()</code>.
643          */

644         Iterator bs = null;
645         
646         /**
647          * The current b object, <code>null</code> initially and after the
648          * last link has been retrieved.
649          */

650         StorableObject b = null;
651         
652         private void initCheck() {
653             if ( ! initialized ) {
654                 initialized = true;
655                 try {
656                     as = bIndex.keySet().iterator();
657                 } catch ( StorageException se ) {
658                     // [XXX]: probably throw a DebugException here
659
as = null;
660                 }
661                 fetchNext();
662             }
663         }
664         
665         private void fetchNext() {
666             if ( as == null ) {
667                 return;
668             }
669             b = null;
670             // check if there is yet another b for the current a
671
if ( bs != null ) {
672                 if ( bs.hasNext() ) {
673                     b = (StorableObject) bs.next();
674                     return;
675                 }
676             }
677             
678             try {
679                 // fetch the next a
680
while ( as.hasNext() ) {
681                     aID = (org.netbeans.mdr.persistence.MOFID) as.next();
682                     a = null;
683                     // fetch the first b for the given a, if exists
684
if ( isMultivaluedB() ) {
685                         bs = getMdrStorage().getObjectsFromIndex((MultivaluedIndex) bIndex, aID).iterator();
686                         if ( bs.hasNext() ) {
687                             b = (StorableObject) bs.next();
688                         }
689                     } else {
690                         b = (StorableObject) getMdrStorage().getObjectFromIndexIfExists((SinglevaluedIndex) bIndex, aID);
691                     }
692                     // check, if a b was found, return, if yes
693
if ( b != null ) {
694                         return;
695                     }
696                 }
697             } catch (StorageException se) {
698                 // [XXX]: probably throw a DebugException here
699
as = null;
700                 b = null;
701             }
702             
703             // there are not more links !
704
return;
705         }
706         
707         public boolean hasNext() {
708             initCheck();
709             return b != null;
710         }
711         
712         public Object JavaDoc next() {
713             initCheck();
714             if ( b == null ) {
715                 throw new NoSuchElementException();
716             }
717             if ( a == null ) {
718                 try {
719                     a = (StorableObject) getMdrStorage().getObject(aID);
720                 } catch (StorageException se) {
721                     // {XXX]: better exception handling
722
throw (DebugException) Logger.getDefault().annotate(new DebugException(), se);
723                 }
724             }
725             AssociationLink link = new AssociationLink(a,b);
726             fetchNext();
727             return link;
728         }
729         
730        /**
731         * operation not supported
732         */

733         public void remove() {
734             throw new UnsupportedOperationException JavaDoc();
735         }
736         
737     }
738 }
739
Popular Tags