KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > enhydra > zeus > binding > ContainerProperty


1 /*
2  * Enhydra Java Application Server Project
3  *
4  * The contents of this file are subject to the Enhydra Public License
5  * Version 1.1 (the "License"); you may not use this file except in
6  * compliance with the License. You may obtain a copy of the License on
7  * the Enhydra web site ( http://www.enhydra.org/ ).
8  *
9  * Software distributed under the License is distributed on an "AS IS"
10  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
11  * the License for the specific terms governing rights and limitations
12  * under the License.
13  *
14  * The Initial Developer of the Enhydra Application Server is Lutris
15  * Technologies, Inc. The Enhydra Application Server and portions created
16  * by Lutris Technologies, Inc. are Copyright Lutris Technologies, Inc.
17  * All Rights Reserved.
18  */

19 package org.enhydra.zeus.binding;
20
21 import java.util.Iterator JavaDoc;
22 import java.util.LinkedList JavaDoc;
23 import java.util.List JavaDoc;
24 import java.util.BitSet JavaDoc;
25 import java.util.Vector JavaDoc;
26
27 /**
28  * <p>
29  * <code>ContainerProperty</code> implements the
30  * <code>{@link org.enhydra.zeus.Binding}</code>,
31  * <code>{@link Property}</code>, and
32  * <code>{@link Container}</code> interfaces, and provides
33  * for a complex object that is itself a property.
34  * </p><p>
35  * A <code>ContainerProperty</code> will most commonly represent
36  * a Java <code>Object</code> that has properties of its own
37  * (like any other <code>Container</code), but that also is a
38  * property itself, of some other Java <code>Object</code>.
39  * </p>
40  *
41  * @author Brett McLaughlin
42  */

43 public class ContainerProperty extends BaseBinding
44                                implements Property, Container {
45                                    
46     /** Default modifier for properties */
47     private static BitSet JavaDoc DEFAULT_MODIFIER = new BitSet JavaDoc();
48     
49     static {
50         DEFAULT_MODIFIER.set(Property.ACCESS_PRIVATE);
51     }
52
53     /**
54      * Note that since Java doesn't allow multiple inheritance, this class
55      * can't simply extend <code>{@link BaseProperty}</code> and
56      * <code>{@link BaseContainer}</code>, which is really what it should
57      * do. Instead, all those methods must be duplicated here, which is really
58      * sort of crummy.
59      */

60
61     /** The access level modifier for this <code>Property</code> */
62     protected BitSet JavaDoc modifier;
63     
64     /**
65      * Whether this <code>Property</code> represents a
66      * <code>Collection</code>
67      */

68     protected boolean isCollection;
69     
70     /** The default value for this <code>Property</code> */
71     protected Object JavaDoc defaultValue;
72     
73     /**
74      * The <code>{@link Property}</code> objects this
75      * <code>Container</code> holds.
76      */

77     protected List JavaDoc properties;
78     
79     /**
80      * <p>
81      * This will create a new <code>ContainerProperty</code> with
82      * the specified information.
83      * </p>
84      *
85      * @param xmlName the XML local name associated with the property.
86      * @param xmlNamespaceURI the XML namespace URI associated with the
87      * property's XML name.
88      * @param xmlType the XML type associated with the property.
89      * @param xmlTypeNamespaceURI the XML namespace URI associated with
90      * the property's XML type.
91      * @param modifier the BitSet representing the property's modifier(s).
92      *
93      * @see <code>{@link Property#ACCESS_PRIVATE}</code>
94      * @see <code>{@link Property#ACCESS_PROTECTED}</code>
95      * @see <code>{@link Property#ACCESS_PUBLIC}</code>
96      */

97     public ContainerProperty(String JavaDoc xmlName,
98                              String JavaDoc xmlNamespaceURI,
99                              String JavaDoc xmlType,
100                              String JavaDoc xmlTypeNamespaceURI,
101                              BitSet JavaDoc modifier) {
102         super();
103         
104         // Error checking
105
if (xmlName == null) {
106             throw new IllegalArgumentException JavaDoc("An AtomicProperty cannot " +
107                 "have a null XML name.");
108         }
109         if (xmlNamespaceURI == null) {
110             throw new IllegalArgumentException JavaDoc("An AtomicProperty cannot " +
111                 "have a null XML namespace URI. To specify no namespace URI, " +
112                 "use the empty String (\"\")");
113         }
114         if (xmlType == null) {
115             throw new IllegalArgumentException JavaDoc("An AtomicProperty cannot " +
116                 "have a null XML type.");
117         }
118         if (xmlTypeNamespaceURI == null) {
119             throw new IllegalArgumentException JavaDoc("An AtomicProperty cannot " +
120                 "have a null XML type namespace URI. To specify no namespace " +
121                 "URI, use the empty String (\"\")");
122         }
123         if (modifier == null) {
124             throw new IllegalArgumentException JavaDoc("A Binding cannot have a " +
125                 "null set of modifiers.");
126         }
127         
128         this.xmlName = xmlName;
129         this.xmlNamespaceURI = xmlNamespaceURI;
130         this.xmlType = xmlType;
131         this.xmlTypeNamespaceURI = xmlTypeNamespaceURI;
132         this.defaultValue = null;
133         this.modifier = modifier;
134         this.isCollection = false;
135     }
136
137     /**
138      * <p>
139      * This will create a new <code>ContainerProperty</code> with
140      * the specified information, and set the access level to "private".
141      * </p>
142      *
143      * @param xmlName the XML local name associated with the property.
144      * @param xmlNamespaceURI the XML namespace URI associated with the
145      * property's XML name.
146      * @param xmlType the XML type associated with the property.
147      * @param xmlTypeNamespaceURI the XML namespace URI associated with the
148      * property's XML type.
149      *
150      * @see <code>{@link Property#ACCESS_PRIVATE}</code>
151      * @see <code>{@link Property#ACCESS_PROTECTED}</code>
152      * @see <code>{@link Property#ACCESS_PUBLIC}</code>
153      */

154     public ContainerProperty(String JavaDoc xmlName,
155                              String JavaDoc xmlNamespaceURI,
156                              String JavaDoc xmlType,
157                              String JavaDoc xmlTypeNamespaceURI) {
158         this(xmlName, xmlNamespaceURI, xmlType, xmlTypeNamespaceURI,
159              DEFAULT_MODIFIER);
160     }
161     
162     /**
163      * <p>
164      * This will create a new <code>ContainerProperty</code> with
165      * the specified information, and set the access level to "private",
166      * as well as setting both the XML name and XML type namespace URIs
167      * to "", the equivalent of no namespace.
168      * </p>
169      *
170      * @param xmlName the XML local name associated with the property.
171      * @param xmlType the XML type associated with the property.
172      *
173      * @see <code>{@link Property#ACCESS_PRIVATE}</code>
174      * @see <code>{@link Property#ACCESS_PROTECTED}</code>
175      * @see <code>{@link Property#ACCESS_PUBLIC}</code>
176      */

177     public ContainerProperty(String JavaDoc xmlName,
178                              String JavaDoc xmlType) {
179         this(xmlName, "", xmlType, "", DEFAULT_MODIFIER);
180     }
181
182     /**
183      * <p>
184      * This will set the modifiers for a property. The
185      * value submitted must be in the form of an <code>int</code>,
186      * which should correspond to one of the constants defined
187      * (<code>{@link #ACCESS_PRIVATE}</code>,
188      * <code>{@link #ACCESS_PROTECTED}</code>,
189      * <code>{@link #ACCESS_PUBLIC}</code>,
190      * <code>{@link #STORAGE_STATIC}</code>,
191      * <code>{@link #MUTABILITY_VOLATILE}</code>,
192      * or <code>{@link #MUTABILITY_FINAL}</code>. By default,
193      * all properties will be <code>private</code>
194      * (<code>ACCESS_PRIVATE</code>).
195      * </p>
196      *
197      * @param modifier <code>BitSet</code>representing modifiers.
198      * @see #ACCESS_PRIVATE
199      * @see #ACCESS_PROTECTED
200      * @see #ACCESS_PUBLIC
201      * @see #STORAGE_STATIC
202      * @see #MUTABILITY_VOLATILE
203      * @see #MUTABILITY_FINAL
204      */

205     public void setModifier(BitSet JavaDoc modifier) {
206         if (modifier == null) {
207             throw new IllegalArgumentException JavaDoc("A Property cannot have a " +
208                 "null set of modifiers.");
209         }
210         this.modifier = modifier;
211     }
212     
213     /**
214      * <p>
215      * This will return the access level modifier for a property. The
216      * value returned will be in the form of an <code>int</code>,
217      * which will correspond to one of the constants defined
218      * (<code>{@link #ACCESS_PRIVATE}</code>,
219      * <code>{@link #ACCESS_PROTECTED}</code>,
220      * <code>{@link #ACCESS_PUBLIC}</code>,
221      * <code>{@link #STORAGE_STATIC}</code>,
222      * or <code>{@link #MUTABILITY_FINAL}</code>.
223      * </p>
224      *
225      * @return <code>BitSet</code> - modifiers.
226      * @see #ACCESS_PRIVATE
227      * @see #ACCESS_PROTECTED
228      * @see #ACCESS_PUBLIC
229      * @see #STORAGE_STATIC
230      * @see #MUTABILITY_VOLATILE
231      * @see #MUTABILITY_FINAL
232      */

233     public BitSet JavaDoc getModifier() {
234         return modifier;
235     }
236     
237     /**
238      * <p>
239      * This will return the Java <code>String</code> representation
240      * of this <code>Property</code>'s modifiers. For
241      * example, <code>{@link #ACCESS_PRIVATE}</code> would be
242      * converted to "private".
243      * </p>
244      *
245      * @return <code>String</code> - Java representation
246      * @see #ACCESS_PRIVATE
247      * @see #ACCESS_PROTECTED
248      * @see #ACCESS_PUBLIC
249      * @see #STORAGE_STATIC
250      * @see #MUTABILITY_VOLATILE
251      * @see #MUTABILITY_FINAL
252      */

253     public String JavaDoc getModifierString() {
254         StringBuffer JavaDoc modifierString = new StringBuffer JavaDoc();
255         if (modifier.get(ACCESS_PRIVATE)) {
256             modifierString.append("private");
257         } else if (modifier.get(ACCESS_PROTECTED)) {
258             modifierString.append("protected");
259         } else if (modifier.get(ACCESS_PUBLIC)) {
260             modifierString.append("public");
261         } else {
262             throw new UnsupportedOperationException JavaDoc
263                 ("Modifier must set access modifiers.");
264         }
265         
266         if (modifier.get(STORAGE_STATIC)) {
267             modifierString.append(" static");
268         }
269         if (modifier.get(MUTABILITY_VOLATILE)) {
270             modifierString.append(" volatile");
271         } else if (modifier.get(MUTABILITY_FINAL)) {
272             modifierString.append(" final");
273         }
274         
275         return modifierString.toString();
276     }
277     
278     /**
279      * <p>
280      * This will set whether or not this <code>Property</code>
281      * is a <code>Collection</code> (in other words, the property
282      * represents a collection of values). By default, properties
283      * are all singular values.
284      * </p>
285      *
286      * @param isCollection <code>true</code> is multiple values can be stored,
287      * or else <code>false</code>.
288      */

289     public void setIsCollection(boolean isCollection) {
290         this.isCollection = isCollection;
291     }
292     
293     /**
294      * <p>
295      * This will indicate whether this <code>Property</code> represents
296      * a <code>Collection</code> of values (resulting in a <code>true</code>
297      * result from this method), or a singular value (resulting in a
298      * <code>false</code> result).
299      * </p>
300      *
301      * @return <code>boolean</code> - whether or not this <code>Property</code>
302      * represents a <code>Collection<code>.
303      */

304     public boolean isCollection() {
305         return isCollection;
306     }
307     
308     /**
309      * <p>
310      * This indicates whether or not this <code>Property</code> has a
311      * a default value set.
312      * </p>
313      *
314      * @return <code>boolean</code> - whether there is a default value set.
315      */

316     public boolean hasDefaultValue() {
317         return (defaultValue != null);
318     }
319     
320     /**
321      * <p>
322      * This will set the default value of the property. Since no typing
323      * is available at this point, a simple Java <code>Object</code>
324      * is allowed as the type supplied. As a result, any errors in
325      * mismatches between object type and allowed paramater type will
326      * occur at runtime, when class generation takes place. Supplying
327      * a value here essentially results in:
328      * <code><pre>
329      * public class Foo {
330      *
331      * private String myString = "some default value";
332      *
333      * public String getMyString() {
334      * return myString;
335      * }
336      *
337      * public void setMyString(String myString) {
338      * this.myString = myString;
339      * }
340      *
341      * // Other methods and properties
342      * }
343      * </pre></code>
344      * </p><p>
345      * Also, note that data binding users who supply their own class
346      * implementations will <b>LOSE THIS DEFAULT VALUE</b>, as the interface
347      * alone cannot specify a default value. So use this carefully!
348      * </p>
349      *
350      * @param defaultValue <code>Object</code> to be used as default value.
351      */

352     public void setDefaultValue(Object JavaDoc defaultValue) {
353         this.defaultValue = defaultValue;
354     }
355     
356     /**
357      * <p>
358      * This will retrieve the default value associated with this property,
359      * or <code>null</code> if there is not one. For more information on
360      * default property values, see
361      * <code>{@link #setDefaultValue(Object)}</code>.
362      * </p>
363      *
364      * @return <code>Object</code> - default value of the property.
365      */

366     public Object JavaDoc getDefaultValue() {
367         return defaultValue;
368     }
369     
370     /**
371      * <p>
372      * This will indicate if this <code>Property</code> has a set of
373      * allowed values (an enumeration) specified for it. For
374      * <code>ContainerProperty</code> implementations, this will
375      * <i>always</i> be false.
376      * </p>
377      *
378      * @return <code>boolean</code> - whether an enumeration is specified.
379      */

380     public boolean hasEnumeration() {
381         return false;
382     }
383
384     /**
385      * <p>
386      * This will set a list (enumeration) of allowed values for this
387      * <code>Property</code>. This complies with the <code>Property</code>
388      * interface, but does nothing for containers.
389      * </p>
390      *
391      * @param enumeration the <code>Vector</code> of allowed values.
392      */

393     public void setEnumeration(Vector JavaDoc enumeration) {
394         return;
395     }
396    
397     /**
398      * <p>
399      * This returns the <code>Vector</code> of allowed values for this
400      * <code>Property</code>, or <code>null</code> if there is none.
401      * For a <code>ContainerProperty</code>, this will <i>always</i>
402      * return <code>null</code>.
403      * </p>
404      *
405      * @return <code>Vector</code> - the allowed values.
406      */

407     public Vector JavaDoc getEnumeration() {
408         return null;
409     }
410           
411     /**
412      * <p>
413      * This will add a <code>{@link Property}</code> to
414      * the member variables of this <code>Container</code>.
415      * </p><p>
416      * It is important to note that this is simply an instance
417      * variable being added to (in most cases) a custom
418      * Java class definition. That variable/property
419      * doesn't have a value (although it might have a
420      * default value) until marshalling and unmarshalling
421      * occurs.
422      * </p>
423      *
424      * @param property <code>Property</code> to add.
425      */

426     public void addProperty(Property property) {
427         if (property == null) {
428             throw new IllegalArgumentException JavaDoc("A Container cannot have " +
429                 "null properties as children.");
430         }
431         
432         if (properties == null) {
433             properties = new LinkedList JavaDoc();
434         }
435         
436         properties.add(property);
437     }
438     
439     /**
440      * <p>
441      * This will remove a <code>{@link Property}</code>
442      * from this <code>Container</code>, given the
443      * property's name. If a successful removal occurs,
444      * the boolean value <code>true</code> is retruned.
445      * If no <code>Property<code> is found with the supplied
446      * Java name, the boolean value <code>false</code> is returned.
447      * </p>
448      *
449      * @param javaName <code>String</code> name of
450      * <code>Property</code> to remove.
451      * @return <code>boolean</code> - indicates whether
452      * the specified named <code>Property</code>
453      * was found and removed.
454      */

455     public boolean removeProperty(String JavaDoc javaName) {
456         if (properties == null) {
457             return false;
458         }
459         
460         for (Iterator JavaDoc i = properties.iterator(); i.hasNext(); ) {
461             Property property = (Property)i.next();
462             if (property.getJavaName().equals(javaName)) {
463                 i.remove();
464                 return true;
465             }
466         }
467         
468         return false;
469     }
470     
471     /**
472      * <p>
473      * This does a wholesale replacement of this binding's current
474      * properties, removing all current ones and replacing with the
475      * supplied <code>List</code> of new properties.
476      * </p>
477      *
478      * @param properties <code>List</code> of properties to use for this
479      * container.
480      */

481     public void setProperties(List JavaDoc properties) {
482         if (properties == null) {
483             throw new IllegalArgumentException JavaDoc("A Container cannot have a " +
484                 "null property set.");
485         }
486         
487         this.properties = properties;
488     }
489     
490     /**
491      * <p>
492      * This will return a list of all the
493      * <code>{@link Property}</code> objects that
494      * this <code>Container</code> has. If there are
495      * none, this will return an empty <code>List</code>.
496      * </p>
497      *
498      * @return <code>List</code> - properties for this
499      * <code>Container</code>.
500      */

501     public List JavaDoc getProperties() {
502         if (properties == null) {
503             return new LinkedList JavaDoc();
504         }
505         
506         return properties;
507     }
508     
509     /**
510      * <p>
511      * This will clear all the properties for this <code>Container</code>.
512      * </p>
513      */

514     public void clearProperties() {
515         if (properties != null) {
516             properties.clear();
517         }
518     }
519 }
520
Popular Tags