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 }