Source Code Cross Referenced for GenClassImpl.java in  » J2EE » JOnAS-4.8.6 » org » objectweb » jonas_ejb » container » jorm » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » J2EE » JOnAS 4.8.6 » org.objectweb.jonas_ejb.container.jorm 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * JOnAS: Java(TM) Open Application Server
003:         * Copyright (C) 1999 Bull S.A.
004:         * Contact: jonas-team@objectweb.org
005:         *
006:         * This library is free software; you can redistribute it and/or
007:         * modify it under the terms of the GNU Lesser General Public
008:         * License as published by the Free Software Foundation; either
009:         * version 2.1 of the License, or any later version.
010:         *
011:         * This library is distributed in the hope that it will be useful,
012:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
013:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014:         * Lesser General Public License for more details.
015:         *
016:         * You should have received a copy of the GNU Lesser General Public
017:         * License along with this library; if not, write to the Free Software
018:         * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
019:         * USA
020:         *
021:         * Initial developer(s): Sebastien Chassande
022:         * Contributor(s):
023:         *
024:         * --------------------------------------------------------------------------
025:         * $Id: GenClassImpl.java 10146 2007-04-05 06:56:36Z durieuxp $
026:         * --------------------------------------------------------------------------
027:         */
028:        package org.objectweb.jonas_ejb.container.jorm;
029:
030:        import java.util.ArrayList;
031:        import java.util.Arrays;
032:        import java.util.Iterator;
033:        import java.util.NoSuchElementException;
034:        import javax.ejb.EJBException;
035:        import org.objectweb.jonas_ejb.container.JEntityFactory;
036:        import org.objectweb.jonas_ejb.container.TraceEjb;
037:        import org.objectweb.jorm.api.PBinding;
038:        import org.objectweb.jorm.api.PClassMapping;
039:        import org.objectweb.jorm.api.PException;
040:        import org.objectweb.jorm.api.PExceptionProtocol;
041:        import org.objectweb.jorm.api.PGenClassAccessor;
042:        import org.objectweb.jorm.api.PIndexedElem;
043:        import org.objectweb.jorm.naming.api.PBinder;
044:        import org.objectweb.jorm.naming.api.PName;
045:        import org.objectweb.jorm.naming.api.PNameManager;
046:        import org.objectweb.jorm.naming.api.PExceptionNaming;
047:        import org.objectweb.util.monolog.api.BasicLevel;
048:
049:        /**
050:         * This class is a basic implementation of the PGenClassAccessor interface
051:         * usefull for the multivalued relation.
052:         *
053:         * @author S.Chassande-Barrioz
054:         */
055:        public abstract class GenClassImpl implements  PGenClassAccessor {
056:
057:            /**
058:             * All elements of the gen class (unmodified, modified, created, deleted)
059:             * This ArrayList contains GenClassElem objects
060:             */
061:            protected ArrayList pIndexedElems = null;
062:
063:            /**
064:             * This array represents the distance between two deleted elements in the
065:             * pIndexedElems arraylist. O means there is no element in the middle. The
066:             * first element is in fact the quantity of existing element before the
067:             * first deleted element.
068:             * The size of this array is also the quantity of deleted elements. Then if
069:             * the array is empty there is no deleted elements.
070:             *
071:             * for example: if this fields is equals to [3, 2] then the elements whith
072:             * the index 3 and 6 are marked as deleted: [a, b, c, D, d, e, D, ....]
073:             *
074:             * This array is useless to convert an index valid inside the user/virtual
075:             * collection to an index valid inside the 'pIndexedElems' ArrayList.
076:             */
077:            protected int[] deletedLength = null;
078:
079:            /**
080:             * This is the size of the relation. This field is equal to the
081:             * pIndexedElems size minus the quantity of deleted element. The value is
082:             * always right and is updated during each delete or create action.
083:             */
084:            protected int size;
085:
086:            /**
087:             * true when GenClass has been modified and must be written
088:             */
089:            protected boolean isModified = false;
090:
091:            /**
092:             * true when we want use select .. for ..update
093:             */
094:            protected boolean selectForUpdate = false;
095:
096:            /**
097:             * This field references the PClassMapping which manages the persistency of
098:             * this GenClass. (xxxGCM.java)
099:             * This is actually a GenClassMapping, returned by the bean Factory (PClassMapping)
100:             */
101:            protected PClassMapping gcm = null;
102:
103:            protected org.objectweb.jonas_ejb.container.JEntityContext ectx = null;
104:
105:            /**
106:             * This fields is the PBinding associated to this instance.
107:             */
108:            protected PBinding pb = null;
109:
110:            /**
111:             * All the actions are send to this listener.
112:             * There is 1 Listener for each GenClass, i.e. for each
113:             * multi-valued CMR field. (See JEntityCmp2.vm)
114:             * Used mainly for coherence.
115:             */
116:            protected GenClassListener listener = null;
117:
118:            /**
119:             * A GenClassImpl object is created for each Multi-Valued CMR field
120:             * See JEntityCmp2.vm
121:             * It starts with an empty list.
122:             */
123:            public GenClassImpl() {
124:                pIndexedElems = new ArrayList(0);
125:                size = 0;
126:                deletedLength = new int[0];
127:                isModified = false;
128:            }
129:
130:            /**
131:             * Set the PClassMapping for this GenClass. It's needed to get
132:             * Connections for read and write operations.
133:             * Used by JEntityCmp2.vm
134:             * @param gcm the PClassMapping
135:             */
136:            public void setPClassMapping(PClassMapping gcm) {
137:                this .gcm = gcm;
138:            }
139:
140:            /**
141:             * Set the EntityContext needed for setDirty calls
142:             */
143:            public void setEntityContext(
144:                    org.objectweb.jonas_ejb.container.JEntityContext ectx) {
145:                this .ectx = ectx;
146:                selectForUpdate = ectx.getEntityFactory().getSelectForUpdate();
147:            }
148:
149:            /**
150:             * reset the GenClass to its initial state.
151:             */
152:            public void reset() {
153:                pIndexedElems.clear();
154:                size = 0;
155:                deletedLength = new int[0];
156:                isModified = false;
157:            }
158:
159:            /**
160:             * Set the PBinding that will be used for this GenClass
161:             * Used by JEntityCmp2.vm
162:             * @param pb The PBinding for this GenClass
163:             */
164:            public void setPBinding(PBinding pb) {
165:                this .pb = pb;
166:            }
167:
168:            /**
169:             * Get the PBinding used for this GenClass
170:             * Used by JEntityCmp2.vm
171:             * @return The PBinding for this GenClass
172:             */
173:            public PBinding gcGetPBinding() {
174:                return pb;
175:            }
176:
177:            public void setListener(GenClassListener gcl) {
178:                listener = gcl;
179:            }
180:
181:            public GenClassListener getListener() {
182:                return listener;
183:            }
184:
185:            // IMPLEMENTATION OF THE Persitence lyfe cycle //
186:            //---------------------------------------------//
187:
188:            public boolean gcIsModified() {
189:                return isModified;
190:            }
191:
192:            /**
193:             * It loads the data of the gen class.
194:             * @param pn is the PName of the genclass
195:             * @param connection is a connection to access to the support. If it is null
196:             * a connection is asked to the mapper and closed after its use.
197:             */
198:            public void read(PName pn, Object connection, Object tx)
199:                    throws PException {
200:                if (pn == null || pn.isNull()) {
201:                    TraceEjb.genclass.log(BasicLevel.DEBUG, "null pn");
202:                    reset();
203:                    return;
204:                }
205:                if (pb == null) {
206:                    throw new PExceptionProtocol(
207:                            "Impossible to read a persitent object withoout PBinding");
208:                }
209:                if (TraceEjb.genclass.isLoggable(BasicLevel.DEBUG)) {
210:                    TraceEjb.genclass.log(BasicLevel.DEBUG, "PName=" + pn);
211:                }
212:
213:                // Allocate a connection if needed
214:                Object conn = (connection == null ? gcm.getPMapper()
215:                        .getConnection() : connection);
216:                if (TraceEjb.genclass.isLoggable(BasicLevel.DEBUG)) {
217:                    TraceEjb.genclass
218:                            .log(BasicLevel.DEBUG, "Load the genclass");
219:                }
220:                pb.bind(pn);
221:                pb.read(conn, this , tx, selectForUpdate);
222:                //pb.unbind();
223:                isModified = false;
224:
225:                // close the connection opened localy
226:                if (connection == null) {
227:                    gcm.getPMapper().closeConnection(conn);
228:                }
229:            }
230:
231:            /**
232:             * It writes the data of the gen class if it was modified (see the field
233:             * isModified).
234:             * @param pn is the PName of the genclass
235:             * @param connection is a connection to access to the support. If it is null
236:             * a connection is asked to the mapper and closed after its use.
237:             */
238:            public void write(PName pn, Object connection) throws PException {
239:                //TraceEjb.genclass.log(BasicLevel.DEBUG, "begin"); printState();
240:                if (pn == null || pn.isNull()) {
241:                    throw new PExceptionProtocol(
242:                            "Impossible to write a persitent object with a null PName: "
243:                                    + pn);
244:                }
245:                if (TraceEjb.genclass.isLoggable(BasicLevel.DEBUG)) {
246:                    TraceEjb.genclass.log(BasicLevel.DEBUG, "");
247:                }
248:                if (isModified) {
249:                    // Allocate a connection if needed
250:                    Object conn = (connection == null ? gcm.getPMapper()
251:                            .getConnection() : connection);
252:
253:                    if (pb == null) {
254:                        throw new PExceptionProtocol(
255:                                "Impossible to write a persitent object without PBinding");
256:                    }
257:                    if (TraceEjb.genclass.isLoggable(BasicLevel.DEBUG)) {
258:                        TraceEjb.genclass.log(BasicLevel.DEBUG,
259:                                "Store the genclass " + pn);
260:                    }
261:                    pb.bind(pn);
262:                    pb.write(conn, this );
263:                    //pb.unbind();
264:
265:                    // The data are written on the support, then the memory instance is
266:                    // up to date. The element marked as removed must really be removed
267:                    // from the list.
268:                    isModified = false;
269:                    int pos = 0;
270:                    for (int i = 0; i < deletedLength.length; i++) {
271:                        pos += deletedLength[i];
272:                        pIndexedElems.remove(pos);
273:                    }
274:                    deletedLength = new int[0];
275:                    for (Iterator it = pIndexedElems.iterator(); it.hasNext();) {
276:                        GenClassElement gce = (GenClassElement) it.next();
277:                        gce.status = PIndexedElem.ELEM_UNMODIFIED;
278:                        gce.hasBeenCreated = false;
279:                    }
280:
281:                    // close the connection opened localy
282:                    if (connection == null) {
283:                        gcm.getPMapper().closeConnection(conn);
284:                    }
285:                }
286:                //TraceEjb.genclass.log(BasicLevel.DEBUG, "end"); printState();
287:            }
288:
289:            // IMPLEMENTATION OF THE PAccessor INTERFACE //
290:            //-------------------------------------------//
291:
292:            /**
293:             * In most of cases this class is extented to personalize to a collection
294:             * type. Then an instance of this class is often the real collection.
295:             */
296:            public Object getMemoryInstance() {
297:                return this ;
298:            }
299:
300:            // IMPLEMENTATION OF THE PGenClassAccessor INTERFACE //
301:            //---------------------------------------------------//
302:
303:            /**
304:             * It adds the elements in the list. This method is used by the PBinding to
305:             * load the data.
306:             * The elements is added at the end of the 'pIndexedElems' then
307:             * 'deletedLength' is not impacted.
308:             */
309:            public void paAdd(PIndexedElem elem, Object conn) throws PException {
310:                pIndexedElems.add(elem);
311:                size++;
312:                //TraceEjb.genclass.log(BasicLevel.DEBUG, "printState"); printState();
313:            }
314:
315:            /**
316:             * The default implementation of the PIndexedElem is GenClassElement.
317:             * This method may be redefined for different GenClass implementations.
318:             */
319:            public PIndexedElem createPIndexedElem() {
320:                return new GenClassElement(this );
321:            }
322:
323:            /**
324:             * This implementation is able to isolate the modification by element of the
325:             * gen class.
326:             */
327:            public boolean paDeltaSupported() {
328:                return true;
329:            }
330:
331:            /**
332:             * This method is used by the PBinding to allocated data structure during a
333:             * write operation. The returned size must then contains also the deleted
334:             * elements.
335:             */
336:            public int paGetNbElem() {
337:                return pIndexedElems.size();
338:            }
339:
340:            /**
341:             * This method is used by the PBinding to fetch all PIndexedElem.
342:             */
343:            public Iterator paIterator() {
344:                return pIndexedElems.iterator();
345:            }
346:
347:            /**
348:             * This method is call in first during a read operation in order to indicate
349:             * the size of the gen class. if the value is equals to -1 then that means
350:             * the data support is unable to known the size of the relation in advance.
351:             * Then the previous size is kept. Otherwise the list is initialized to the
352:             * specified size.
353:             */
354:            public void paSetNbElem(int nbelem) {
355:                if (TraceEjb.genclass.isLoggable(BasicLevel.DEBUG)) {
356:                    TraceEjb.genclass
357:                            .log(BasicLevel.DEBUG, "nbElem: " + nbelem);
358:                }
359:                if (nbelem == -1) {
360:                    pIndexedElems.clear();
361:                } else {
362:                    pIndexedElems = new ArrayList(nbelem);
363:                }
364:                deletedLength = new int[0];
365:                size = 0;
366:            }
367:
368:            // METHODS USABLE FOR THE SUB CLASS //
369:            //----------------------------------//
370:
371:            /**
372:             * This method calculates the real index of an element.
373:             * @param idx the index valid in the colllection
374:             * @return an index valid into the 'pIndexedElems' ArrayList.
375:             */
376:            protected int gcGetRealIndex(int idx) {
377:                int a = idx;
378:                int i = 0;
379:                while (i < deletedLength.length && (a -= deletedLength[i]) >= 0) {
380:                    i++;
381:                }
382:                return idx + i;
383:            }
384:
385:            /**
386:             * This method add a new element in the collection. A PIndexedElem is built
387:             * via the 'createPIndexedElem' method. Then this instance is initialized
388:             * with the element and the staus specified by the parameter 'status'.
389:             * Before added the element, a checking is done. If the element was
390:             * previously removed in the same transaction then the status of the
391:             * removed element is changed to ELEM_UNMODIFIED. This optimization avoid
392:             * two useless I/O.
393:             *
394:             * @param element the object to add
395:             * @param callListener indicates if the gen class listener must be call
396:             * about this action
397:             */
398:            protected void gcAdd(PObject element, boolean callListener) {
399:                //TraceEjb.genclass.log(BasicLevel.DEBUG, "printState"); printState();
400:                int pos = 0;
401:                GenClassElement gce = null;
402:                int i = 0;
403:
404:                // call setDirty before, because if there is a conflict, we must
405:                // not update the collection.
406:                ectx.setDirty(true);
407:
408:                while (i < deletedLength.length) {
409:                    pos += deletedLength[i];
410:                    gce = (GenClassElement) pIndexedElems.get(pos);
411:                    if (gce.value == element) {
412:                        break;
413:                    }
414:                    pos++;
415:                    i++;
416:                }
417:                if (i < deletedLength.length) {
418:                    if (gce.hasBeenCreated) {
419:                        throw new EJBException(
420:                                "Internal error state: A deleted element has not been created");
421:                    }
422:                    if (TraceEjb.genclass.isLoggable(BasicLevel.DEBUG)) {
423:                        TraceEjb.genclass.log(BasicLevel.DEBUG,
424:                                "The element added was previously removed. i: "
425:                                        + i + "gce.pname: " + gce.pname);
426:                    }
427:                    // The element was previously removed and added now.
428:                    // - the status must be change to unmodified
429:                    gce.status = PIndexedElem.ELEM_UNMODIFIED;
430:                    if (deletedLength.length == 1) {
431:                        deletedLength = new int[0];
432:                    } else {
433:                        int[] old = deletedLength;
434:                        deletedLength = new int[deletedLength.length - 1];
435:                        System.arraycopy(old, 0, deletedLength, 0, i);
436:                        if (i < deletedLength.length) {
437:                            System.arraycopy(old, i + 1, deletedLength, i,
438:                                    old.length - 1 - i);
439:                            deletedLength[i] += old[i] + 1;
440:                        }
441:                    }
442:                } else {
443:                    if (TraceEjb.genclass.isLoggable(BasicLevel.DEBUG)) {
444:                        try {
445:                            TraceEjb.genclass
446:                                    .log(BasicLevel.DEBUG, "Add the element '"
447:                                            + element.getPName().encodeString());
448:                        } catch (PExceptionNaming pExceptionNaming) {
449:                        }
450:                    }
451:                    gce = (GenClassElement) createPIndexedElem();
452:                    gce.value = element;
453:                    gce.status = PIndexedElem.ELEM_CREATED;
454:                    gce.hasBeenCreated = true;
455:                    // Check if the element is legal, before added it (fix bug #300521)
456:                    listener.isLegalElement(gce);
457:                    pIndexedElems.add(gce);
458:                }
459:                isModified = true;
460:                size++;
461:                //TraceEjb.genclass.log(BasicLevel.DEBUG, "printState"); printState();
462:                if (callListener) {
463:                    if (gce == null) {
464:                        TraceEjb.genclass.log(BasicLevel.ERROR, "null gce");
465:                        return;
466:                    }
467:                    listener.gcAdd(gce);
468:                }
469:            }
470:
471:            /**
472:             * It removes the first occurence of an element from the relation.
473:             * @param element an element which must be removed
474:             * @param callListener indicates if the gen class listener must be call
475:             * about this action
476:             * @return the remove element
477:             */
478:            protected Object gcRemove(Object element, boolean callListener)
479:                    throws PException {
480:                //TraceEjb.genclass.log(BasicLevel.DEBUG, "printState"); printState();
481:                GenClassElement gce = null;
482:                boolean found = false;
483:                int b = 0; //The number of existing element since the last deleted element
484:                int i = 0; // Quantity of deleted elements before
485:                int a;
486:                for (a = 0; a < pIndexedElems.size() && !found; a++) {
487:                    gce = (GenClassElement) pIndexedElems.get(a);
488:                    if (gce.status == PIndexedElem.ELEM_DELETED) {
489:                        i++;
490:                        b = 0;
491:                        continue; //Do not search the element among the deleted elements
492:                    }
493:                    b++;
494:                    if (gce.pname != null && gce.value == null) {
495:                        gce.value = gcDeref(gce.pname);
496:                    }
497:                    found = (element == null && gce.value == null)
498:                            || (element != null && element.equals(gce.value));
499:                }
500:                if (!found) {
501:                    if (TraceEjb.genclass.isLoggable(BasicLevel.DEBUG)) {
502:                        TraceEjb.genclass.log(BasicLevel.DEBUG,
503:                                "Nothing to remove");
504:                    }
505:                    return null;
506:                }
507:
508:                // call setDirty before, because if there is a conflict, we must
509:                // not update the collection.
510:                ectx.setDirty(true);
511:
512:                // call listener before removing field
513:                if (callListener) {
514:                    listener.gcRemove(gce, false);
515:                }
516:                if (gce.hasBeenCreated) {
517:                    // Remove the element permanantly
518:                    if (TraceEjb.genclass.isLoggable(BasicLevel.DEBUG)) {
519:                        TraceEjb.genclass.log(BasicLevel.DEBUG,
520:                                "Remove permanantly the element");
521:                    }
522:                    pIndexedElems.remove(a - 1);
523:                    if (i < deletedLength.length) {
524:                        //decrease the number of existing element until the next deletec
525:                        // element.
526:                        deletedLength[i]--;
527:                    }
528:                } else {
529:                    //Mark the element as removed
530:                    gce.status = PIndexedElem.ELEM_DELETED;
531:
532:                    // add the entry in the deletedLength array
533:                    if (TraceEjb.genclass.isLoggable(BasicLevel.DEBUG)) {
534:                        TraceEjb.genclass.log(BasicLevel.DEBUG,
535:                                "Add the entry in the deletedLength array: i:"
536:                                        + i + " / b:" + b + ")");
537:                    }
538:                    int[] old = deletedLength;
539:                    deletedLength = new int[old.length + 1];
540:                    System.arraycopy(old, 0, deletedLength, 0, i);
541:                    deletedLength[i] = b - 1;
542:                    if (i < old.length) {
543:                        deletedLength[i + 1] = old[i] - b;
544:                        System.arraycopy(old, i + 1, deletedLength, i + 2,
545:                                old.length - i - 1);
546:                    }
547:                }
548:                isModified = true;
549:                size--;
550:                //TraceEjb.genclass.log(BasicLevel.DEBUG, "printState"); printState();
551:                return gce.value;
552:            }
553:
554:            private static String toString(int[] t) {
555:                StringBuffer sb = new StringBuffer("[");
556:                for (int i = 0; i < t.length;) {
557:                    sb.append(t[i]);
558:                    i++;
559:                    if (i < t.length) {
560:                        sb.append(',');
561:                    }
562:                }
563:                sb.append(']');
564:                return sb.toString();
565:            }
566:
567:            public int gcGetSize() {
568:                return size;
569:            }
570:
571:            protected boolean gcContains(PObject element, Object connection)
572:                    throws PException {
573:                //Open a connection if the parameter is null
574:                Object conn = (connection == null ? gcm.getPMapper()
575:                        .getConnection() : connection);
576:
577:                boolean result = false;
578:                for (Iterator it = gcIterator(conn); !result && it.hasNext();) {
579:                    Object o = it.next();
580:                    result = (element == null && o == null)
581:                            || (element != null && element.equals(o));
582:                }
583:
584:                if (connection == null) {
585:                    // close the localy opened connection
586:                    gcm.getPMapper().closeConnection(conn);
587:                }
588:                if (TraceEjb.genclass.isLoggable(BasicLevel.DEBUG)) {
589:                    try {
590:                        TraceEjb.genclass.log(BasicLevel.DEBUG,
591:                                "Looking for the element '"
592:                                        + element.getPName().encodeString()
593:                                        + ". return " + result);
594:                    } catch (PExceptionNaming pExceptionNaming) {
595:                    }
596:                }
597:                return result;
598:            }
599:
600:            protected Iterator gcIterator() throws PException {
601:                return gcIterator(null);
602:            }
603:
604:            /**
605:             * @param connection the connection to use during the PName resolving (if it has not
606:             * already dereferenced).
607:             * @return an Iterator over the virtual relations (only the existing elements).
608:             */
609:            protected Iterator gcIterator(Object connection) throws PException {
610:                return new ElementIterator(this , connection);
611:            }
612:
613:            /**
614:             * It dereferences an element if needed
615:             * @param gce is the PIndexedElem which must be dereferenced
616:             * @param connection a connection to use to resolve the PName. If this parameter is
617:             * null a new connection is allocate via the mapper.
618:             * This connection is closed just after its use.
619:             * @return a reference to the bean (The local interface in fact).
620:             */
621:            protected PObject gcGetElement(GenClassElement gce,
622:                    Object connection) throws PException {
623:                if (gce.pname != null && gce.value == null) {
624:                    // Dereference the PName
625:                    if (gce.pname == null || gce.pname.isNull()) {
626:                        return null;
627:                    }
628:                    PName current = gce.pname;
629:
630:                    // Allocate a connection if needed
631:                    Object conn = (connection == null ? gcm.getPMapper()
632:                            .getConnection() : connection);
633:
634:                    // Resolve the pname
635:                    Object res = current.resolve(conn);
636:                    while (res != null && res instanceof  PName
637:                            && !res.equals(current)) {
638:                        current = (PName) res;
639:                        res = current.resolve(conn);
640:                    }
641:
642:                    // close the connection opened localy
643:                    if (connection == null) {
644:                        gcm.getPMapper().closeConnection(conn);
645:                    }
646:
647:                    // Fetch a Local Object on the factory of the referenced bean
648:                    gce.value = gcDeref(current);
649:                }
650:                return gce.value;
651:            }
652:
653:            /**
654:             * Clear the GenClass.
655:             * @param delete true if cascade delete must be checked (ONE - MANY)
656:             */
657:            public void gcClear(boolean delete) {
658:                if (TraceEjb.genclass.isLoggable(BasicLevel.DEBUG)) {
659:                    TraceEjb.genclass.log(BasicLevel.DEBUG, "Clear the gc");
660:                }
661:                //TraceEjb.genclass.log(BasicLevel.DEBUG, "begin"); printState();
662:
663:                // Call listener now because ejbRemove can still access fields.
664:                for (Iterator it = pIndexedElems.iterator(); it.hasNext();) {
665:                    GenClassElement gce = (GenClassElement) it.next();
666:                    if (gce.status != PIndexedElem.ELEM_DELETED) {
667:                        if (gce.pname != null && gce.value == null) {
668:                            gce.value = gcDeref(gce.pname);
669:                        }
670:                        if (TraceEjb.genclass.isLoggable(BasicLevel.DEBUG)) {
671:                            TraceEjb.genclass.log(BasicLevel.DEBUG,
672:                                    "listener.gcRemove");
673:                        }
674:                        listener.gcRemove(gce, delete);
675:                    }
676:                }
677:
678:                // Mark all elements as DELETED or remove the created element.
679:                for (Iterator it = pIndexedElems.iterator(); it.hasNext();) {
680:                    GenClassElement gce = (GenClassElement) it.next();
681:                    if (gce.status != PIndexedElem.ELEM_DELETED) {
682:                        gce.status = PIndexedElem.ELEM_DELETED;
683:                        if (gce.hasBeenCreated) {
684:                            // Remove the element permanantly
685:                            if (TraceEjb.genclass.isLoggable(BasicLevel.DEBUG)) {
686:                                TraceEjb.genclass.log(BasicLevel.DEBUG,
687:                                        "Clear permanantly an element");
688:                            }
689:                            it.remove();
690:                        }
691:                    }
692:                }
693:                // update the virtual size
694:                size = 0;
695:                isModified = true;
696:                ectx.setDirty(true);
697:
698:                // As all elements are deleted, the 'deletedLength' contains only 0
699:                // numbers. The size of this array is the same as the size of the
700:                // pIndexedElems list.
701:                deletedLength = new int[pIndexedElems.size()];
702:                Arrays.fill(deletedLength, 0);
703:                //TraceEjb.genclass.log(BasicLevel.DEBUG, "end"); printState();
704:
705:            }
706:
707:            protected PObject gcDeref(PName pn) {
708:                JEntityFactory f = (JEntityFactory) ((PBinder) pn
709:                        .getPNameManager()).getBinderClassMapping();
710:                if (f.getLocalHome() != null) {
711:                    return ((PObjectHome) f.getLocalHome()).getPObject(pn);
712:                } else {
713:                    return ((PObjectHome) f.getHome()).getPObject(pn);
714:                }
715:            }
716:
717:            /**
718:             * This method permits to find the PName of an object.
719:             */
720:            protected PName gcObject2ref(PObject value) throws PException {
721:                if (value != null) {
722:                    Object conn = gcm.getPMapper().getConnection();
723:                    PNameManager pnm = (PNameManager) gcm.getPNameCoder();
724:                    PName pn = pnm.export(conn, value.getPName(), null);
725:                    gcm.getPMapper().closeConnection(conn);
726:                    return pn;
727:                } else {
728:                    return gcm.getPNameCoder().getNull();
729:                }
730:            }
731:
732:            public void printState() {
733:                if (!TraceEjb.genclass.isLoggable(BasicLevel.DEBUG)) {
734:                    return;
735:                }
736:                TraceEjb.genclass.log(BasicLevel.DEBUG, "deletedLength: "
737:                        + toString(deletedLength));
738:                TraceEjb.genclass.log(BasicLevel.DEBUG, "pIndexedElems.size():"
739:                        + pIndexedElems.size());
740:                TraceEjb.genclass.log(BasicLevel.DEBUG, "isModified: "
741:                        + isModified);
742:                TraceEjb.genclass.log(BasicLevel.DEBUG, "size:" + size);
743:                int i = 0;
744:                for (Iterator it = pIndexedElems.iterator(); it.hasNext();) {
745:                    GenClassElement gce = (GenClassElement) it.next();
746:                    TraceEjb.genclass.log(BasicLevel.DEBUG, "GCE:" + i
747:                            + " / status:" + gce.status + " / hasBeenCreated:"
748:                            + gce.hasBeenCreated);
749:                    TraceEjb.genclass.log(BasicLevel.DEBUG, "- pname:"
750:                            + gce.pname);
751:                    TraceEjb.genclass.log(BasicLevel.DEBUG, "- value:"
752:                            + gce.value);
753:                    i++;
754:                }
755:            }
756:
757:            /**
758:             * this class is an implementation of the Iterator interface which return
759:             * only the existing objects. The return elements are dereferenced, then
760:             * PObject instances.
761:             */
762:            protected class ElementIterator implements  Iterator {
763:
764:                private int cursor = 0;
765:                private int next = 0;
766:                private GenClassImpl gc;
767:                private Object conn;
768:
769:                public ElementIterator(GenClassImpl gc, Object connection) {
770:                    this .gc = gc;
771:                    conn = connection;
772:                    reset();
773:                }
774:
775:                public void reset() {
776:                    cursor = -1;
777:                    next = nextExist(cursor);
778:                }
779:
780:                private int nextExist(int pos) {
781:                    int tmp = pos + 1;
782:                    while (tmp < pIndexedElems.size()) {
783:                        GenClassElement gce = (GenClassElement) pIndexedElems
784:                                .get(tmp);
785:                        if (gce == null) {
786:                            TraceEjb.genclass.log(BasicLevel.ERROR,
787:                                    "null GenClassElement");
788:                            return -1;
789:                        }
790:                        if (gce.status != PIndexedElem.ELEM_DELETED) {
791:                            //TraceEjb.genclass.log(BasicLevel.DEBUG, "nextExist("+pos+")="+tmp);
792:                            return tmp;
793:                        }
794:                        tmp++;
795:                    }
796:                    //TraceEjb.genclass.log(BasicLevel.DEBUG, "nextExist("+pos+")=-1");
797:                    return -1;
798:                }
799:
800:                // IMPLEMENTATION OF THE Iterator INTERFACE //
801:                //------------------------------------------//
802:
803:                /**
804:                 * Returns <tt>true</tt> if the iteration has more elements. (In other
805:                 * words, returns <tt>true</tt> if <tt>next</tt> would return an element
806:                 * rather than throwing an exception.)
807:                 *
808:                 * @return <tt>true</tt> if the iterator has more elements.
809:                 */
810:                public boolean hasNext() {
811:                    return next != -1;
812:                }
813:
814:                /**
815:                 * Returns the next element in the interation.
816:                 *
817:                 * @return the next element in the iteration.
818:                 * @throws NoSuchElementException iteration has no more elements.
819:                 */
820:                public Object next() {
821:                    if (next == -1) {
822:                        throw new NoSuchElementException();
823:                    }
824:                    cursor = next;
825:                    try {
826:                        GenClassElement gce = (GenClassElement) pIndexedElems
827:                                .get(cursor);
828:                        gc.gcGetElement(gce, conn);
829:                        //Caculate the next
830:                        next = nextExist(cursor);
831:                        return gce.value;
832:                    } catch (PException e) {
833:                        next = -1;
834:                        TraceEjb.genclass.log(BasicLevel.ERROR,
835:                                "Impossible to obtain value:", e);
836:                        throw new NoSuchElementException(
837:                                "Impossible to obtain value:" + e);
838:                    }
839:                }
840:
841:                public void remove() {
842:                    try {
843:                        gcRemove(
844:                                ((GenClassElement) pIndexedElems.get(cursor)).value,
845:                                true);
846:                    } catch (PException e) {
847:                        throw new UnsupportedOperationException(e.getMessage());
848:                    }
849:                }
850:            }
851:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.