KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > ojb > odmg > collections > DListImpl


1 package org.apache.ojb.odmg.collections;
2
3 /* Copyright 2003-2005 The Apache Software Foundation
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17
18 import java.util.AbstractList JavaDoc;
19 import java.util.ArrayList JavaDoc;
20 import java.util.Iterator JavaDoc;
21 import java.util.List JavaDoc;
22 import java.util.ListIterator JavaDoc;
23
24 import org.apache.commons.lang.builder.ToStringBuilder;
25 import org.apache.ojb.broker.ManageableCollection;
26 import org.apache.ojb.broker.OJBRuntimeException;
27 import org.apache.ojb.broker.PBKey;
28 import org.apache.ojb.broker.PersistenceBroker;
29 import org.apache.ojb.broker.PersistenceBrokerAware;
30 import org.apache.ojb.broker.PersistenceBrokerException;
31 import org.apache.ojb.broker.core.ValueContainer;
32 import org.apache.ojb.broker.metadata.ClassDescriptor;
33 import org.apache.ojb.broker.metadata.FieldDescriptor;
34 import org.apache.ojb.broker.query.Criteria;
35 import org.apache.ojb.broker.query.Query;
36 import org.apache.ojb.broker.query.QueryByCriteria;
37 import org.apache.ojb.broker.util.logging.Logger;
38 import org.apache.ojb.broker.util.logging.LoggerFactory;
39 import org.apache.ojb.odmg.PBCapsule;
40 import org.apache.ojb.odmg.TransactionImpl;
41 import org.apache.ojb.odmg.TxManagerFactory;
42 import org.apache.ojb.odmg.RuntimeObject;
43 import org.apache.ojb.odmg.oql.OQLQueryImpl;
44 import org.odmg.DArray;
45 import org.odmg.DCollection;
46 import org.odmg.DList;
47 import org.odmg.ODMGRuntimeException;
48 import org.odmg.OQLQuery;
49 import org.odmg.QueryInvalidException;
50 import org.odmg.Transaction;
51
52
53 /**
54  *
55  * @author Thomas Mahler
56  * @author <a HREF="mailto:armin@codeAuLait.de">Armin Waibel</a>
57  * @version $Id: DListImpl.java,v 1.27.2.5 2005/12/21 22:29:50 tomdz Exp $
58  */

59 public class DListImpl extends AbstractList JavaDoc implements DList, DArray,
60         ManageableCollection, PersistenceBrokerAware
61 {
62     private static final long serialVersionUID = -9219943066614026526L;
63
64     private transient Logger log;
65
66     private Integer JavaDoc id;
67     private List JavaDoc elements;
68
69     private PBKey pbKey;
70
71     /**
72      * Used by PB-Kernel to instantiate ManageableCollections
73      * FOR INTERNAL USE ONLY
74      */

75     public DListImpl()
76     {
77         super();
78         elements = new ArrayList JavaDoc();
79 // if(getTransaction() == null)
80
// {
81
// throw new TransactionNotInProgressException("Materialization of DCollection instances must be done" +
82
// " within a odmg-tx");
83
// }
84
getPBKey();
85     }
86
87     /**
88      * Used on odmg-level
89      */

90     public DListImpl(PBKey pbKey)
91     {
92         this();
93         this.pbKey = pbKey;
94     }
95
96     protected Logger getLog()
97     {
98         if (log == null)
99         {
100             log = LoggerFactory.getLogger(DListImpl.class);
101         }
102         return log;
103     }
104
105     private DListEntry prepareEntry(Object JavaDoc obj)
106     {
107         return new DListEntry(this, obj);
108     }
109
110     protected TransactionImpl getTransaction()
111     {
112         return TxManagerFactory.instance().getTransaction();
113     }
114
115     protected boolean checkForOpenTransaction(TransactionImpl tx)
116     {
117         boolean result = false;
118         if(tx != null && tx.isOpen())
119         {
120             result = true;
121         }
122         return result;
123     }
124
125     public PBKey getPBKey()
126     {
127         if(pbKey == null)
128         {
129             TransactionImpl tx = getTransaction();
130             if(tx != null && tx.isOpen())
131             {
132                 pbKey = tx.getBroker().getPBKey();
133             }
134         }
135         return pbKey;
136     }
137
138     public void setPBKey(PBKey pbKey)
139     {
140         this.pbKey = pbKey;
141     }
142
143     /**
144      * Inserts the specified element at the specified position in this list
145      * (optional operation). Shifts the element currently at that position
146      * (if any) and any subsequent elements to the right (adds one to their
147      * indices).
148      *
149      * @param index index at which the specified element is to be inserted.
150      * @param element element to be inserted.
151      *
152      * @throws UnsupportedOperationException if the <tt>add</tt> method is not
153      * supported by this list.
154      * @throws ClassCastException if the class of the specified element
155      * prevents it from being added to this list.
156      * @throws IllegalArgumentException if some aspect of the specified
157      * element prevents it from being added to this list.
158      * @throws IndexOutOfBoundsException if the index is out of range
159      * (index &lt; 0 || index &gt; size()).
160      */

161     public void add(int index, Object JavaDoc element)
162     {
163         DListEntry entry = prepareEntry(element);
164         elements.add(index, entry);
165         // if we are in a transaction: acquire locks !
166
TransactionImpl tx = getTransaction();
167         if (checkForOpenTransaction(tx))
168         {
169             RuntimeObject rt = new RuntimeObject(this, tx);
170             List JavaDoc regList = tx.getRegistrationList();
171             tx.lockAndRegister(rt, Transaction.WRITE, false, regList);
172
173             rt = new RuntimeObject(element, tx);
174             tx.lockAndRegister(rt, Transaction.READ, regList);
175
176             rt = new RuntimeObject(entry, tx, true);
177             tx.lockAndRegister(rt, Transaction.WRITE, false, regList);
178         }
179
180         // changing the position markers of entries:
181
int offset = 0;
182         try
183         {
184             offset = ((DListEntry) elements.get(index - 1)).getPosition();
185         }
186         catch (Exception JavaDoc ignored)
187         {
188         }
189         for (int i = offset; i < elements.size(); i++)
190         {
191             entry = (DListEntry) elements.get(i);
192             entry.setPosition(i);
193         }
194     }
195
196     /**
197      * Removes the element at the specified position in this list (optional
198      * operation). Shifts any subsequent elements to the left (subtracts one
199      * from their indices). Returns the element that was removed from the
200      * list.<p>
201      *
202      * This implementation always throws an
203      * <tt>UnsupportedOperationException</tt>.
204      *
205      * @param index the index of the element to remove.
206      * @return the element previously at the specified position.
207      *
208      * @throws UnsupportedOperationException if the <tt>remove</tt> method is
209      * not supported by this list.
210      * @throws IndexOutOfBoundsException if the specified index is out of
211      * range (<tt>index &lt; 0 || index &gt;= size()</tt>).
212      */

213     public Object JavaDoc remove(int index)
214     {
215         DListEntry entry = (DListEntry) elements.get(index);
216         // if we are in a transaction: acquire locks !
217
TransactionImpl tx = getTransaction();
218         if (checkForOpenTransaction(tx))
219         {
220             tx.deletePersistent(new RuntimeObject(entry, tx));
221         }
222         elements.remove(index);
223         // changing the position markers of entries:
224
int offset = 0;
225         try
226         {
227             offset = ((DListEntry) elements.get(index)).getPosition();
228         }
229         catch (Exception JavaDoc ignored)
230         {
231         }
232         for (int i = offset; i < elements.size(); i++)
233         {
234             entry = (DListEntry) elements.get(i);
235             entry.setPosition(i);
236         }
237
238         return entry.getRealSubject();
239     }
240
241     /**
242      * Creates a new <code>DList</code> object that contains the contents of this
243      * <code>DList</code> object concatenated
244      * with the contents of the <code>otherList</code> object.
245      * @param otherList The list whose elements are placed at the end of the list
246      * returned by this method.
247      * @return A new <code>DList</code> that is the concatenation of this list and
248      * the list referenced by <code>otherList</code>.
249      */

250     public DList concat(DList otherList)
251     {
252         DListImpl result = new DListImpl(pbKey);
253         result.addAll(this);
254         result.addAll(otherList);
255         return result;
256     }
257
258     /**
259      * Determines whether there is an element of the collection that evaluates to true
260      * for the predicate.
261      * @param predicate An OQL boolean query predicate.
262      * @return True if there is an element of the collection that evaluates to true
263      * for the predicate, otherwise false.
264      * @exception org.odmg.QueryInvalidException The query predicate is invalid.
265      */

266     public boolean existsElement(String JavaDoc predicate) throws org.odmg.QueryInvalidException
267     {
268         DList results = (DList) this.query(predicate);
269         if (results == null || results.size() == 0)
270             return false;
271         else
272             return true;
273     }
274
275     /**
276      * Returns the element at the specified position in this list.
277      *
278      * @param index index of element to return.
279      * @return the element at the specified position in this list.
280      *
281      * @throws IndexOutOfBoundsException if the index is out of range (index
282      * &lt; 0 || index &gt;= size()).
283      */

284     public Object JavaDoc get(int index)
285     {
286         DListEntry entry = (DListEntry) elements.get(index);
287         return entry.getRealSubject();
288     }
289
290     /**
291      * Insert the method's description here.
292      * Creation date: (10.02.2001 20:53:01)
293      * @return java.util.Vector
294      */

295     public List JavaDoc getElements()
296     {
297         return elements;
298     }
299
300     /**
301      * Lazily return the Id, no point in precomputing it.
302      * @return int
303      */

304     public Integer JavaDoc getId()
305     {
306         return id;
307     }
308
309     /**
310      * Returns an iterator over the elements in this collection. There are no
311      * guarantees concerning the order in which the elements are returned
312      * (unless this collection is an instance of some class that provides a
313      * guarantee).
314      *
315      * @return an <tt>Iterator</tt> over the elements in this collection
316      */

317     public Iterator JavaDoc iterator()
318     {
319         return new DListIterator(this);
320     }
321
322     /**
323      * Returns a list iterator of the elements in this list (in proper
324      * sequence).
325      *
326      * @return a list iterator of the elements in this list (in proper
327      * sequence).
328      */

329     public ListIterator JavaDoc listIterator()
330     {
331         return new DListIterator(this);
332     }
333
334     /**
335      * Returns a list iterator of the elements in this list (in proper
336      * sequence), starting at the specified position in this list. The
337      * specified index indicates the first element that would be returned by
338      * an initial call to the <tt>next</tt> method. An initial call to
339      * the <tt>previous</tt> method would return the element with the
340      * specified index minus one.
341      *
342      * @param index index of first element to be returned from the
343      * list iterator (by a call to the <tt>next</tt> method).
344      * @return a list iterator of the elements in this list (in proper
345      * sequence), starting at the specified position in this list.
346      * @throws IndexOutOfBoundsException if the index is out of range (index
347      * &lt; 0 || index &gt; size()).
348      */

349     public ListIterator JavaDoc listIterator(int index)
350     {
351         return new DListIterator(this, index);
352     }
353
354     private Criteria getPkCriteriaForAllElements(PersistenceBroker brokerForClass)
355     {
356         try
357         {
358             Criteria crit = null;
359             for (int i = 0; i < elements.size(); i++)
360             {
361                 DListEntry entry = (DListEntry) elements.get(i);
362                 Object JavaDoc obj = entry.getRealSubject();
363                 ClassDescriptor cld = brokerForClass.getClassDescriptor(obj.getClass());
364
365                 FieldDescriptor[] pkFields = cld.getPkFields();
366                 ValueContainer[] pkValues = brokerForClass.serviceBrokerHelper().getKeyValues(cld, obj);
367
368                 Criteria criteria = new Criteria();
369                 for (int j = 0; j < pkFields.length; j++)
370                 {
371                     FieldDescriptor fld = pkFields[j];
372                     criteria.addEqualTo(fld.getPersistentField().getName(), pkValues[j].getValue());
373                 }
374
375                 if (crit == null)
376                     crit = criteria;
377                 else
378                     crit.addOrCriteria(criteria);
379             }
380             return crit;
381         }
382         catch (PersistenceBrokerException e)
383         {
384             return null;
385         }
386     }
387
388     private Class JavaDoc getElementsExtentClass(PersistenceBroker brokerForClass) throws PersistenceBrokerException
389     {
390         // we ll have to compute the most general extent class here !!!
391
DListEntry entry = (DListEntry) elements.get(0);
392         Class JavaDoc elementsClass = entry.getRealSubject().getClass();
393         Class JavaDoc extentClass = brokerForClass.getTopLevelClass(elementsClass);
394         return extentClass;
395     }
396
397     /**
398      * Evaluate the boolean query predicate for each element of the collection and
399      * return a new collection that contains each element that evaluated to true.
400      * @param predicate An OQL boolean query predicate.
401      * @return A new collection containing the elements that evaluated true for the predicate.
402      * @exception org.odmg.QueryInvalidException The query predicate is invalid.
403      */

404     public DCollection query(String JavaDoc predicate) throws QueryInvalidException
405     {
406         // 1.build complete OQL statement
407
String JavaDoc oql = "select all from java.lang.Object where " + predicate;
408         TransactionImpl tx = getTransaction();
409         if (tx == null) throw new QueryInvalidException("Need running transaction to do query");
410
411         OQLQuery predicateQuery = tx.getImplementation().newOQLQuery();
412         predicateQuery.create(oql);
413         Query pQ = ((OQLQueryImpl) predicateQuery).getQuery();
414         Criteria pCrit = pQ.getCriteria();
415
416         PBCapsule handle = new PBCapsule(pbKey, tx);
417         DList result;
418         try
419         {
420             PersistenceBroker broker = handle.getBroker();
421             Criteria allElementsCriteria = this.getPkCriteriaForAllElements(broker);
422             // join selection of elements with predicate criteria:
423
allElementsCriteria.addAndCriteria(pCrit);
424
425             Class JavaDoc clazz = null;
426             try
427             {
428                 clazz = this.getElementsExtentClass(broker);
429             }
430             catch (PersistenceBrokerException e)
431             {
432                 getLog().error(e);
433                 throw new ODMGRuntimeException(e.getMessage());
434             }
435             Query q = new QueryByCriteria(clazz, allElementsCriteria);
436             if (getLog().isDebugEnabled()) getLog().debug(q.toString());
437
438             result = null;
439             try
440             {
441                 result = (DList) broker.getCollectionByQuery(DListImpl.class, q);
442             }
443             catch (PersistenceBrokerException e)
444             {
445                 getLog().error("Query failed", e);
446                 throw new OJBRuntimeException(e);
447             }
448         }
449         finally
450         {
451             // cleanup stuff
452
if (handle != null) handle.destroy();
453         }
454
455         // 3. return resulting collection
456
return result;
457
458     }
459
460     public int hashCode()
461     {
462         int hashCode = 1;
463         Iterator JavaDoc it = elements.iterator();
464         while (it.hasNext())
465         {
466             Object JavaDoc obj = it.next();
467             hashCode = 31 * hashCode + (obj == null ? 0 : obj.hashCode());
468         }
469         return hashCode;
470     }
471
472     public String JavaDoc toString()
473     {
474         ToStringBuilder buf = new ToStringBuilder(this);
475         buf.append("id", id);
476         buf.append("pbKey", pbKey);
477         buf.append("[containing elements: ");
478         Iterator JavaDoc it = elements.iterator();
479         while (it.hasNext())
480         {
481             Object JavaDoc obj = it.next();
482             buf.append(obj != null ? obj.toString() : null);
483         }
484         buf.append("]");
485         return buf.toString();
486     }
487
488     /**
489      * Access all of the elements of the collection that evaluate to true for the
490      * provided query predicate.
491      * @param predicate An OQL boolean query predicate.
492      * @return An iterator used to iterate over the elements that evaluated true for the predicate.
493      * @exception org.odmg.QueryInvalidException The query predicate is invalid.
494      */

495     public Iterator JavaDoc select(String JavaDoc predicate) throws org.odmg.QueryInvalidException
496     {
497         return this.query(predicate).iterator();
498     }
499
500     /**
501      * Selects the single element of the collection for which the provided OQL query
502      * predicate is true.
503      * @param predicate An OQL boolean query predicate.
504      * @return The element that evaluates to true for the predicate. If no element
505      * evaluates to true, null is returned.
506      * @exception org.odmg.QueryInvalidException The query predicate is invalid.
507      */

508     public Object JavaDoc selectElement(String JavaDoc predicate) throws org.odmg.QueryInvalidException
509     {
510         return ((DList) this.query(predicate)).get(0);
511     }
512
513     /**
514      * Returns the number of elements in this collection. If this collection
515      * contains more than <tt>Integer.MAX_VALUE</tt> elements, returns
516      * <tt>Integer.MAX_VALUE</tt>.
517      *
518      * @return the number of elements in this collection
519      */

520     public int size()
521     {
522         return elements.size();
523     }
524
525     /**
526      * add a single Object to the Collection. This method is used during reading Collection elements
527      * from the database. Thus it is is save to cast anObject to the underlying element type of the
528      * collection.
529      */

530     public void ojbAdd(Object JavaDoc anObject)
531     {
532         DListEntry entry = prepareEntry(anObject);
533         entry.setPosition(elements.size());
534         elements.add(entry);
535     }
536
537     /**
538      * adds a Collection to this collection. Used in reading Extents from the Database.
539      * Thus it is save to cast otherCollection to this.getClass().
540      */

541     public void ojbAddAll(ManageableCollection otherCollection)
542     {
543         // don't use this to avoid locking
544
// this.addAll((DListImpl) otherCollection);
545
Iterator JavaDoc it = otherCollection.ojbIterator();
546         while (it.hasNext())
547         {
548             ojbAdd(it.next());
549         }
550     }
551
552     public void afterStore(PersistenceBroker broker) throws PersistenceBrokerException
553     {
554     }
555
556     /**
557      * returns an Iterator over all elements in the collection. Used during store and delete Operations.
558      * If the implementor does not return an iterator over ALL elements, OJB cannot store and delete all elements properly.
559      */

560     public Iterator JavaDoc ojbIterator()
561     {
562         return this.iterator();
563     }
564
565     /**
566      * Resize the array to have <code>newSize</code> elements.
567      * @param newSize The new size of the array.
568      */

569     public void resize(int newSize)
570     {
571     }
572
573     /**
574      * Sets the elements.
575      * @param elements The elements to set
576      */

577     public void setElements(List JavaDoc elements)
578     {
579         this.elements = elements;
580     }
581
582     /**
583      * Sets the id.
584      * @param id The id to set
585      */

586     public void setId(Integer JavaDoc id)
587     {
588         this.id = id;
589     }
590
591
592     //***************************************************************
593
// PersistenceBrokerAware interface
594
//***************************************************************
595

596     /**
597      * prepare itself for persistence. Each DList entry generates an
598      * {@link org.apache.ojb.broker.Identity} for the wrapped persistent
599      * object.
600      */

601     public void beforeInsert(PersistenceBroker broker) throws PersistenceBrokerException
602     {
603 // Iterator it = elements.iterator();
604
// DListEntry entry;
605
// while (it.hasNext())
606
// {
607
// entry = (DListEntry) it.next();
608
// entry.prepareForPersistency(broker);
609
// }
610
}
611
612     /**
613      * noop
614      */

615     public void beforeUpdate(PersistenceBroker broker) throws PersistenceBrokerException
616     {
617     }
618
619     /**
620      * noop
621      */

622     public void beforeDelete(PersistenceBroker broker) throws PersistenceBrokerException
623     {
624     }
625
626     /**
627      * noop
628      */

629     public void afterUpdate(PersistenceBroker broker) throws PersistenceBrokerException
630     {
631     }
632
633     /**
634      * noop
635      */

636     public void afterInsert(PersistenceBroker broker) throws PersistenceBrokerException
637     {
638     }
639
640     /**
641      * noop
642      */

643     public void afterDelete(PersistenceBroker broker) throws PersistenceBrokerException
644     {
645     }
646
647     /**
648      * noop
649      */

650     public void afterLookup(PersistenceBroker broker) throws PersistenceBrokerException
651     {
652     }
653 }
654
Popular Tags