KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > jonas_ejb > container > jorm > GenClassImpl


1 /*
2  * JOnAS: Java(TM) Open Application Server
3  * Copyright (C) 1999 Bull S.A.
4  * Contact: jonas-team@objectweb.org
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19  * USA
20  *
21  * Initial developer(s): Sebastien Chassande
22  * Contributor(s):
23  *
24  * --------------------------------------------------------------------------
25  * $Id: GenClassImpl.java,v 1.26 2005/04/28 16:52:59 benoitf Exp $
26  * --------------------------------------------------------------------------
27  */

28 package org.objectweb.jonas_ejb.container.jorm;
29
30 import java.util.ArrayList JavaDoc;
31 import java.util.Arrays JavaDoc;
32 import java.util.Iterator JavaDoc;
33 import java.util.NoSuchElementException JavaDoc;
34 import javax.ejb.EJBException JavaDoc;
35 import org.objectweb.jonas_ejb.container.JEntityFactory;
36 import org.objectweb.jonas_ejb.container.TraceEjb;
37 import org.objectweb.jorm.api.PBinding;
38 import org.objectweb.jorm.api.PClassMapping;
39 import org.objectweb.jorm.api.PException;
40 import org.objectweb.jorm.api.PExceptionProtocol;
41 import org.objectweb.jorm.api.PGenClassAccessor;
42 import org.objectweb.jorm.api.PIndexedElem;
43 import org.objectweb.jorm.naming.api.PBinder;
44 import org.objectweb.jorm.naming.api.PName;
45 import org.objectweb.jorm.naming.api.PNameManager;
46 import org.objectweb.jorm.naming.api.PExceptionNaming;
47 import org.objectweb.util.monolog.api.BasicLevel;
48
49
50 /**
51  * This class is a basic implementation of the PGenClassAccessor interface
52  * usefull for the multivalued relation.
53  *
54  * @author S.Chassande-Barrioz
55  */

56 public abstract class GenClassImpl implements PGenClassAccessor {
57
58     /**
59      * All elements of the gen class (unmodified, modified, created, deleted)
60      * This ArrayList contains GenClassElem objects
61      */

62     protected ArrayList JavaDoc pIndexedElems = null;
63
64     /**
65      * This array represents the distance between two deleted elements in the
66      * pIndexedElems arraylist. O means there is no element in the middle. The
67      * first element is in fact the quantity of existing element before the
68      * first deleted element.
69      * The size of this array is also the quantity of deleted elements. Then if
70      * the array is empty there is no deleted elements.
71      *
72      * for example: if this fields is equals to [3, 2] then the elements whith
73      * the index 3 and 6 are marked as deleted: [a, b, c, D, d, e, D, ....]
74      *
75      * This array is useless to convert an index valid inside the user/virtual
76      * collection to an index valid inside the 'pIndexedElems' ArrayList.
77      */

78     protected int[] deletedLength = null;
79
80     /**
81      * This is the size of the relation. This field is equal to the
82      * pIndexedElems size minus the quantity of deleted element. The value is
83      * always right and is updated during each delete or create action.
84      */

85     protected int size;
86
87     /**
88      * true when GenClass has been modified and must be written
89      */

90     protected boolean isModified = false;
91
92     /**
93      * This field references the PClassMapping which manages the persistency of
94      * this GenClass. (xxxGCM.java)
95      * This is actually a GenClassMapping, returned by the bean Factory (PClassMapping)
96      */

97     protected PClassMapping gcm = null;
98
99     /**
100      * This fields is the PBinding associated to this instance.
101      */

102     protected PBinding pb = null;
103
104     /**
105      * All the actions are send to this listener.
106      * There is 1 Listener for each GenClass, i.e. for each
107      * multi-valued CMR field. (See JEntityCmp2.vm)
108      * Used mainly for coherence.
109      */

110     protected GenClassListener listener = null;
111
112     /**
113      * UNUSED ???
114      */

115     public GenClassImpl(PClassMapping gcm) {
116         this();
117         this.gcm = gcm;
118     }
119
120     /**
121      * A GenClassImpl object is created for each Multi-Valued CMR field
122      * See JEntityCmp2.vm
123      * It starts with an empty list.
124      */

125     public GenClassImpl() {
126         pIndexedElems = new ArrayList JavaDoc(0);
127         size = 0;
128         deletedLength = new int[0];
129         isModified = false;
130     }
131
132     /**
133      * Set the PClassMapping for this GenClass. It's needed to get
134      * Connections for read and write operations.
135      * Used by JEntityCmp2.vm
136      * @param gcm the PClassMapping
137      */

138     public void setPClassMapping(PClassMapping gcm) {
139         this.gcm = gcm;
140     }
141
142     /**
143      * reset the GenClass to its initial state.
144      */

145     public void reset() {
146         pIndexedElems.clear();
147         size = 0;
148         deletedLength = new int[0];
149         isModified = false;
150     }
151
152     /**
153      * Set the PBinding that will be used for this GenClass
154      * Used by JEntityCmp2.vm
155      * @param pb The PBinding for this GenClass
156      */

157     public void setPBinding(PBinding pb) {
158         this.pb = pb;
159     }
160
161     /**
162      * Get the PBinding used for this GenClass
163      * Used by JEntityCmp2.vm
164      * @return The PBinding for this GenClass
165      */

166     public PBinding gcGetPBinding() {
167         return pb;
168     }
169
170     public void setListener(GenClassListener gcl) {
171         listener = gcl;
172     }
173
174     public GenClassListener getListener() {
175         return listener;
176     }
177
178     // IMPLEMENTATION OF THE Persitence lyfe cycle //
179
//---------------------------------------------//
180

181     public boolean gcIsModified() {
182         return isModified;
183     }
184
185     /**
186      * It loads the data of the gen class.
187      * @param pn is the PName of the genclass
188      * @param connection is a connection to access to the support. If it is null
189      * a connection is asked to the mapper and closed after its use.
190      */

191     public void read(PName pn, Object JavaDoc connection, Object JavaDoc tx) throws PException {
192         if (TraceEjb.genclass.isLoggable(BasicLevel.DEBUG)) {
193             TraceEjb.genclass.log(BasicLevel.DEBUG, "PName=" + pn);
194         }
195         if (pn == null || pn.isNull()) {
196             reset();
197             return;
198         }
199         if (pb == null) {
200             throw new PExceptionProtocol("Impossible to read a persitent object withoout PBinding");
201         }
202         // Allocate a connection if needed
203
Object JavaDoc conn = (connection == null
204                        ? gcm.getPMapper().getConnection()
205                        : connection);
206         if (TraceEjb.genclass.isLoggable(BasicLevel.DEBUG)) {
207             TraceEjb.genclass.log(BasicLevel.DEBUG, "Load the genclass");
208         }
209         pb.bind(pn);
210         pb.read(conn, this, tx);
211         //pb.unbind();
212
isModified = false;
213
214         // close the connection opened localy
215
if (connection == null) {
216             gcm.getPMapper().closeConnection(conn);
217         }
218     }
219
220     /**
221      * It writes the data of the gen class if it was modified (see the field
222      * isModified).
223      * @param pn is the PName of the genclass
224      * @param connection is a connection to access to the support. If it is null
225      * a connection is asked to the mapper and closed after its use.
226      */

227     public void write(PName pn, Object JavaDoc connection) throws PException {
228         if (TraceEjb.genclass.isLoggable(BasicLevel.DEBUG)) {
229             TraceEjb.genclass.log(BasicLevel.DEBUG, "");
230         }
231         //TraceEjb.genclass.log(BasicLevel.DEBUG, "begin"); printState();
232
if (pn == null || pn.isNull()) {
233             throw new PExceptionProtocol("Impossible to write a persitent object with a null PName: " + pn);
234         }
235         if (isModified) {
236             // Allocate a connection if needed
237
Object JavaDoc conn = (connection == null
238                            ? gcm.getPMapper().getConnection()
239                            : connection);
240
241             if (pb == null) {
242                 throw new PExceptionProtocol("Impossible to write a persitent object without PBinding");
243             }
244             if (TraceEjb.genclass.isLoggable(BasicLevel.DEBUG)) {
245                 TraceEjb.genclass.log(BasicLevel.DEBUG, "Store the genclass " + pn);
246             }
247             pb.bind(pn);
248             pb.write(conn, this);
249             //pb.unbind();
250

251             // The data are written on the support, then the memory instance is
252
// up to date. The element marked as removed must really be removed
253
// from the list.
254
isModified = false;
255             int pos = 0;
256             for (int i = 0; i < deletedLength.length; i++) {
257                 pos += deletedLength[i];
258                 pIndexedElems.remove(pos);
259             }
260             deletedLength = new int[0];
261             for (Iterator JavaDoc it = pIndexedElems.iterator(); it.hasNext();) {
262                 GenClassElement gce = (GenClassElement) it.next();
263                 gce.status = PIndexedElem.ELEM_UNMODIFIED;
264                 gce.hasBeenCreated = false;
265             }
266
267             // close the connection opened localy
268
if (connection == null) {
269                 gcm.getPMapper().closeConnection(conn);
270             }
271         }
272         //TraceEjb.genclass.log(BasicLevel.DEBUG, "end"); printState();
273
}
274
275     public void doNotWrite(PObject po) {
276         GenClassElement gce = null;
277         for (Iterator JavaDoc it = pIndexedElems.iterator(); it.hasNext() && gce == null;) {
278             gce = (GenClassElement) it.next();
279             if (gce.value != null) {
280                 if (po == gce.value) {
281                     break;
282                 }
283             } else if (gce.pname != null && gce.pname.equals(po.getPName())) {
284                 break;
285             }
286             gce = null;
287         }
288         if (gce == null) {
289             throw new EJBException JavaDoc("Impossible to mark the element as written "
290                                    + "because it does not be found in the GenClass: "
291                                    + po.getPName());
292         }
293         if (TraceEjb.genclass.isLoggable(BasicLevel.DEBUG)) {
294             TraceEjb.genclass.log(BasicLevel.DEBUG,
295                                   "assign ELEM_UNMODIFIED to " + po.getPName());
296         }
297         gce.status = PIndexedElem.ELEM_UNMODIFIED;
298     }
299
300     // IMPLEMENTATION OF THE PAccessor INTERFACE //
301
//-------------------------------------------//
302

303     /**
304      * In most of cases this class is extented to personalize to a collection
305      * type. Then an instance of this class is often the real collection.
306      */

307     public Object JavaDoc getMemoryInstance() {
308         return this;
309     }
310
311
312     // IMPLEMENTATION OF THE PGenClassAccessor INTERFACE //
313
//---------------------------------------------------//
314

315     /**
316      * It adds the elements in the list. This method is used by the PBinding to
317      * load the data.
318      * The elements is added at the end of the 'pIndexedElems' then
319      * 'deletedLength' is not impacted.
320      */

321     public void paAdd(PIndexedElem elem, Object JavaDoc conn) throws PException {
322         pIndexedElems.add(elem);
323         size++;
324         //TraceEjb.genclass.log(BasicLevel.DEBUG, "printState"); printState();
325
}
326
327     /**
328      * The default implementation of the PIndexedElem is GenClassElement.
329      * This method may be redefined for different GenClass implementations.
330      */

331     public PIndexedElem createPIndexedElem() {
332         return new GenClassElement(this);
333     }
334
335     /**
336      * This implementation is able to isolate the modification by element of the
337      * gen class.
338      */

339     public boolean paDeltaSupported() {
340         return true;
341     }
342
343     /**
344      * This method is used by the PBinding to allocated data structure during a
345      * write operation. The returned size must then contains also the deleted
346      * elements.
347      */

348     public int paGetNbElem() {
349         return pIndexedElems.size();
350     }
351
352     /**
353      * This method is used by the PBinding to fetch all PIndexedElem.
354      */

355     public Iterator JavaDoc paIterator() {
356         return pIndexedElems.iterator();
357     }
358
359     /**
360      * This method is call in first during a read operation in order to indicate
361      * the size of the gen class. if the value is equals to -1 then that means
362      * the data support is unable to known the size of the relation in advance.
363      * Then the previous size is kept. Otherwise the list is initialized to the
364      * specified size.
365      */

366     public void paSetNbElem(int nbelem) {
367         if (TraceEjb.genclass.isLoggable(BasicLevel.DEBUG)) {
368             TraceEjb.genclass.log(BasicLevel.DEBUG, "nbElem: " + nbelem);
369         }
370         if (nbelem == -1) {
371             pIndexedElems.clear();
372         } else {
373             pIndexedElems = new ArrayList JavaDoc(nbelem);
374         }
375         deletedLength = new int[0];
376         size = 0;
377     }
378
379
380     // METHODS USABLE FOR THE SUB CLASS //
381
//----------------------------------//
382

383     /**
384      * This method calculates the real index of an element.
385      * @param idx the index valid in the colllection
386      * @return an index valid into the 'pIndexedElems' ArrayList.
387      */

388     protected int gcGetRealIndex(int idx) {
389         int a = idx;
390         int i = 0;
391         while (i < deletedLength.length && (a -= deletedLength[i]) >= 0) {
392             i++;
393         }
394         return idx + i;
395     }
396
397     /**
398      * This method add a new element in the collection. A PIndexedElem is built
399      * via the 'createPIndexedElem' method. Then this instance is initialized
400      * with the element and the staus specified by the parameter 'status'.
401      * Before added the element, a checking is done. If the element was
402      * previously removed in the same transaction then the status of the
403      * removed element is changed to ELEM_UNMODIFIED. This optimization avoid
404      * two useless I/O.
405      *
406      * @param element the object to add
407      * @param callListener indicates if the gen class listener must be call
408      * about this action
409      */

410     protected void gcAdd(PObject element, boolean callListener) {
411         //TraceEjb.genclass.log(BasicLevel.DEBUG, "printState"); printState();
412
int pos = 0;
413         GenClassElement gce = null;
414         int i = 0;
415         while (i < deletedLength.length) {
416             pos += deletedLength[i];
417             gce = (GenClassElement) pIndexedElems.get(pos);
418             if (gce.value == element) {
419                 break;
420             }
421             pos++;
422             i++;
423         }
424         if (i < deletedLength.length) {
425             if (gce.hasBeenCreated) {
426                 throw new EJBException JavaDoc("Internal error state: A deleted element has not been created");
427             }
428             if (TraceEjb.genclass.isLoggable(BasicLevel.DEBUG)) {
429             TraceEjb.genclass.log(BasicLevel.DEBUG,
430                                   "The element added was previously removed. i: " + i
431                                   + "gce.pname: " + gce.pname);
432             }
433             // The element was previously removed and added now.
434
// - the status must be change to unmodified
435
gce.status = PIndexedElem.ELEM_UNMODIFIED;
436             if (deletedLength.length == 1) {
437                 deletedLength = new int[0];
438             } else {
439                 int[] old = deletedLength;
440                 deletedLength = new int[deletedLength.length - 1];
441                 System.arraycopy(old, 0, deletedLength, 0, i);
442                 if (i < deletedLength.length) {
443                     System.arraycopy(old, i + 1,
444                                      deletedLength, i,
445                                      deletedLength.length - i - 1);
446                     deletedLength[i] += old[i] + 1;
447                 }
448             }
449         } else {
450             if (TraceEjb.genclass.isLoggable(BasicLevel.DEBUG)) {
451                 try {
452                     TraceEjb.genclass.log(BasicLevel.DEBUG, "Add the element '"
453                             + element.getPName().encodeString());
454                 } catch (PExceptionNaming pExceptionNaming) {
455                 }
456             }
457             gce = (GenClassElement) createPIndexedElem();
458             gce.value = element;
459             gce.status = PIndexedElem.ELEM_CREATED;
460             gce.hasBeenCreated = true;
461             // Check if the element is legal, before added it (fix bug #300521)
462
listener.isLegalElement(gce);
463             pIndexedElems.add(gce);
464         }
465         isModified = true;
466         size++;
467         //TraceEjb.genclass.log(BasicLevel.DEBUG, "printState"); printState();
468
if (callListener) {
469             listener.gcAdd(gce);
470         }
471     }
472
473     /**
474      * It removes the first occurence of an element from the relation.
475      * @param element an element which must be removed
476      * @param callListener indicates if the gen class listener must be call
477      * about this action
478      * @return the remove element
479      */

480     protected Object JavaDoc gcRemove(Object JavaDoc element, boolean callListener) throws PException {
481         //TraceEjb.genclass.log(BasicLevel.DEBUG, "printState"); printState();
482
GenClassElement gce = null;
483         boolean found = false;
484         int b = 0; //The number of existing element since the last deleted element
485
int i = 0; // Quantity of deleted elements before
486
int a;
487         for (a = 0; a < pIndexedElems.size() && !found; a++) {
488             gce = (GenClassElement) pIndexedElems.get(a);
489             if (gce.status == PIndexedElem.ELEM_DELETED) {
490                 i++;
491                 b = 0;
492                 continue; //Do not search the element among the deleted elements
493
}
494             b++;
495             if (gce.pname != null && gce.value == null) {
496                 gce.value = gcDeref(gce.pname);
497             }
498             found = (element == null && gce.value == null)
499                 || (element != null && element.equals(gce.value));
500         }
501         if (!found) {
502             if (TraceEjb.genclass.isLoggable(BasicLevel.DEBUG)) {
503                 TraceEjb.genclass.log(BasicLevel.DEBUG, "Nothing to remove");
504             }
505             return null;
506         }
507
508         // call listener before removing field
509
if (callListener) {
510             listener.gcRemove(gce, false);
511         }
512         if (gce.hasBeenCreated) {
513             // Remove the element permanantly
514
if (TraceEjb.genclass.isLoggable(BasicLevel.DEBUG)) {
515                 TraceEjb.genclass.log(BasicLevel.DEBUG, "Remove permanantly the element");
516             }
517             pIndexedElems.remove(a - 1);
518             if (i < deletedLength.length) {
519                 //decrease the number of existing element until the next deletec
520
// element.
521
deletedLength[i]--;
522             }
523         } else {
524             //Mark the element as removed
525
gce.status = PIndexedElem.ELEM_DELETED;
526
527             // add the entry in the deletedLength array
528
if (TraceEjb.genclass.isLoggable(BasicLevel.DEBUG)) {
529             TraceEjb.genclass.log(BasicLevel.DEBUG,
530                                   "Add the entry in the deletedLength array: i:" + i + " / b:" + b + ")");
531             }
532             int[] old = deletedLength;
533             deletedLength = new int[old.length + 1];
534             System.arraycopy(old, 0, deletedLength, 0, i);
535             deletedLength[i] = b - 1;
536             if (i < old.length) {
537                 deletedLength[i + 1] = old[i] - b;
538                 System.arraycopy(old, i + 1, deletedLength, i + 2, old.length - i - 1);
539             }
540         }
541         isModified = true;
542         size--;
543         //TraceEjb.genclass.log(BasicLevel.DEBUG, "printState"); printState();
544
return gce.value;
545     }
546
547     private static String JavaDoc toString(int[] t) {
548         StringBuffer JavaDoc sb = new StringBuffer JavaDoc("[");
549         for (int i = 0; i < t.length;) {
550             sb.append(t[i]);
551             i++;
552             if (i < t.length) {
553                 sb.append(',');
554             }
555         }
556         sb.append(']');
557         return sb.toString();
558     }
559
560     public int gcGetSize() {
561         return size;
562     }
563
564     protected boolean gcContains(PObject element, Object JavaDoc connection)
565         throws PException {
566         //Open a connection if the parameter is null
567
Object JavaDoc conn = (connection == null
568                        ? gcm.getPMapper().getConnection()
569                        : connection);
570
571         boolean result = false;
572         for (Iterator JavaDoc it = gcIterator(conn); !result && it.hasNext();) {
573             Object JavaDoc o = it.next();
574             result = (element == null && o == null)
575                 || (element != null && element.equals(o));
576         }
577
578         if (connection == null) {
579             // close the localy opened connection
580
gcm.getPMapper().closeConnection(conn);
581         }
582         if (TraceEjb.genclass.isLoggable(BasicLevel.DEBUG)) {
583             try {
584                 TraceEjb.genclass.log(BasicLevel.DEBUG, "Looking for the element '"
585                         + element.getPName().encodeString()
586                         + ". return " + result);
587             } catch (PExceptionNaming pExceptionNaming) {
588             }
589         }
590         return result;
591     }
592
593     protected Iterator JavaDoc gcIterator() throws PException {
594         return gcIterator(null);
595     }
596
597     /**
598      * @param connection the connection to use during the PName resolving (if it has not
599      * already dereferenced).
600      * @return an Iterator over the virtual relations (only the existing elements).
601      */

602     protected Iterator JavaDoc gcIterator(Object JavaDoc connection) throws PException {
603         return new ElementIterator(this, connection);
604     }
605
606     /**
607      * It dereferences an element if needed
608      * @param gce is the PIndexedElem which must be dereferenced
609      * @param connection a connection to use to resolve the PName. If this parameter is
610      * null a new connection is allocate via the mapper.
611      * This connection is closed just after its use.
612      * @return a reference to the bean (The local interface in fact).
613      */

614     protected PObject gcGetElement(GenClassElement gce, Object JavaDoc connection) throws PException {
615         if (gce.pname != null && gce.value == null) {
616             // Dereference the PName
617
if (gce.pname == null || gce.pname.isNull()) {
618                 return null;
619             }
620             PName current = gce.pname;
621
622             // Allocate a connection if needed
623
Object JavaDoc conn = (connection == null
624                            ? gcm.getPMapper().getConnection()
625                            : connection);
626
627             // Resolve the pname
628
Object JavaDoc res = current.resolve(conn);
629             while (res != null && res instanceof PName && !res.equals(current)) {
630                 current = (PName) res;
631                 res = current.resolve(conn);
632             }
633
634             // close the connection opened localy
635
if (connection == null) {
636                 gcm.getPMapper().closeConnection(conn);
637             }
638
639             // Fetch a Local Object on the factory of the referenced bean
640
gce.value = gcDeref(current);
641         }
642         return gce.value;
643     }
644
645     /**
646      * Clear the GenClass.
647      * @param delete true if cascade delete must be checked (ONE - MANY)
648      */

649     public void gcClear(boolean delete) {
650         if (TraceEjb.genclass.isLoggable(BasicLevel.DEBUG)) {
651             TraceEjb.genclass.log(BasicLevel.DEBUG, "Clear the gc");
652         }
653         //TraceEjb.genclass.log(BasicLevel.DEBUG, "begin"); printState();
654

655         // Call listener now because ejbRemove can still access fields.
656
for (Iterator JavaDoc it = pIndexedElems.iterator(); it.hasNext();) {
657             GenClassElement gce = (GenClassElement) it.next();
658             if (gce.status != PIndexedElem.ELEM_DELETED) {
659                 if (gce.pname != null && gce.value == null) {
660                     gce.value = gcDeref(gce.pname);
661                 }
662                 if (TraceEjb.genclass.isLoggable(BasicLevel.DEBUG)) {
663                     TraceEjb.genclass.log(BasicLevel.DEBUG, "listener.gcRemove");
664                 }
665                 listener.gcRemove(gce, delete);
666             }
667         }
668
669         // Mark all elements as DELETED or remove the created element.
670
for (Iterator JavaDoc it = pIndexedElems.iterator(); it.hasNext();) {
671             GenClassElement gce = (GenClassElement) it.next();
672             if (gce.status != PIndexedElem.ELEM_DELETED) {
673                 gce.status = PIndexedElem.ELEM_DELETED;
674                 if (gce.hasBeenCreated) {
675                     // Remove the element permanantly
676
if (TraceEjb.genclass.isLoggable(BasicLevel.DEBUG)) {
677                         TraceEjb.genclass.log(BasicLevel.DEBUG, "Clear permanantly an element");
678                     }
679                     it.remove();
680                 }
681             }
682         }
683         // update the virtual size
684
size = 0;
685         isModified = true;
686
687         // As all elements are deleted, the 'deletedLength' contains only 0
688
// numbers. The size of this array is the same as the size of the
689
// pIndexedElems list.
690
deletedLength = new int[pIndexedElems.size()];
691         Arrays.fill(deletedLength, 0);
692         //TraceEjb.genclass.log(BasicLevel.DEBUG, "end"); printState();
693

694     }
695
696     protected PObject gcDeref(PName pn) {
697         JEntityFactory f = (JEntityFactory)
698             ((PBinder) pn.getPNameManager()).getBinderClassMapping();
699         if (f.getLocalHome() != null) {
700             return ((PObjectHome) f.getLocalHome()).getPObject(pn);
701         } else {
702             return ((PObjectHome) f.getHome()).getPObject(pn);
703         }
704     }
705
706     /**
707      * This method permits to find the PName of an object.
708      */

709     protected PName gcObject2ref(PObject value) throws PException {
710         if (value != null) {
711             Object JavaDoc conn = gcm.getPMapper().getConnection();
712             PNameManager pnm = (PNameManager) gcm.getPNameCoder();
713             PName pn = pnm.export(conn, value.getPName(), null);
714             gcm.getPMapper().closeConnection(conn);
715             return pn;
716         } else {
717             return gcm.getPNameCoder().getNull();
718         }
719     }
720
721     public void printState() {
722         if (!TraceEjb.genclass.isLoggable(BasicLevel.DEBUG)) {
723             return;
724         }
725         TraceEjb.genclass.log(BasicLevel.DEBUG, "deletedLength: " + toString(deletedLength));
726         TraceEjb.genclass.log(BasicLevel.DEBUG, "pIndexedElems.size():" + pIndexedElems.size());
727         TraceEjb.genclass.log(BasicLevel.DEBUG, "isModified: " + isModified);
728         TraceEjb.genclass.log(BasicLevel.DEBUG, "size:" + size);
729         int i = 0;
730         for (Iterator JavaDoc it = pIndexedElems.iterator(); it.hasNext();) {
731             GenClassElement gce = (GenClassElement) it.next();
732             TraceEjb.genclass.log(BasicLevel.DEBUG, "GCE:" + i
733                                   + " / status:" + gce.status
734                                   + " / hasBeenCreated:" + gce.hasBeenCreated
735                                   );
736             TraceEjb.genclass.log(BasicLevel.DEBUG, "- pname:" + gce.pname);
737             TraceEjb.genclass.log(BasicLevel.DEBUG, "- value:" + gce.value);
738             i++;
739         }
740     }
741
742     /**
743      * this class is an implementation of the Iterator interface which return
744      * only the existing objects. The return elements are dereferenced, then
745      * PObject instances.
746      */

747     protected class ElementIterator implements Iterator JavaDoc {
748
749         private int cursor = 0;
750         private int next = 0;
751         private GenClassImpl gc;
752         private Object JavaDoc conn;
753
754         public ElementIterator(GenClassImpl gc, Object JavaDoc connection) {
755             this.gc = gc;
756             conn = connection;
757             reset();
758         }
759
760         public void reset() {
761             cursor = -1;
762             next = nextExist(cursor);
763         }
764
765         private int nextExist(int pos) {
766             int tmp = pos + 1;
767             while (tmp < pIndexedElems.size()) {
768                 if (((GenClassElement) pIndexedElems.get(tmp)).status != PIndexedElem.ELEM_DELETED) {
769                     //TraceEjb.genclass.log(BasicLevel.DEBUG, "nextExist("+pos+")="+tmp);
770
return tmp;
771                 }
772                 tmp++;
773             }
774             //TraceEjb.genclass.log(BasicLevel.DEBUG, "nextExist("+pos+")=-1");
775
return -1;
776         }
777
778         // IMPLEMENTATION OF THE Iterator INTERFACE //
779
//------------------------------------------//
780

781         /**
782          * Returns <tt>true</tt> if the iteration has more elements. (In other
783          * words, returns <tt>true</tt> if <tt>next</tt> would return an element
784          * rather than throwing an exception.)
785          *
786          * @return <tt>true</tt> if the iterator has more elements.
787          */

788         public boolean hasNext() {
789             return next != -1;
790         }
791
792         /**
793          * Returns the next element in the interation.
794          *
795          * @return the next element in the iteration.
796          * @throws NoSuchElementException iteration has no more elements.
797          */

798         public Object JavaDoc next() {
799             if (next == -1) {
800                 throw new NoSuchElementException JavaDoc();
801             }
802             cursor = next;
803             try {
804                 GenClassElement gce = (GenClassElement) pIndexedElems.get(cursor);
805                 gc.gcGetElement(gce, conn);
806                 //Caculate the next
807
next = nextExist(cursor);
808                 return gce.value;
809             } catch (PException e) {
810                 next = -1;
811                 TraceEjb.genclass.log(BasicLevel.ERROR, "Impossible to obtain value:", e);
812                 throw new NoSuchElementException JavaDoc("Impossible to obtain value:" + e);
813             }
814         }
815
816         public void remove() {
817             try {
818                 gcRemove(((GenClassElement) pIndexedElems.get(cursor)).value, true);
819             } catch (PException e) {
820                 throw new UnsupportedOperationException JavaDoc(e.getMessage());
821             }
822         }
823     }
824 }
825
Popular Tags