KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jibx > binding > model > CollectionElement


1 /*
2 Copyright (c) 2004-2005, Dennis M. Sosnoski
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without modification,
6 are permitted provided that the following conditions are met:
7
8  * Redistributions of source code must retain the above copyright notice, this
9    list of conditions and the following disclaimer.
10  * Redistributions in binary form must reproduce the above copyright notice,
11    this list of conditions and the following disclaimer in the documentation
12    and/or other materials provided with the distribution.
13  * Neither the name of JiBX nor the names of its contributors may be used
14    to endorse or promote products derived from this software without specific
15    prior written permission.
16
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
21 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
24 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */

28
29 package org.jibx.binding.model;
30
31 import java.util.ArrayList JavaDoc;
32
33 import org.jibx.binding.util.StringArray;
34 import org.jibx.runtime.IUnmarshallingContext;
35 import org.jibx.runtime.JiBXException;
36
37 /**
38  * Model component for <b>collection</b> element of binding definition.
39  *
40  * @author Dennis M. Sosnoski
41  * @version 1.0
42  */

43  
44 public class CollectionElement extends StructureElementBase
45 {
46     /** Enumeration of allowed attribute names */
47     public static final StringArray s_allowedAttributes =
48         new StringArray(new String JavaDoc[] { "add-method", "item-type", "iter-method",
49         "load-method", "size-method", "store-method" },
50         StructureElementBase.s_allowedAttributes);
51     
52     /** Load method name. */
53     private String JavaDoc m_loadMethodName;
54     
55     /** Size method name. */
56     private String JavaDoc m_sizeMethodName;
57     
58     /** Store method name. */
59     private String JavaDoc m_storeMethodName;
60     
61     /** Add method name. */
62     private String JavaDoc m_addMethodName;
63     
64     /** Iterator method name. */
65     private String JavaDoc m_iterMethodName;
66     
67     /** Item type name. */
68     private String JavaDoc m_itemTypeName;
69     
70     /** Load method information. */
71     private IClassItem m_loadMethodItem;
72     
73     /** Size method information. */
74     private IClassItem m_sizeMethodItem;
75     
76     /** Store method information. */
77     private IClassItem m_storeMethodItem;
78     
79     /** Add method information. */
80     private IClassItem m_addMethodItem;
81     
82     /** Iterator method information. */
83     private IClassItem m_iterMethodItem;
84     
85     /** Item type information. */
86     private IClass m_itemTypeClass;
87     
88     /**
89      * Default constructor.
90      */

91     public CollectionElement() {
92         super(COLLECTION_ELEMENT);
93     }
94
95     /**
96      * Get item type name.
97      *
98      * @return item type name (or <code>null</code> if none)
99      */

100     public String JavaDoc getItemTypeName() {
101         return m_itemTypeName;
102     }
103     
104     /**
105      * Set item type name.
106      *
107      * @param type item type name (or <code>null</code> if none)
108      */

109     public void setItemTypeName(String JavaDoc type) {
110         m_itemTypeName = type;
111     }
112
113     /**
114      * Get item type information. This call is only meaningful after
115      * validation.
116      *
117      * @return item type information (or <code>null</code> if none)
118      */

119     public IClass getItemTypeClass() {
120         return m_itemTypeClass;
121     }
122     
123     /**
124      * Get add method name.
125      *
126      * @return add method name (or <code>null</code> if none)
127      */

128     public String JavaDoc getAddMethodName() {
129         return m_addMethodName;
130     }
131     
132     /**
133      * Set add method name.
134      *
135      * @param name add method name (or <code>null</code> if none)
136      */

137     public void setAddMethodName(String JavaDoc name) {
138         m_addMethodName = name;
139     }
140
141     /**
142      * Get add method information. This call is only meaningful after
143      * validation.
144      *
145      * @return add method information (or <code>null</code> if none)
146      */

147     public IClassItem getAddMethodItem() {
148         return m_addMethodItem;
149     }
150     
151     /**
152      * Get iterator method name.
153      *
154      * @return iterator method name (or <code>null</code> if none)
155      */

156     public String JavaDoc getIterMethodName() {
157         return m_iterMethodName;
158     }
159     
160     /**
161      * Set iterator method name.
162      *
163      * @param name iterator method name (or <code>null</code> if none)
164      */

165     public void setIterMethodName(String JavaDoc name) {
166         m_iterMethodName = name;
167     }
168     
169     /**
170      * Get iterator method information. This call is only meaningful after
171      * validation.
172      *
173      * @return iterator method information (or <code>null</code> if none)
174      */

175     public IClassItem getIterMethodItem() {
176         return m_iterMethodItem;
177     }
178     
179     /**
180      * Get load method name.
181      *
182      * @return load method name (or <code>null</code> if none)
183      */

184     public String JavaDoc getLoadMethodName() {
185         return m_loadMethodName;
186     }
187     
188     /**
189      * Set load method name.
190      *
191      * @param name load method name (or <code>null</code> if none)
192      */

193     public void setLoadMethodName(String JavaDoc name) {
194         m_loadMethodName = name;
195     }
196     
197     /**
198      * Get load method information. This call is only meaningful after
199      * validation.
200      *
201      * @return load method information (or <code>null</code> if none)
202      */

203     public IClassItem getLoadMethodItem() {
204         return m_loadMethodItem;
205     }
206     
207     /**
208      * Get size method name.
209      *
210      * @return size method name (or <code>null</code> if none)
211      */

212     public String JavaDoc getSizeMethodName() {
213         return m_sizeMethodName;
214     }
215     
216     /**
217      * Set size method name.
218      *
219      * @param name size method name (or <code>null</code> if none)
220      */

221     public void setSizeMethodName(String JavaDoc name) {
222         m_sizeMethodName = name;
223     }
224     
225     /**
226      * Get size method information. This call is only meaningful after
227      * validation.
228      *
229      * @return size method information (or <code>null</code> if none)
230      */

231     public IClassItem getSizeMethodItem() {
232         return m_sizeMethodItem;
233     }
234     
235     /**
236      * Get store method name.
237      *
238      * @return store method name (or <code>null</code> if none)
239      */

240     public String JavaDoc getStoreMethodName() {
241         return m_storeMethodName;
242     }
243     
244     /**
245      * Set store method name.
246      *
247      * @param name store method name (or <code>null</code> if none)
248      */

249     public void setStoreMethodName(String JavaDoc name) {
250         m_storeMethodName = name;
251     }
252     
253     /**
254      * Get store method information. This call is only meaningful after
255      * validation.
256      *
257      * @return store method information (or <code>null</code> if none)
258      */

259     public IClassItem getStoreMethodItem() {
260         return m_storeMethodItem;
261     }
262     
263     //
264
// Overrides of base class methods
265

266     /**
267      * Get class linked to binding element. This call is only meaningful after
268      * validation.
269      *
270      * @return information for class linked by binding
271      */

272     public IClass getEffectiveType() {
273         return m_itemTypeClass;
274     }
275     
276     /**
277      * Get class linked to binding element. This call is only meaningful after
278      * validation.
279      *
280      * @return information for class linked by binding
281      */

282     public IClass getActualType() {
283         return m_itemTypeClass;
284     }
285
286     /**
287      * Set ID property. This is never supported for an object coming from a
288      * collection.
289      *
290      * @param child child defining the ID property
291      * @return <code>true</code> if successful, <code>false</code> if ID
292      * already defined
293      */

294     public boolean setIdChild(IComponent child) {
295         throw new IllegalStateException JavaDoc
296             ("Internal error: method should never be called");
297     }
298     
299     //
300
// Validation methods
301

302     /**
303      * Make sure all attributes are defined.
304      *
305      * @param uctx unmarshalling context
306      * @exception JiBXException on unmarshalling error
307      */

308     private void preSet(IUnmarshallingContext uctx) throws JiBXException {
309         validateAttributes(uctx, s_allowedAttributes);
310     }
311     
312     /* (non-Javadoc)
313      * @see org.jibx.binding.model.ElementBase#prevalidate(org.jibx.binding.model.ValidationContext)
314      */

315     public void prevalidate(ValidationContext vctx) {
316         
317         // first process attributes and check for errors
318
super.prevalidate(vctx);
319         if (!vctx.isSkipped(this)) {
320             
321             // get the actual collection type and item type
322
IClass clas = getType();
323             if (clas == null) {
324                 clas = vctx.getContextObject().getActualType();
325             }
326             String JavaDoc tname = m_itemTypeName;
327             if (tname == null) {
328                 tname = "java.lang.Object";
329             }
330             m_itemTypeClass = vctx.getClassInfo(tname);
331             if (m_itemTypeClass == null) {
332                 vctx.addFatal("Can't find class " + tname);
333             }
334             // TODO: check compatibility with specified item-type
335

336             // handle input and output bindings separately
337
if (vctx.isInBinding()) {
338                 
339                 // check store techniques
340
String JavaDoc sname = m_storeMethodName;
341                 String JavaDoc aname = m_addMethodName;
342                 if (sname != null && aname != null) {
343                     vctx.addWarning("Both store-method and add-method " +
344                         "supplied; using add-method");
345                     sname = null;
346                 }
347                 
348                 // set defaults based on collection type if needed
349
if (sname == null && aname == null) {
350                     if (clas.isSuperclass("java.util.ArrayList") ||
351                         clas.isSuperclass("java.util.Vector") ||
352                         clas.isImplements("Ljava/util/Collection;")) {
353                         aname = "add";
354                     } else {
355                         vctx.addError("Need store-method or add-method for " +
356                             "input binding");
357                     }
358                 }
359                 
360                 // find the actual method information
361
if (sname != null) {
362                     m_storeMethodItem = clas.getBestMethod(sname,
363                         null, new String JavaDoc[] { "int", tname });
364                     if (m_storeMethodItem == null) {
365                         vctx.addError("store-method " + sname +
366                             " not found in class " + clas.getName());
367                     }
368                 }
369                 if (aname != null) {
370                     m_addMethodItem = clas.getBestMethod(aname,
371                         null, new String JavaDoc[] { tname });
372                     if (m_addMethodItem == null) {
373                         vctx.addError("add-method " + aname +
374                             " not found in class " + clas.getName());
375                     }
376                 }
377                 
378             }
379             if (vctx.isOutBinding()) {
380                 
381                 // precheck load techniques
382
String JavaDoc lname = m_loadMethodName;
383                 String JavaDoc sname = m_sizeMethodName;
384                 String JavaDoc iname = m_iterMethodName;
385                 if (lname == null) {
386                     if (sname != null) {
387                         vctx.addWarning("size-method requires load-method; " +
388                             "ignoring supplied size-method");
389                         sname = null;
390                     }
391                 } else {
392                     if (sname == null) {
393                         vctx.addWarning("load-method requires " +
394                             "size-method; ignoring supplied load-method");
395                         lname = null;
396                     } else {
397                         if (iname != null) {
398                             vctx.addWarning("Both load-method and " +
399                                 "iter-method supplied; using load-method");
400                             iname = null;
401                         }
402                     }
403                 }
404                 
405                 // set defaults based on collection type if needed
406
if (lname == null && iname == null) {
407                     if (clas.isSuperclass("java.util.ArrayList") ||
408                         clas.isSuperclass("java.util.Vector")) {
409                         lname = "get";
410                         sname = "size";
411                     } else if (clas.isImplements("Ljava/util/Collection;")) {
412                         iname = "iterator";
413                     }
414                 }
415                 
416                 // postcheck load techniques with defaults set
417
if (lname == null) {
418                     if (iname == null) {
419                         vctx.addError("Need load-method and size-method, or " +
420                             "iter-method, for output binding");
421                     }
422                 } else {
423                     if (sname == null && iname == null) {
424                         vctx.addError("Need load-method and size-method," +
425                             " or iter-method, for output binding");
426                     }
427                 }
428                 
429                 // find the actual method information
430
if (lname != null) {
431                     m_loadMethodItem = clas.getBestMethod(lname,
432                         tname, new String JavaDoc[] { "int" });
433                     if (m_loadMethodItem == null) {
434                         vctx.addError("load-method " + lname +
435                             " not found in class " + clas.getName());
436                     }
437                 }
438                 if (iname != null) {
439                     m_iterMethodItem = clas.getBestMethod(iname,
440                         "java.util.Iterator", new String JavaDoc[0]);
441                     if (m_iterMethodItem == null) {
442                         vctx.addError("iter-method " + iname +
443                             " not found in class " + clas.getName());
444                     }
445                 }
446             }
447         }
448     }
449     
450     /* (non-Javadoc)
451      * @see org.jibx.binding.model.ElementBase#validate(org.jibx.binding.model.ValidationContext)
452      */

453     public void validate(ValidationContext vctx) {
454         
455         // call base class method first
456
super.validate(vctx);
457         
458         // check each child component
459
ArrayList JavaDoc children = children();
460         for (int i = 0; i < children.size(); i++) {
461             ElementBase child = (ElementBase)children.get(i);
462             if (child instanceof IComponent) {
463                 IComponent comp = (IComponent)child;
464                 if (!comp.hasName()) {
465                     vctx.addFatal("Child components of collection must " +
466                         "define element names", comp);
467                 }
468                 if (vctx.isInBinding() && !comp.hasType()) {
469                     if (children.size() != 1) {
470                         vctx.addFatal("Child components of collection must " +
471                             "define type", comp);
472                     }
473                 }
474                 if (m_itemTypeClass != null) {
475                     if (comp.hasType()) {
476                         IClass ctype = comp.getType();
477                         if (!ctype.isAssignable(m_itemTypeClass)) {
478                             vctx.addFatal("Child components of collection " +
479                                 "must have types compatible with specified " +
480                                 "item-type of collection", comp);
481                         }
482                     }
483                 }
484             }
485         }
486     }
487 }
Popular Tags