View Javadoc
1   /*
2    * Redistribution and use of this software and associated documentation
3    * ("Software"), with or without modification, are permitted provided
4    * that the following conditions are met:
5    *
6    * 1. Redistributions of source code must retain copyright
7    *    statements and notices.  Redistributions must also contain a
8    *    copy of this document.
9    *
10   * 2. Redistributions in binary form must reproduce the
11   *    above copyright notice, this list of conditions and the
12   *    following disclaimer in the documentation and/or other
13   *    materials provided with the distribution.
14   *
15   * 3. The name "Exolab" must not be used to endorse or promote
16   *    products derived from this Software without prior written
17   *    permission of Intalio, Inc.  For written permission,
18   *    please contact info@exolab.org.
19   *
20   * 4. Products derived from this Software may not be called "Exolab"
21   *    nor may "Exolab" appear in their names without prior written
22   *    permission of Intalio, Inc. Exolab is a registered
23   *    trademark of Intalio, Inc.
24   *
25   * 5. Due credit should be given to the Exolab Project
26   *    (http://www.exolab.org/).
27   *
28   * THIS SOFTWARE IS PROVIDED BY INTALIO, INC. AND CONTRIBUTORS
29   * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
30   * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
31   * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
32   * INTALIO, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
33   * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
35   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
39   * OF THE POSSIBILITY OF SUCH DAMAGE.
40   *
41   * Copyright 1999 (C) Intalio, Inc. All Rights Reserved.
42   *
43   * This file was originally developed by Keith Visco during the course
44   * of employment at Intalio Inc.
45   * All portions of this file developed by Keith Visco after Jan 19 2005
46   * are Copyright (C) 2005 Keith Visco. All Rights Reserverd.
47   *
48   * $Id$
49   */
50  package org.exolab.castor.builder.info;
51  
52  import java.util.Collection;
53  import java.util.HashMap;
54  import java.util.HashSet;
55  import java.util.Map;
56  import java.util.Set;
57  import java.util.Vector;
58  
59  import org.castor.core.nature.PropertyHolder;
60  import org.exolab.castor.builder.info.nature.XMLInfoNature;
61  import org.exolab.javasource.JClass;
62  
63  /**
64   * This class holds the necessary information so that the source generator can
65   * properly create the necessary classes for the object model.
66   *
67   * @author <a href="mailto:keith AT kvisco DOT com">Keith Visco</a>
68   * @version $Revision$ $Date: 2006-04-13 07:37:49 -0600 (Thu, 13 Apr 2006) $
69   */
70  public final class ClassInfo implements XMLInfo, PropertyHolder {
71      
72      /** The base class. */
73      private ClassInfo _baseClass = null;
74      /**  A reference to the JClass that this ClassInfo describes. */
75      private JClass _class = null;
76      /** true if this ClassInfo represents an abstract class. */
77      private boolean _abstract    = false;
78      
79      /** Vector of FieldInfo's for all attributes that are members of this Class. */
80      private Vector<FieldInfo> _atts = new Vector<FieldInfo>();
81      /** Vector of FieldInfo's for all elements that are members of this Class. */
82      private Vector<FieldInfo> _elements = new Vector<FieldInfo>();
83      /** if this ClassInfo represents a TextField, this is this TextField's FieldInfo. */
84      private FieldInfo _textField = null;
85      
86      /**
87       * Map holding the properties set and read by Natures.
88       */
89      private Map<String, Object> _properties = new HashMap<String, Object>();
90      
91      /**
92       * Map holding the available natures.
93       */
94      private Set<String> _natures = new HashSet<String>();
95  
96      /**
97       * Creates a new ClassInfo. Adds the {@link XMLInfoNature} for legacy compliance.
98       * @param jClass the JClass which this ClassInfo describes
99       */
100     public ClassInfo(final JClass jClass) {
101         this.addNature(XMLInfoNature.class.getName());
102         XMLInfoNature xmlNature = new XMLInfoNature(this);
103         xmlNature.setNodeType(NodeType.ELEMENT);
104         if (jClass == null) {
105             String err = "JClass passed to constructor of ClassInfo must not be null.";
106             throw new IllegalArgumentException(err);
107         }
108         this._class = jClass;
109 
110         // set default GroupInfo instance
111         xmlNature.setGroupInfo(new GroupInfo());
112     }
113 
114     /**
115      * Adds the given FieldInfo to this ClassInfo.
116      *
117      * @param fieldInfo the FieldInfo to add
118      */
119     public void addFieldInfo(final FieldInfo fieldInfo) {
120         if (fieldInfo == null) {
121             return;
122         }
123 
124         fieldInfo.setDeclaringClassInfo(this);
125 
126         switch(new XMLInfoNature(fieldInfo).getNodeType()) {
127             case ATTRIBUTE:
128                 if (!_atts.contains(fieldInfo)) {
129                     _atts.addElement(fieldInfo);
130                 }
131                 break;
132             case TEXT:
133                 _textField = fieldInfo;
134                 break;
135             default:
136                 if (!_elements.contains(fieldInfo)) {
137                     _elements.addElement(fieldInfo);
138                 }
139                 break;
140         }
141     }
142 
143     /**
144      * Adds the given set of FieldInfos to this ClassInfo.
145      *
146      * @param fields an Array of FieldInfo objects
147      */
148     public void addFieldInfo(final FieldInfo[] fields) {
149         for (int i = 0; i < fields.length; i++) {
150             addFieldInfo(fields[i]);
151         }
152     }
153 
154     /**
155      * @return true if Classes created with this ClassInfo allow content
156      */
157     public boolean allowContent() {
158         return _textField != null;
159     }
160 
161     /**
162      * Returns true if the given FieldInfo is contained within this ClassInfo.
163      *
164      * @param fieldInfo
165      *            the FieldInfo to check
166      * @return true if the given FieldInfo is contained within this ClassInfo
167      */
168     public boolean contains(final FieldInfo fieldInfo) {
169         if (fieldInfo == null) {
170             return false;
171         }
172 
173         switch (new XMLInfoNature(fieldInfo).getNodeType()) {
174             case ATTRIBUTE:
175                 if (_atts != null) {
176                     return _atts.contains(fieldInfo);
177                 }
178                 break;
179             case TEXT:
180                 return (fieldInfo == _textField);
181             default:
182                 if (_elements != null) {
183                     return _elements.contains(fieldInfo);
184                 }
185                 break;
186         }
187 
188         //if (sourceInfo != null)
189         //    return sourceInfo.contains(fieldInfo);
190 
191         return false;
192     }
193 
194     /**
195      * Returns an array of XML attribute associated fields.
196      * @return an array of XML attribute associated fields.
197      */
198     public FieldInfo[] getAttributeFields() {
199         FieldInfo[] fields = null;
200         if (_atts != null) {
201             fields = new FieldInfo[_atts.size()];
202             _atts.copyInto(fields);
203         } else {
204             fields = new FieldInfo[0];
205         }
206         return fields;
207     } //-- getAttributeFields
208 
209     /**
210      * Returns a fieldInfo that corresponds to an attribute with the given node name.
211      * A ClassInfo cannot have 2 attributes with the same xml name.
212      *
213      * @param nodeName the NodeName of the field to get.
214      * @return a fieldInfo that corresponds to an attribute with the given node name.
215      */
216     public FieldInfo getAttributeField(final String nodeName) {
217         if (_atts == null) {
218             return null;
219         }
220 
221         for (int i = 0; i < _atts.size(); i++) {
222             FieldInfo temp = _atts.get(i);
223             if (new XMLInfoNature(temp).getNodeName().equals(nodeName)) {
224                 return temp;
225             }
226         }
227 
228         return null;
229     }
230 
231     /**
232      * Returns the base class of this classInfo if any. A classInfo can indeed
233      * extend another classInfo to reflect the extension mechanism used in the
234      * XML Schema.
235      *
236      * @return the base class of this classInfo if any.
237      */
238     public ClassInfo getBaseClass() {
239         return _baseClass;
240     }
241 
242     /**
243      * Returns an array of XML element associated fields.
244      *
245      * @return an array of XML element associated fields.
246      */
247     public FieldInfo[] getElementFields() {
248         FieldInfo[] members = null;
249         if (_elements != null) {
250             members = new FieldInfo[_elements.size()];
251             _elements.copyInto(members);
252         } else {
253             members = new FieldInfo[0];
254         }
255         return members;
256     } //-- getElementFields
257 
258     /**
259      * Returns a fieldInfo that corresponds to an element with the given node name.
260      * A ClassInfo cannot have 2 elements with the same xml name.
261      *
262      * @param nodeName the NodeName of the field to get.
263      * @return a fieldInfo that corresponds to an element with the given node name.
264      */
265     public FieldInfo getElementField(final String nodeName) {
266         if (_elements != null) {
267             for (int i = 0; i < _elements.size(); i++) {
268                 FieldInfo temp = _elements.get(i);
269                 String elementNodeName = new XMLInfoNature(temp).getNodeName();
270                 if (elementNodeName != null && elementNodeName.equals(nodeName)) {
271                     return temp;
272                 }
273             }
274         }
275         return null;
276     }
277 
278     /**
279      * Returns the number of FieldInfo definitions for this ClassInfo.
280      *
281      * @return the number of FieldInfo definitions for this ClassInfo.
282      */
283     public int getFieldCount() {
284         int count = 0;
285         if (_atts != null) {
286             count += _atts.size();
287         }
288         if (_elements != null) {
289             count += _elements.size();
290         }
291         if (_textField != null) {
292             ++count;
293         }
294         return count;
295     } //-- getFieldCount
296 
297     /**
298      * Returns the JClass described by this ClassInfo.
299      *
300      * @return the JClass which is described by this ClassInfo
301      */
302     public JClass getJClass() {
303         return _class;
304     } //-- getJClass
305 
306     /**
307      * Returns the FieldInfo for the XML text associated field.
308      *
309      * @return the FieldInfo for the text content associated field, this may be
310      *         null.
311      */
312     public FieldInfo getTextField() {
313         return _textField;
314     } //-- getTextField
315 
316     /**
317      * Returns true if the JClass represented by this ClassInfo is abstract.
318      *
319      * @return true if the JClass represented by this ClassInfo is abstract
320      */
321     public boolean isAbstract() {
322         return _abstract;
323     }
324 
325     /**
326      * Sets the class of this ClassInfo to be abstract of
327      *
328      * <code>abstractClass</code> is true, false otherwise.
329      *
330      * @param abstractClass true if the class represented by this ClassInfo is
331      *        abstract
332      */
333     public void setAbstract(final boolean abstractClass) {
334         _abstract = abstractClass;
335     }
336 
337     /**
338      * Sets the base class of this classInfo. A classInfo can indeed extend
339      * another classInfo to reflect the extension mechanism used in the XML
340      * Schema
341      *
342      * @param base the base class of this classInfo.
343      */
344     public void setBaseClass(final ClassInfo base) {
345         _baseClass = base;
346     }
347 
348     /**
349      * @see org.exolab.castor.builder.info.nature.PropertyHolder#
350      *      getProperty(java.lang.String)
351      * @param name
352      *            of the property
353      * @return value of the property
354      */
355     public Object getProperty(final String name) {
356         return _properties.get(name);
357     }
358 
359     /**
360      * @see org.exolab.castor.builder.info.nature.PropertyHolder#
361      *      setProperty(java.lang.String, java.lang.Object)
362      * @param name
363      *            of the property
364      * @param value
365      *            of the property
366      */
367     public void setProperty(final String name, final Object value) {
368         _properties.put(name, value);
369     }
370 
371     /**
372      * @see org.exolab.castor.builder.info.nature.NatureExtendable#
373      *      addNature(java.lang.String)
374      * @param nature
375      *            ID of the Nature
376      */
377     public void addNature(final String nature) {
378         _natures.add(nature);
379     }
380 
381     /**
382      * @see org.exolab.castor.builder.info.nature.NatureExtendable#
383      *      hasNature(java.lang.String)
384      * @param nature
385      *            ID of the Nature
386      * @return true if the Nature ID was added.
387      */
388     public boolean hasNature(final String nature) {
389         return _natures.contains(nature);
390     }
391 
392     /**
393      * Returns all attribute {@link FieldInfo}s as a collection.
394      * @return attribute fields.
395      */
396     public Collection<FieldInfo> getAttributeFieldsAsCollection() {
397         return this._atts;
398     }
399 
400     /**
401      * Returns all element {@link FieldInfo}s as a collection.
402      * @return element fields.
403      */
404     public Collection<FieldInfo> getElementFieldsAsCollection() {
405         return this._elements;
406     }
407 
408 }