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 2000 (C) Intalio Inc. All Rights Reserved.
42 *
43 * $Id$
44 */
45
46 package org.exolab.castor.xml.dtd;
47
48 import java.util.HashSet;
49 import java.util.Hashtable;
50 import java.util.Iterator;
51 import java.util.Enumeration;
52
53 /**
54 * Implementation of DTD Element declaration specification.
55 * @author <a href="mailto:totok@intalio.com">Alexander Totok</a>
56 * @version $Revision$ $Date: 2006-04-25 15:08:23 -0600 (Tue, 25 Apr 2006) $
57 */
58 public class Element {
59
60 private static final short ANY = 0;
61 private static final short EMPTY = 1;
62 private static final short MIXED = 2;
63 private static final short ELEMENTS_ONLY = 3;
64
65 /**
66 * Name of the element.
67 */
68 private String name;
69
70 /**
71 * DTD document owning this element
72 */
73 private DTDdocument document;
74
75 /**
76 * Content type of the element. Value may be {@link #ANY ANY}, {@link #EMPTY EMPTY},
77 * {@link #MIXED MIXED}, {@link #ELEMENTS_ONLY ELEMENTS_ONLY} or
78 * -1, if unspecified.
79 */
80 private short contentType = -1;
81
82 /**
83 * Set of names of children of the element,
84 * if the element has <tt>MIXED</tt> content.
85 */
86 private HashSet mixedChildren = null;
87
88 /**
89 * Content Particle representing content of the element, if the element has
90 * <tt>ELEMENTS_ONLY</tt> content.
91 */
92 private ContentParticle content = null;
93
94 /**
95 * Attributes of the element.
96 */
97 private Hashtable attributes;
98
99 /**
100 * Constructor, setting the name of the element and owning DTD document.
101 * @param document must not be null.
102 */
103 public Element(DTDdocument document, String name) {
104
105 if (document == null) {
106 String err = "Element constructor: document must not be null.";
107 throw new IllegalArgumentException(err);
108 }
109
110 this.name = name;
111 this.document = document;
112 attributes = new Hashtable();
113 } //-- Element
114
115 /**
116 * Constructor, setting owning DTD document of the element.
117 * @param document must not be null.
118 */
119 public Element(DTDdocument document) {
120 this(document, null);
121 } //-- Element
122
123 /**
124 * Returns the name of the element.
125 */
126 public String getName() {
127 return name;
128 } //-- getName
129
130 /**
131 * Returns DTD document owning this element.
132 */
133 public DTDdocument getDocument() {
134 return document;
135 } //-- getDocument
136
137 /**
138 * Returns {@link java.util.Iterator iterator} of the set of mixed children,
139 * if of <tt>MIXED</tt> content, <tt>null</tt> otherwise.
140 */
141 public Iterator getMixedContentChildren() {
142 if (isMixedContent()) return mixedChildren.iterator();
143 return null;
144 } //-- getMixedContentChildren
145
146 /**
147 * Returns enumeration of the attributes of the element.
148 */
149 public Enumeration getAttributes() {
150 return attributes.elements();
151 } //-- getAttributes
152
153 /**
154 * Returns {@link org.exolab.castor.xml.dtd.ContentParticle Content Particle},
155 * representing the content of the element, if has <tt>ELEMENTS_ONLY</tt>
156 * content, <tt>null</tt> otherwise.
157 */
158 public ContentParticle getContent() {
159 if (isElemOnlyContent()) return content;
160 return null;
161 } //-- getContent
162
163 /**
164 * Sets the name of the element.
165 */
166 public void setName(String name) {
167 this.name = name;
168 } //-- setName
169
170 /**
171 * Sets the content type of the element to <tt>ANY</tt>.
172 */
173 public void setAnyContent() {
174 contentType = ANY;
175 } //-- setAnyContent
176
177 /**
178 * <b>True</b> if the element is of <tt>ANY</tt> content type,
179 * <b>false</b> otherwise.
180 */
181 public boolean isAnyContent() {
182 return contentType == ANY;
183 } //-- isAnyContent
184
185 /**
186 * Sets the content type of the element to <tt>EMPTY</tt>.
187 */
188 public void setEmptyContent() {
189 contentType = EMPTY;
190 } //-- setEmptyContent
191
192 /**
193 * <b>True</b> if the element is of <tt>EMPTY</tt> content type, <b>false</b> otherwise.
194 */
195 public boolean isEmptyContent() {
196 return contentType == EMPTY;
197 } //-- isEmptyContent
198
199 /**
200 * Sets the content type of the element to <tt>MIXED</tt>.
201 */
202 public void setMixedContent() {
203 contentType = MIXED;
204 mixedChildren = new HashSet();
205 } //-- setMixedContent
206
207 /**
208 * <b>True</b> if the element is of <tt>MIXED</tt> content type, <b>false</b> otherwise.
209 */
210 public boolean isMixedContent() {
211 return contentType == MIXED;
212 } //-- isMixedContent
213
214 /**
215 * Sets the content type of the element to <tt>ELEMENTS_ONLY</tt>.
216 * @param cp Content Particle representing content of the element.
217 */
218 public void setElemOnlyContent(ContentParticle cp) {
219 contentType = ELEMENTS_ONLY;
220 content = cp;
221 } //-- setChildrenContent
222
223 /**
224 * <b>True</b> if the element is of <tt>ELEMENTS_ONLY</tt> content type,
225 * <b>false</b> otherwise.
226 */
227 public boolean isElemOnlyContent() {
228 return contentType == ELEMENTS_ONLY;
229 } //-- isChildrenContent
230
231 /**
232 * Adds name of a <tt>child</tt> to the set of children's names.
233 * @throws DTDException if there already exists the child with the same name.
234 */
235 public synchronized void addMixedContentChild(String child) throws DTDException {
236 if (mixedChildren.contains(child)) {
237 String err = "Element \"" + name + "\" already contains child element ";
238 err += "\"" + child + "\".";
239 throw new DTDException(err);
240 }
241 mixedChildren.add(child);
242 } //-- addChild
243
244 /**
245 * Adds attribute to the element. If the element already has the attribute
246 * with the same name, does nothing.
247 */
248 public synchronized void addAttribute(Attribute attribute) {
249 String name = attribute.getName();
250 if (!attributes.containsKey(name)) attributes.put(name,attribute);
251 } //-- addAttribute
252
253 } //-- Element