001: /**
002: * Redistribution and use of this software and associated documentation
003: * ("Software"), with or without modification, are permitted provided
004: * that the following conditions are met:
005: *
006: * 1. Redistributions of source code must retain copyright
007: * statements and notices. Redistributions must also contain a
008: * copy of this document.
009: *
010: * 2. Redistributions in binary form must reproduce the
011: * above copyright notice, this list of conditions and the
012: * following disclaimer in the documentation and/or other
013: * materials provided with the distribution.
014: *
015: * 3. The name "Exolab" must not be used to endorse or promote
016: * products derived from this Software without prior written
017: * permission of Intalio, Inc. For written permission,
018: * please contact info@exolab.org.
019: *
020: * 4. Products derived from this Software may not be called "Exolab"
021: * nor may "Exolab" appear in their names without prior written
022: * permission of Intalio, Inc. Exolab is a registered
023: * trademark of Intalio, Inc.
024: *
025: * 5. Due credit should be given to the Exolab Project
026: * (http://www.exolab.org/).
027: *
028: * THIS SOFTWARE IS PROVIDED BY INTALIO, INC. AND CONTRIBUTORS
029: * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
030: * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
031: * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
032: * INTALIO, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
033: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
034: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
035: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
036: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
037: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
038: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
039: * OF THE POSSIBILITY OF SUCH DAMAGE.
040: *
041: * Copyright 1999 - 2004 (C) Intalio, Inc. All Rights Reserved.
042: *
043: * $Id: ModelGroup.java 6230 2006-09-19 07:56:07Z wguttmn $
044: */package org.exolab.castor.xml.schema;
045:
046: import org.exolab.castor.xml.*;
047:
048: import java.util.Vector;
049: import java.util.Enumeration;
050:
051: /**
052: * An XML Schema ModelGroup : <xsd:group>
053: *
054: * @author <a href="mailto:kvisco@intalio.com">Keith Visco</a>
055: * @version $Revision: 6230 $ $Date: 2006-04-25 15:08:23 -0600 (Tue, 25 Apr 2006) $
056: **/
057: public class ModelGroup extends Group {
058: /** SerialVersionUID */
059: private static final long serialVersionUID = -2057934322265672413L;
060:
061: /**
062: * the name of the ModelGroup referenced
063: */
064: private String _groupRef = null;
065:
066: /**
067: * An ordered list of all ModelGroup definitions
068: **/
069: private Vector _modelDefs;
070:
071: /**
072: * An attribute that indicates if this Group is
073: * a redefinition
074: */
075: private boolean _redefinition = false;
076:
077: /**
078: * the schema that contains this model group
079: */
080: private Schema _schema = null;
081:
082: /**
083: * Creates a new ModelGroup, with no name
084: **/
085: public ModelGroup() {
086: this (null);
087: } //-- ModelGroup
088:
089: /**
090: * Creates a new ModelGroup definition
091: * @param schema the XML Schema to which this ModelGroup
092: * belongs
093: */
094: public ModelGroup(Schema schema) {
095: this (null, schema);
096: }
097:
098: /**
099: * Creates a new ModelGroup with the given name
100: * @param name of the ModelGroup
101: **/
102: public ModelGroup(String name, Schema schema) {
103: super (name);
104: _schema = schema;
105: _modelDefs = new Vector();
106: } //-- ModelGroup
107:
108: /**
109: * Adds the given ModelGroup to this ModelGroup
110: * @param modelGroup the ModelGroup to add to this ModelGroup
111: **/
112: public void addModelGroup(ModelGroup modelGroup) {
113: if (!_modelDefs.contains(modelGroup)) {
114: _modelDefs.addElement(modelGroup);
115: }
116: } //-- addModelGroup
117:
118: /**
119: * Returns an enumeration of all the Particles of this
120: * ContentModelGroup
121: *
122: * @return an enumeration of the Particles contained
123: * within this ContentModelGroup
124: **/
125: public Enumeration enumerate() {
126: return this .getContentModelGroup().enumerate();
127: } //-- enumerate
128:
129: /**
130: * Returns an ordered Enumeration of all the ContentModelType
131: * definitions (element, group, modelGroupRef)+
132: **/
133: public Enumeration getDeclarations() {
134: return _modelDefs.elements();
135: } //-- getDeclarations
136:
137: /**
138: * Returns the ContentModelGroup for this group
139: * Only used for a <group> element
140: * @return the ContentModelGroup for this group
141: */
142: public ContentModelGroup getContentModelGroup() {
143: if (_groupRef != null)
144: return getReference().getContentModelGroup();
145: return super .getContentModelGroup();
146: }
147:
148: /**
149: * Returns the name of this ModelGroup.
150: * @return the name of this ModelGroup.
151: **/
152: public String getName() {
153: return getName(false);
154: } //-- getName
155:
156: /**
157: * Returns the name of this Model Group definition
158: *
159: * @param ignoreRef If True the name of the referenced
160: * model group (if specified) is returned
161: * @return the name of this element declaration
162: **/
163: public String getName(boolean ignoreRef) {
164:
165: if (ignoreRef == false && _groupRef != null) {
166: String localName = _groupRef;
167: //-- check for namespace prefix
168: int idx = localName.indexOf(':');
169: if (idx > 0) {
170: localName = localName.substring(idx + 1);
171: }
172: return localName;
173: }
174: return super .getName();
175: } //-- getName
176:
177: /**
178: * Returns true if this model group definition simply references another
179: * model group Definition
180: * @return true if this model group definition is a reference
181: */
182: public boolean isReference() {
183: return (_groupRef != null);
184: } //-- isReference
185:
186: /**
187: * Sets this Group has redefined.
188: */
189: public void setRedefined() {
190: _redefinition = true;
191: }
192:
193: /**
194: * Returns true if this group is a redefinition.
195: *
196: * @return true if this group is a redefinition.
197: */
198: public boolean isRedefined() {
199: return _redefinition;
200: }
201:
202: /**
203: * Sets the reference for this ModelGroup definition
204: * @param reference the name of the ModelGroup that this
205: * definition references
206: **/
207: public void setReference(String reference) {
208: this ._groupRef = reference;
209: } //-- setReference
210:
211: //-------------------------------/
212: //- Implementation of Structure -/
213: //-------------------------------/
214:
215: /**
216: * Returns the type of this Schema Structure
217: * @return the type of this Schema Structure
218: **/
219: public short getStructureType() {
220: return Structure.MODELGROUP;
221: } //-- getStructureType
222:
223: /**
224: * Returns the Id used to Refer to this Object
225: * @return the Id used to Refer to this Object
226: * @see Referable
227: **/
228: public String getReferenceId() {
229: if (this .getName() != null)
230: return "group:" + this .getName();
231: return null;
232: } //-- getReferenceId
233:
234: /**
235: * Returns the reference if any
236: * @return the reference if any
237: */
238: public ModelGroup getReference() {
239: ModelGroup result = null;
240: if (_groupRef != null) {
241: result = _schema.getModelGroup(_groupRef);
242:
243: //--check for redefinition
244: if (_schema.getMasterSchema() != null) {
245: ModelGroup temp = _schema.getMasterSchema()
246: .getModelGroup(_groupRef);
247: if (temp != null)
248: result = temp;
249: }
250:
251: if (result == null) {
252: String err = "Unable to find group referenced :\" ";
253: err += getName();
254: err += "\"";
255: throw new IllegalStateException(err);
256: }
257: }
258: return result;
259: } //-- getReference
260:
261: /**
262: * Returns true if this ModelGroup is referencing another one
263: * @return true if this ModelGroup is referencing another one
264: */
265: public boolean hasReference() {
266: return (_groupRef != null) ? (_groupRef.length() != 0) : false;
267: }
268:
269: /**
270: * Checks the validity of this Schema defintion.
271: * @exception ValidationException when this Schema definition
272: * is invalid.
273: **/
274: public void validate() throws ValidationException {
275: //-- check name
276: if (getParent() != null
277: && getParent().getStructureType() != Structure.SCHEMA) {
278: if (getName(true) != null) {
279: String err = "Only top-level model group definition (<group>) can be named.";
280: err += getName()
281: + "is not a valid model group definition.";
282: throw new ValidationException(err);
283: }
284: }
285:
286: if (getContentModelGroup() == null) {
287: String err = "<group> should contains :\" ";
288: err += " 'all' or 'sequence' or 'choice'";
289: err += "\"";
290: throw new ValidationException(err);
291: }
292:
293: //-- Check for circular references
294: //-- Validation related to section 3.8.6 : Constraints on Model Group Schema Components
295: //-- Schema Component Constraint: Model Group Correct
296: //-- from the W3C XML Schema Recommendation
297: for (int i = 0; i < getParticleCount(); i++) {
298: Structure temp = getParticle(i);
299: switch (temp.getStructureType()) {
300: case Structure.MODELGROUP:
301: ModelGroup tempGroup = (ModelGroup) temp;
302: String name = null;
303: if (tempGroup.getReference() != null)
304: name = tempGroup.getReference().getName();
305:
306: if (name != null && name.equals(this .getName())) {
307: if (isRedefined()) {
308: if (getMaxOccurs() != 1 || getMinOccurs() != 1) {
309: String err = "in the redefined <group> named:"
310: + this .getName();
311: err += "\nThe particle information (minOccurs, maxOccurs) of a circular group must be set to 1.\n";
312: throw new ValidationException(err);
313: }
314:
315: } else {
316: String err = "in <group> named:"
317: + this .getName();
318: err += "\nCircular groups are disallowed.\n";
319: err += "That is, within the {particles} of a group there must not be at any depth a particle whose {term} is the group itself.\n";
320: throw new ValidationException(err);
321: }
322: }
323: //check cross-reference
324: int j = 0;
325: tempGroup = tempGroup.getReference();
326: while (j < tempGroup.getParticleCount()) {
327: if (tempGroup.getParticle(j).getStructureType() == Structure.MODELGROUP) {
328: ModelGroup referencedGroup = ((ModelGroup) tempGroup
329: .getParticle(j)).getReference();
330: if ((referencedGroup != null)
331: && (referencedGroup.equals(this ))) {
332: if (isRedefined()) {
333: if (getMaxOccurs() != 1
334: || getMinOccurs() != 1) {
335: String err = "in the redefined <group> named:"
336: + this .getName();
337: err += "\nThe particle information (minOccurs, maxOccurs) of a circular group must be set to 1.\n";
338: throw new ValidationException(err);
339: }
340: } else {
341: String err = "Cross reference between <group>:"
342: + this .getName()
343: + " and <group>:"
344: + tempGroup.getName();
345: err += "\nCircular groups are disallowed.\n";
346: err += "That is, within the {particles} of a group there must not be at any depth a particle whose {term} is the group itself.\n";
347: throw new ValidationException(err);
348: }
349: }
350:
351: }
352: j++;
353:
354: }
355: break;
356: default:
357: break;
358:
359: }
360: }
361: } //-- validate
362:
363: /**
364: * Returns the schema that contains this modelGroup definition
365: */
366: public Schema getSchema() {
367: return _schema;
368: }
369:
370: /**
371: * Sets the Schema that contains this group.
372: *
373: * @param schema the Schema that contains this group.
374: */
375: public void setSchema(Schema schema) {
376: _schema = schema;
377: }
378:
379: } //-- Group
|