KickJava   Java API By Example, From Geeks To Geeks.

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


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.EnumSet;
35
36 /**
37  * Model component for <i>property</i> attribute group in binding definition.
38  *
39  * @author Dennis M. Sosnoski
40  * @version 1.0
41  */

42  
43 public class PropertyAttributes extends AttributeBase
44 {
45     /** Enumeration of allowed attribute names */
46     public static final StringArray s_allowedAttributes =
47         new StringArray(new String JavaDoc[] { "field", "get-method", "set-method",
48         "test-method", "type", "usage" });
49     
50     //
51
// Value set information
52

53     public static final int REQUIRED_USAGE = 0;
54     public static final int OPTIONAL_USAGE = 1;
55     public static final int OPTIONAL_IN_USAGE = 2;
56     public static final int OPTIONAL_OUT_USAGE = 3;
57     private static final EnumSet s_usageEnum = new EnumSet(REQUIRED_USAGE,
58         new String JavaDoc[] { "required", "optional", "opt-in", "opt-out" });
59     
60     //
61
// Instance data.
62

63     /** Usage type code. */
64     private int m_usage;
65     
66     /** Usage name. */
67     private String JavaDoc m_usageName = s_usageEnum.getName(REQUIRED_USAGE);
68     
69     /** Property type name. */
70     private String JavaDoc m_declaredType;
71     
72     /** Property field name. */
73     private String JavaDoc m_fieldName;
74     
75     /** Test method name. */
76     private String JavaDoc m_testName;
77     
78     /** Get method name. */
79     private String JavaDoc m_getName;
80     
81     /** Set method name. */
82     private String JavaDoc m_setName;
83     
84     /** Type for value loaded on stack. */
85     private IClass m_getType;
86     
87     /** Type for value stored from stack. */
88     private IClass m_setType;
89     
90     /** Property type information. */
91     private IClass m_type;
92     
93     /** Property field information. */
94     private IClassItem m_fieldItem;
95     
96     /** Test method information. */
97     private IClassItem m_testItem;
98     
99     /** Get method information. */
100     private IClassItem m_getItem;
101     
102     /** Set method information. */
103     private IClassItem m_setItem;
104     
105     /** Flag for no actual property definition. */
106     private boolean m_isImplicit;
107     
108     /**
109      * Get usage name.
110      *
111      * @return usage name
112      */

113     public String JavaDoc getUsageName() {
114         return s_usageEnum.getName(m_usage);
115     }
116     
117     /**
118      * Get usage value. This method is only usable after a call to {@link
119      * #validate}.
120      *
121      * @return usage value
122      */

123     public int getUsage() {
124         return m_usage;
125     }
126     
127     /**
128      * Set usage name.
129      *
130      * @param name usage name
131      */

132     public void setUsageName(String JavaDoc name) {
133         m_usageName = name;
134     }
135     
136     /**
137      * Check if property is defined. This method is only usable after a call to
138      * {@link #validate}.
139      *
140      * @return <code>true</code> if property defined, <code>false</code> if not
141      */

142     public boolean hasProperty() {
143         return !m_isImplicit && m_type != null;
144     }
145     
146     /**
147      * Get declared type name.
148      *
149      * @return declared type name (or <code>null</code> if none)
150      */

151     public String JavaDoc getDeclaredType() {
152         return m_declaredType;
153     }
154     
155     /**
156      * Get type information. This method is only usable after a call to {@link
157      * #validate}.
158      *
159      * @return type information (or <code>null</code> if none)
160      */

161     public IClass getType() {
162         return m_type;
163     }
164     
165     /**
166      * Set declared type name.
167      *
168      * @param declared type name (or <code>null</code> if none)
169      */

170     public void setDeclaredType(String JavaDoc type) {
171         m_declaredType = type;
172     }
173     
174     /**
175      * Get field name.
176      *
177      * @return field name (or <code>null</code> if none)
178      */

179     public String JavaDoc getFieldName() {
180         return m_fieldName;
181     }
182     
183     /**
184      * Get field information. This method is only usable after a call to {@link
185      * #validate}.
186      *
187      * @return field information (or <code>null</code> if none)
188      */

189     public IClassItem getField() {
190         return m_fieldItem;
191     }
192     
193     /**
194      * Set field name.
195      *
196      * @param field field name (or <code>null</code> if none)
197      */

198     public void setFieldName(String JavaDoc field) {
199         m_fieldName = field;
200     }
201     
202     /**
203      * Get test method name.
204      *
205      * @return test method name (or <code>null</code> if none)
206      */

207     public String JavaDoc getTestName() {
208         return m_testName;
209     }
210     
211     /**
212      * Get test method information. This method is only usable after a call to
213      * {@link #validate}.
214      *
215      * @return test method information (or <code>null</code> if none)
216      */

217     public IClassItem getTest() {
218         return m_testItem;
219     }
220     
221     /**
222      * Set test method name.
223      *
224      * @param test test method name (or <code>null</code> if none)
225      */

226     public void setTestName(String JavaDoc test) {
227         m_testName = test;
228     }
229     
230     /**
231      * Get get method name.
232      *
233      * @return get method name (or <code>null</code> if none)
234      */

235     public String JavaDoc getGetName() {
236         return m_getName;
237     }
238     
239     /**
240      * Get get method information. This method is only usable after a call to
241      * {@link #validate}.
242      *
243      * @return get method information (or <code>null</code> if none)
244      */

245     public IClassItem getGet() {
246         return m_getItem;
247     }
248     
249     /**
250      * Get type for value loaded to stack. This method is only usable after a
251      * call to {@link #validate}.
252      *
253      * @return get value type (or <code>null</code> if none)
254      */

255     public IClass getGetType() {
256         return m_getType;
257     }
258     
259     /**
260      * Set get method name.
261      *
262      * @param get get method name (or <code>null</code> if none)
263      */

264     public void setGetName(String JavaDoc get) {
265         m_getName = get;
266     }
267     
268     /**
269      * Get set method name.
270      *
271      * @return set method name (or <code>null</code> if none)
272      */

273     public String JavaDoc getSetName() {
274         return m_setName;
275     }
276     
277     /**
278      * Get set method information. This method is only usable after a call to
279      * {@link #validate}.
280      *
281      * @return set method information (or <code>null</code> if none)
282      */

283     public IClassItem getSet() {
284         return m_setItem;
285     }
286     
287     /**
288      * Get type for value stored from stack. This method is only usable after a
289      * call to {@link #validate}.
290      *
291      * @return set value type (or <code>null</code> if none)
292      */

293     public IClass getSetType() {
294         return m_setType;
295     }
296     
297     /**
298      * Set set method name.
299      *
300      * @param set set method name (or <code>null</code> if none)
301      */

302     public void setSetName(String JavaDoc set) {
303         m_setName = set;
304     }
305     
306     /**
307      * Check if empty property definition. Empty property definitions occur
308      * because every <b>collection</b>, <b>structure</b>, and <b>value</b>
309      * element has associated property attributes but these may not actually
310      * reference a property (when using the containing object). This call is
311      * only meaningful after prevalidation.
312      *
313      * @return <code>true</code> if implicit property, <code>false</code> if not
314      */

315     public boolean isImplicit() {
316         return m_isImplicit;
317     }
318     
319     /* (non-Javadoc)
320      * @see org.jibx.binding.model.AttributeBase#prevalidate(org.jibx.binding.model.ValidationContext)
321      */

322     public void prevalidate(ValidationContext vctx) {
323         
324         // check usage value
325
if (m_usageName != null) {
326             m_usage = s_usageEnum.getValue(m_usageName);
327             if (m_usage < 0) {
328                 vctx.addError("Value \"" + m_usageName +
329                     "\" is not a valid choice for usage");
330             }
331         } else {
332             m_usage = vctx.getParentElement().getDefaultStyle();
333         }
334         
335         // handle basic lookups and checks
336
ContainerElementBase parent = vctx.getParentContainer();
337         IClass cobj = parent.getEffectiveType();
338         String JavaDoc dtype = null;
339         String JavaDoc gtype = null;
340         String JavaDoc stype = null;
341         boolean err = false;
342         m_isImplicit = true;
343         if (m_fieldName != null) {
344             
345             // field means this is real (not implicit)
346
m_isImplicit = false;
347             
348             // look up the field information
349
m_fieldItem = cobj.getField(m_fieldName);
350             if (m_fieldItem == null) {
351                 vctx.addFatal("Nonstatic field " + m_fieldName +
352                     " not found in class " + cobj.getName());
353                 err = true;
354             } else {
355                 dtype = gtype = stype = m_fieldItem.getTypeName();
356             }
357             
358         }
359         if (m_testName != null) {
360             
361             // look up the method information
362
m_testItem = cobj.getMethod(m_testName, "()Z");
363             if (m_testItem == null) {
364                 vctx.addError("Nonstatic test-method " + m_testName +
365                     " not found in class " + cobj.getName());
366             }
367             
368         }
369         if (m_getName != null) {
370             
371             // get-method means this is real (not implicit)
372
m_isImplicit = false;
373             
374             // look up the get method by name (no overload possible)
375
m_getItem = cobj.getMethod(m_getName, "()");
376             if (m_getItem == null) {
377                 vctx.addFatal("Nonstatic get-method " + m_getName +
378                     " not found in class " + cobj.getName());
379                 err = true;
380             } else {
381                 gtype = m_getItem.getTypeName();
382                 if (dtype == null) {
383                     dtype = gtype;
384                 }
385             }
386         }
387         if (m_setName != null) {
388             
389             // set-method means this is real (not implicit)
390
m_isImplicit = false;
391             
392             // need to handle overloads, so generate possible signatures
393
ArrayList JavaDoc sigs = new ArrayList JavaDoc();
394             if (m_getItem != null) {
395                 sigs.add("(" + ClassUtils.getSignature(gtype) + ")V");
396             }
397             if (m_declaredType != null) {
398                 sigs.add("(" + ClassUtils.getSignature(m_declaredType) + ")V");
399             }
400             if (m_fieldItem != null) {
401                 sigs.add("(" + m_fieldItem.getSignature() + ")V");
402             }
403             sigs.add("(Ljava/lang/Object;)V");
404             
405             // match any of the possible signatures
406
m_setItem = cobj.getMethod(m_setName,
407                 (String JavaDoc[])sigs.toArray(new String JavaDoc[0]));
408             if (m_setItem == null) {
409                 vctx.addFatal("Nonstatic set-method " + m_setName +
410                     " with argument of appropriate type not found in class " +
411                     cobj.getName());
412                 err = true;
413             } else {
414                 stype = m_setItem.getArgumentType(0);
415                 if (dtype == null) {
416                     dtype = stype;
417                 }
418             }
419         }
420         
421         // set the property type information
422
String JavaDoc tname = m_declaredType;
423         if (tname == null) {
424             tname = dtype;
425             if (tname == null) {
426                 tname = cobj.getName();
427             }
428         } else if (dtype == null) {
429             // TODO: make sure assigned type is compatible with actual type
430
dtype = gtype = stype = tname;
431         }
432         m_type = vctx.getClassInfo(tname);
433         if (m_type == null) {
434             vctx.addFatal("Unable to load class " + tname);
435         } else if (vctx.getContextObject() instanceof CollectionElement) {
436             
437             // forbid access specifications for child of collection
438
if (m_fieldName != null || m_testName != null ||
439                 m_getName != null || m_setName != null) {
440                 vctx.addWarning("Property access attributes (field, " +
441                     "get-method, set-method, test-method) ignored " +
442                     "for collection item");
443             }
444             
445         } else if (!err && !m_isImplicit) {
446             
447             // check that type information is consistent
448
boolean valid = true;
449             
450             // require access specifications for child of non-collection
451
if (vctx.isInBinding()) {
452                 if (stype == null) {
453                     vctx.addError("No way to set property value");
454                 } else {
455                     valid = ClassUtils.isAssignable(tname, stype, vctx);
456                 }
457             }
458             if (!vctx.isInBinding()) {
459                 if (gtype == null) {
460                     vctx.addError("No way to get property value");
461                 } else if (valid) {
462                     valid = ClassUtils.isAssignable(tname, gtype, vctx) ||
463                         ClassUtils.isAssignable(gtype, tname, vctx);
464                 }
465             }
466             if (!valid) {
467                 vctx.addError("Incompatible types used in property definition");
468             }
469         }
470         super.prevalidate(vctx);
471     }
472 }
Popular Tags