KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > ejb > plugins > cmp > jdbc > bridge > RelationSet


1 /*
2 * JBoss, Home of Professional Open Source
3 * Copyright 2005, JBoss Inc., and individual contributors as indicated
4 * by the @authors tag. See the copyright.txt in the distribution for a
5 * full listing of individual contributors.
6 *
7 * This is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
11 *
12 * This software is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this software; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21 */

22 package org.jboss.ejb.plugins.cmp.jdbc.bridge;
23
24 import java.util.Collection JavaDoc;
25 import java.util.ConcurrentModificationException JavaDoc;
26 import java.util.ArrayList JavaDoc;
27 import java.util.Iterator JavaDoc;
28 import java.util.List JavaDoc;
29 import java.util.Set JavaDoc;
30 import java.util.HashSet JavaDoc;
31 import javax.ejb.EJBException JavaDoc;
32 import javax.ejb.EJBLocalObject JavaDoc;
33 import javax.ejb.NoSuchObjectLocalException JavaDoc;
34
35 import org.jboss.ejb.EntityEnterpriseContext;
36 import org.jboss.ejb.LocalProxyFactory;
37
38 /**
39  * This is the relationship set. An instance of this class
40  * is returned when collection valued cmr field is accessed.
41  * See the EJB 2.0 specification for a more detailed description
42  * or the responsibilities of this class.
43  *
44  * @author <a HREF="mailto:dain@daingroup.com">Dain Sundstrom</a>
45  * @version $Revision: 37459 $
46  */

47 public class RelationSet implements Set JavaDoc
48 {
49    private JDBCCMRFieldBridge cmrField;
50    private EntityEnterpriseContext ctx;
51    private List JavaDoc[] setHandle;
52    private boolean readOnly;
53    private Class JavaDoc relatedLocalInterface;
54
55    //
56
// Most of this class is a boring wrapper arround the id set.
57
// The only interesting hitch is the setHandle. This class doesn't
58
// have a direct referance to the related id set, it has a referance
59
// to a referance to the set. When the transaction is completed the
60
// CMR field sets my referance to the set to null, so that I know that
61
// this set is no longer valid. See the ejb spec for more info.
62
//
63
public RelationSet(
64       JDBCCMRFieldBridge cmrField,
65       EntityEnterpriseContext ctx,
66       List JavaDoc[] setHandle,
67       boolean readOnly)
68    {
69
70       this.cmrField = cmrField;
71       this.ctx = ctx;
72       this.setHandle = setHandle;
73       this.readOnly = readOnly;
74       relatedLocalInterface = cmrField.getRelatedLocalInterface();
75    }
76
77    private List JavaDoc getIdList()
78    {
79       if(setHandle[0] == null)
80       {
81          throw new IllegalStateException JavaDoc("A CMR collection may only be used " +
82             "within the transction in which it was created");
83       }
84       return setHandle[0];
85    }
86
87    public int size()
88    {
89       List JavaDoc idList = getIdList();
90       return idList.size();
91    }
92
93    public boolean isEmpty()
94    {
95       List JavaDoc idList = getIdList();
96       return idList.isEmpty();
97    }
98
99    public boolean add(Object JavaDoc o)
100    {
101       if(o == null)
102       {
103          throw new IllegalArgumentException JavaDoc("Null cannot be added to a CMR " +
104             "relationship collection");
105       }
106
107       checkForPKChange();
108
109       List JavaDoc idList = getIdList();
110       if(readOnly)
111       {
112          throw new EJBException JavaDoc("This collection is a read-only snapshot");
113       }
114
115       if(cmrField.isReadOnly())
116       {
117          throw new EJBException JavaDoc("Field is read-only: " +
118             cmrField.getFieldName());
119       }
120
121       if(!relatedLocalInterface.isInstance(o))
122       {
123          String JavaDoc msg = "Object must be an instance of " +
124             relatedLocalInterface.getName() + ", but is an isntance of [";
125          Class JavaDoc[] classes = o.getClass().getInterfaces();
126          for(int i = 0; i < classes.length; i++)
127          {
128             if(i > 0) msg += ", ";
129             msg += classes[i].getName();
130          }
131          msg += "]";
132          throw new IllegalArgumentException JavaDoc(msg);
133       }
134
135       Object JavaDoc id = getPrimaryKey((EJBLocalObject JavaDoc) o);
136       if(idList.contains(id))
137       {
138          return false;
139       }
140       cmrField.createRelationLinks(ctx, id);
141       return true;
142    }
143
144    public boolean addAll(Collection JavaDoc c)
145    {
146       if(readOnly)
147       {
148          throw new EJBException JavaDoc("This collection is a read-only snapshot");
149       }
150       if(cmrField.isReadOnly())
151       {
152          throw new EJBException JavaDoc("Field is read-only: " +
153             cmrField.getFieldName());
154       }
155
156       if(c == null)
157       {
158          return false;
159       }
160
161       boolean isModified = false;
162
163       Iterator JavaDoc iterator = (new HashSet JavaDoc(c)).iterator();
164       while(iterator.hasNext())
165       {
166          isModified = add(iterator.next()) || isModified;
167       }
168       return isModified;
169    }
170
171    public boolean remove(Object JavaDoc o)
172    {
173       List JavaDoc idList = getIdList();
174       if(readOnly)
175       {
176          throw new EJBException JavaDoc("This collection is a read-only snapshot");
177       }
178       if(cmrField.isReadOnly())
179       {
180          throw new EJBException JavaDoc("Field is read-only: " +
181             cmrField.getFieldName());
182       }
183
184       checkForPKChange();
185
186       if(!relatedLocalInterface.isInstance(o))
187       {
188          throw new IllegalArgumentException JavaDoc("Object must be an instance of " +
189             relatedLocalInterface.getName());
190       }
191
192       Object JavaDoc id = getPrimaryKey((EJBLocalObject JavaDoc) o);
193       if(!idList.contains(id))
194       {
195          return false;
196       }
197       cmrField.destroyRelationLinks(ctx, id);
198       return true;
199    }
200
201    public boolean removeAll(Collection JavaDoc c)
202    {
203       if(readOnly)
204       {
205          throw new EJBException JavaDoc("This collection is a read-only snapshot");
206       }
207       if(cmrField.isReadOnly())
208       {
209          throw new EJBException JavaDoc("Field is read-only: " +
210             cmrField.getFieldName());
211       }
212
213       if(c == null)
214       {
215          return false;
216       }
217
218       boolean isModified = false;
219
220       Iterator JavaDoc iterator = (new HashSet JavaDoc(c)).iterator();
221       while(iterator.hasNext())
222       {
223          isModified = remove(iterator.next()) || isModified;
224       }
225       return isModified;
226    }
227
228    public void clear()
229    {
230       checkForPKChange();
231
232       List JavaDoc idList = getIdList();
233       if(readOnly)
234       {
235          throw new EJBException JavaDoc("This collection is a read-only snapshot");
236       }
237       if(cmrField.isReadOnly())
238       {
239          throw new EJBException JavaDoc("Field is read-only: " +
240             cmrField.getFieldName());
241       }
242
243       Iterator JavaDoc iterator = (new ArrayList JavaDoc(idList)).iterator();
244       while(iterator.hasNext())
245       {
246          cmrField.destroyRelationLinks(ctx, iterator.next());
247       }
248    }
249
250    public boolean retainAll(Collection JavaDoc c)
251    {
252       List JavaDoc idList = getIdList();
253       if(readOnly)
254       {
255          throw new EJBException JavaDoc("This collection is a read-only snapshot");
256       }
257       if(cmrField.isReadOnly())
258       {
259          throw new EJBException JavaDoc("Field is read-only: " +
260             cmrField.getFieldName());
261       }
262
263       checkForPKChange();
264
265       if(c == null)
266       {
267          if(idList.size() == 0)
268          {
269             return false;
270          }
271          clear();
272          return true;
273       }
274
275       // get a set of the argument collection's ids
276
List JavaDoc argIds = new ArrayList JavaDoc();
277       Iterator JavaDoc iterator = c.iterator();
278       while(iterator.hasNext())
279       {
280          EJBLocalObject JavaDoc localObject = (EJBLocalObject JavaDoc) iterator.next();
281          Object JavaDoc relatedId = getPrimaryKey(localObject);
282          argIds.add(relatedId);
283       }
284
285       boolean isModified = false;
286
287       iterator = (new ArrayList JavaDoc(idList)).iterator();
288       while(iterator.hasNext())
289       {
290          Object JavaDoc id = iterator.next();
291          if(!argIds.contains(id))
292          {
293             cmrField.destroyRelationLinks(ctx, id);
294             isModified = true;
295          }
296       }
297       return isModified;
298    }
299
300    public boolean contains(Object JavaDoc o)
301    {
302       List JavaDoc idList = getIdList();
303
304       if(!relatedLocalInterface.isInstance(o))
305       {
306          throw new IllegalArgumentException JavaDoc("Object must be an instance of " +
307             relatedLocalInterface.getName());
308       }
309
310       Object JavaDoc id = getPrimaryKey((EJBLocalObject JavaDoc) o);
311       return idList.contains(id);
312    }
313
314    public boolean containsAll(Collection JavaDoc c)
315    {
316       List JavaDoc idList = getIdList();
317
318       if(c == null)
319       {
320          return true;
321       }
322
323       // get a set of the argument collection's ids
324
List JavaDoc argIds = new ArrayList JavaDoc();
325       Iterator JavaDoc iterator = c.iterator();
326       while(iterator.hasNext())
327       {
328          EJBLocalObject JavaDoc localObject = (EJBLocalObject JavaDoc) iterator.next();
329          Object JavaDoc relatedId = getPrimaryKey(localObject);
330          argIds.add(relatedId);
331       }
332
333       return idList.containsAll(argIds);
334    }
335
336    public Object JavaDoc[] toArray(Object JavaDoc a[])
337    {
338       List JavaDoc idList = getIdList();
339
340       Collection JavaDoc c = cmrField.getRelatedInvoker().getEntityLocalCollection(idList);
341       return c.toArray(a);
342    }
343
344    public Object JavaDoc[] toArray()
345    {
346       List JavaDoc idList = getIdList();
347       Collection JavaDoc c = cmrField.getRelatedInvoker().getEntityLocalCollection(idList);
348       return c.toArray();
349    }
350
351    // Private
352

353    private static void checkForPKChange()
354    {
355       /**
356        * Uncomment to disallow attempts to override PK value with equal FK value
357        *
358        if(cmrField.getRelatedCMRField().allFkFieldsMappedToPkFields()) {
359        throw new IllegalStateException(
360        "Can't modify relationship: CMR field "
361        + cmrField.getRelatedEntity().getEntityName() + "." + cmrField.getRelatedCMRField().getFieldName()
362        + " has _ALL_ foreign key fields mapped to the primary key columns."
363        + " Primary key may only be set once in ejbCreate [EJB 2.0 Spec. 10.3.5].");
364        }
365        */

366    }
367
368    // Inner
369

370    public Iterator JavaDoc iterator()
371    {
372       return new Iterator JavaDoc()
373       {
374          private final Iterator JavaDoc idIterator = getIdList().iterator();
375          private final LocalProxyFactory localFactory = cmrField.getRelatedInvoker();
376          private Object JavaDoc currentId;
377
378          public boolean hasNext()
379          {
380             verifyIteratorIsValid();
381
382             try
383             {
384                return idIterator.hasNext();
385             }
386             catch(ConcurrentModificationException JavaDoc e)
387             {
388                throw new IllegalStateException JavaDoc("Underlying collection has " +
389                   "been modified");
390             }
391          }
392
393          public Object JavaDoc next()
394          {
395             verifyIteratorIsValid();
396
397             try
398             {
399                currentId = idIterator.next();
400                return localFactory.getEntityEJBLocalObject(currentId);
401             }
402             catch(ConcurrentModificationException JavaDoc e)
403             {
404                throw new IllegalStateException JavaDoc("Underlying collection has " +
405                   "been modified");
406             }
407          }
408
409          public void remove()
410          {
411             verifyIteratorIsValid();
412             if(readOnly)
413             {
414                throw new EJBException JavaDoc("This collection is a read-only snapshot");
415             }
416             if(cmrField.isReadOnly())
417             {
418                throw new EJBException JavaDoc("Field is read-only: " +
419                   cmrField.getFieldName());
420             }
421
422             checkForPKChange();
423
424             try
425             {
426                idIterator.remove();
427                cmrField.destroyRelationLinks(ctx, currentId, false);
428             }
429             catch(ConcurrentModificationException JavaDoc e)
430             {
431                throw new IllegalStateException JavaDoc("Underlying collection has been modified");
432             }
433          }
434
435          private void verifyIteratorIsValid()
436          {
437             if(setHandle[0] == null)
438             {
439                throw new IllegalStateException JavaDoc("The iterator of a CMR " +
440                   "collection may only be used within the transction in " +
441                   "which it was created");
442             }
443          }
444       };
445    }
446
447    public String JavaDoc toString()
448    {
449       return new StringBuffer JavaDoc()
450          .append('[')
451          .append(cmrField.getEntity().getEntityName())
452          .append('.')
453          .append(cmrField.getFieldName())
454          .append(':')
455          .append(getIdList()).append(']')
456          .toString();
457    }
458
459    private Object JavaDoc getPrimaryKey(EJBLocalObject JavaDoc o)
460    {
461       try
462       {
463          return o.getPrimaryKey();
464       }
465       catch(NoSuchObjectLocalException JavaDoc e)
466       {
467          throw new IllegalArgumentException JavaDoc(e.getMessage());
468       }
469    }
470 }
471
Popular Tags