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-2004 (C) Intalio, Inc. All Rights Reserved.
42 *
43 * $Id$
44 */
45
46 package org.exolab.castor.xml.schema;
47
48 import java.util.Enumeration;
49 import java.util.Vector;
50
51 /**
52 * An implementation of an XML Schema content model group.
53 *
54 * @author <a href="mailto:kvisco@intalio.com">Keith Visco</a>
55 * @author <a href="mailto:blandin@intalio.com">Arnaud Blandin</a>
56 * @version $Revision$ $Date: 2006-04-14 04:14:43 -0600 (Fri, 14 Apr 2006) $
57 */
58 class ContentModelGroupImpl implements ContentModelGroup , java.io.Serializable {
59 /** SerialVersionUID */
60 private static final long serialVersionUID = -2477271185972337873L;
61
62 /**
63 * Collection holding all {@link Particle}s of this content model group.
64 */
65 private Vector<Particle> _contentModel = new Vector<Particle>();
66
67 private transient ScopableResolver _resolver = new ScopableResolver();
68
69 /**
70 * {@inheritDoc}
71 *
72 * @see org.exolab.castor.xml.schema.ContentModelGroup#addWildcard(org.exolab.castor.xml.schema.Wildcard)
73 */
74 public void addWildcard(final Wildcard wildcard) throws SchemaException {
75 if (wildcard.isAttributeWildcard()) {
76 throw new SchemaException("only <any> should be add in a group.");
77 }
78 _contentModel.addElement(wildcard);
79 }
80
81 /**
82 * {@inheritDoc}
83 *
84 * @see org.exolab.castor.xml.schema.ContentModelGroup#addElementDecl(org.exolab.castor.xml.schema.ElementDecl)
85 */
86 public void addElementDecl(final ElementDecl elementDecl)
87 throws SchemaException {
88
89 if (elementDecl == null) {
90 return;
91 }
92
93 String name = elementDecl.getName();
94
95 if (!elementDecl.isReference()) {
96 String key = "element:" + name;
97 //-- check for naming collisions
98 if (_resolver.resolve(key) != null) {
99 String err = "An element declaration with the given name, ";
100 err += name + ", already exists in this scope.";
101 throw new SchemaException(err);
102 }
103 _resolver.addResolvable(key, elementDecl);
104 }
105
106 //-- add to content model
107 _contentModel.addElement(elementDecl);
108
109 }
110
111 /**
112 * {@inheritDoc}
113 *
114 * @see org.exolab.castor.xml.schema.ContentModelGroup#removeElementDecl(org.exolab.castor.xml.schema.ElementDecl)
115 */
116 public boolean removeElementDecl(final ElementDecl elementDecl) {
117 if (elementDecl == null) {
118 return false;
119 }
120 int position = _contentModel.indexOf(elementDecl);
121 if (position >= 0) {
122 _contentModel.removeElementAt(position);
123 if (!elementDecl.isReference()) {
124 String key = "element:" + elementDecl.getName();
125 _resolver.removeResolvable(key);
126 }
127 return true;
128 }
129 return false;
130 }
131
132 /**
133 * {@inheritDoc}
134 *
135 * @see org.exolab.castor.xml.schema.ContentModelGroup#addGroup(org.exolab.castor.xml.schema.Group)
136 */
137 public void addGroup(final Group group) throws SchemaException {
138 if (group == null) {
139 return;
140 }
141
142 String name = group.getName();
143 if (name != null) {
144 String key = "group:" + name;
145 // -- check for naming collisions
146 if (_resolver.resolve(key) != null) {
147 String err = "A group definition with the given name, ";
148 err += name + ", already exists in this scope.";
149 throw new SchemaException(err);
150 }
151
152 _resolver.addResolvable(key, group);
153 }
154
155 // -- add to content model
156 _contentModel.addElement(group);
157 }
158
159 /**
160 * {@inheritDoc}
161 *
162 * @see org.exolab.castor.xml.schema.ContentModelGroup#removeGroup(org.exolab.castor.xml.schema.Group)
163 */
164 public boolean removeGroup(final Group group) {
165 if (group == null) {
166 return false;
167 }
168 int position = _contentModel.indexOf(group);
169 if (position >= 0) {
170 String name = group.getName();
171 if (name != null) {
172 String key = "group:" + name;
173 _resolver.removeResolvable(key);
174 }
175 _contentModel.removeElementAt(position);
176 return true;
177 }
178 return false;
179 }
180
181 /**
182 * {@inheritDoc}
183 *
184 * @see org.exolab.castor.xml.schema.ContentModelGroup#addGroup(org.exolab.castor.xml.schema.ModelGroup)
185 */
186 public void addGroup(final ModelGroup group) throws SchemaException {
187 if (group == null) {
188 return;
189 }
190
191 String name = group.getName();
192 if ((name != null) && (!group.isReference())) {
193 String key = "group:" + name;
194 // -- check for naming collisions
195 if (_resolver.resolve(key) != null) {
196 String err = "An element declaration with the given name, ";
197 err += name + ", already exists in this scope.";
198 throw new SchemaException(err);
199 }
200
201 _resolver.addResolvable(key, group);
202 }
203
204 // -- add to content model
205 _contentModel.addElement(group);
206 }
207
208 /**
209 * {@inheritDoc}
210 *
211 * @see org.exolab.castor.xml.schema.ContentModelGroup#removeGroup(org.exolab.castor.xml.schema.ModelGroup)
212 */
213 public boolean removeGroup(final ModelGroup group) {
214 if (group == null) {
215 return false;
216 }
217 int position = _contentModel.indexOf(group);
218 if (position >= 0) {
219 String name = group.getName();
220 if ((name != null) && (!group.isReference())) {
221 String key = "group:" + name;
222 _resolver.removeResolvable(key);
223 }
224 _contentModel.removeElementAt(position);
225 return true;
226 }
227 return false;
228 }
229
230 /**
231 * {@inheritDoc}
232 *
233 * @see org.exolab.castor.xml.schema.ContentModelGroup#removeWildcard(org.exolab.castor.xml.schema.Wildcard)
234 */
235 public boolean removeWildcard(final Wildcard wildcard) {
236 if (wildcard == null) {
237 return false;
238 }
239 int position = _contentModel.indexOf(wildcard);
240 if (position >= 0) {
241 _contentModel.removeElementAt(position);
242 return true;
243 }
244 return false;
245 }
246
247 /**
248 * {@inheritDoc}
249 *
250 * @see org.exolab.castor.xml.schema.ContentModelGroup#enumerate()
251 */
252 public Enumeration<Particle> enumerate() {
253 return _contentModel.elements();
254 }
255
256 /**
257 * {@inheritDoc}
258 *
259 * @see org.exolab.castor.xml.schema.ContentModelGroup#getElementDecl(java.lang.String)
260 */
261 public ElementDecl getElementDecl(final String name) {
262 if (name == null) {
263 return null;
264 }
265 ElementDecl result = null;
266 if (_resolver != null) {
267 String key = "element:" + name;
268 result = (ElementDecl) _resolver.resolve(key);
269 // resolver is always not null (initialized in the constructor)
270 // but it may not contain the element (in case of a complexType)
271 if (result != null) {
272 return result;
273 }
274 }
275 for (int i = 0; i < _contentModel.size(); i++) {
276 Particle particle = _contentModel.elementAt(i);
277 switch (particle.getStructureType()) {
278 case Structure.ELEMENT:
279 ElementDecl e = (ElementDecl) particle;
280 if (name.equals(e.getName())) {
281 result = e;
282 }
283 break;
284 case Structure.GROUP:
285 case Structure.MODELGROUP:
286 result = ((ContentModelGroup) particle).getElementDecl(name);
287 break;
288 default:
289 break;
290 }
291 if (result != null) {
292 break;
293 }
294 }
295 return result;
296 }
297
298 /**
299 * {@inheritDoc}
300 *
301 * @see org.exolab.castor.xml.schema.ContentModelGroup#getMaxOccurs()
302 */
303 public int getMaxOccurs() {
304 return 1;
305 }
306
307 /**
308 * {@inheritDoc}
309 *
310 * @see org.exolab.castor.xml.schema.ContentModelGroup#getMinOccurs()
311 */
312 public int getMinOccurs() {
313 return 1;
314 }
315
316 /**
317 * {@inheritDoc}
318 *
319 * @see org.exolab.castor.xml.schema.ContentModelGroup#getParticle(int)
320 */
321 public Particle getParticle(final int index) {
322 return _contentModel.elementAt(index);
323 }
324
325 /**
326 * {@inheritDoc}
327 *
328 * @see org.exolab.castor.xml.schema.ContentModelGroup#getParticleCount()
329 */
330 public int getParticleCount() {
331 return _contentModel.size();
332 }
333
334 }