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