001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.xerces.impl.xs;
019:
020: import org.apache.xerces.xs.*;
021: import org.apache.xerces.impl.xs.util.XSObjectListImpl;
022:
023: /**
024: * Store schema model group declaration.
025: *
026: * @xerces.internal
027: *
028: * @author Sandy Gao, IBM
029: *
030: * @version $Id: XSModelGroupImpl.java 446734 2006-09-15 20:51:23Z mrglavas $
031: */
032: public class XSModelGroupImpl implements XSModelGroup {
033:
034: // types of model groups
035: // REVISIT: can't use same constants as those for particles, because
036: // there are place where the constants are used together. For example,
037: // to check whether the content is an element or a sequence.
038: public static final short MODELGROUP_CHOICE = 101;
039: public static final short MODELGROUP_SEQUENCE = 102;
040: public static final short MODELGROUP_ALL = 103;
041:
042: // compositor of the model group
043: public short fCompositor;
044:
045: // particles
046: public XSParticleDecl[] fParticles = null;
047: public int fParticleCount = 0;
048:
049: // this particle's optional annotations
050: public XSObjectList fAnnotations = null;
051:
052: // whether this model group contains nothing
053: public boolean isEmpty() {
054: for (int i = 0; i < fParticleCount; i++) {
055: if (!fParticles[i].isEmpty())
056: return false;
057: }
058: return true;
059: }
060:
061: /**
062: * 3.8.6 Effective Total Range (all and sequence) and
063: * Effective Total Range (choice)
064: * The following methods are used to return min/max range for a particle.
065: * They are not exactly the same as it's described in the spec, but all the
066: * values from the spec are retrievable by these methods.
067: */
068: public int minEffectiveTotalRange() {
069: if (fCompositor == MODELGROUP_CHOICE)
070: return minEffectiveTotalRangeChoice();
071: else
072: return minEffectiveTotalRangeAllSeq();
073: }
074:
075: // return the sum of all min values of the particles
076: private int minEffectiveTotalRangeAllSeq() {
077: int total = 0;
078: for (int i = 0; i < fParticleCount; i++)
079: total += fParticles[i].minEffectiveTotalRange();
080: return total;
081: }
082:
083: // return the min of all min values of the particles
084: private int minEffectiveTotalRangeChoice() {
085: int min = 0, one;
086: if (fParticleCount > 0)
087: min = fParticles[0].minEffectiveTotalRange();
088:
089: for (int i = 1; i < fParticleCount; i++) {
090: one = fParticles[i].minEffectiveTotalRange();
091: if (one < min)
092: min = one;
093: }
094:
095: return min;
096: }
097:
098: public int maxEffectiveTotalRange() {
099: if (fCompositor == MODELGROUP_CHOICE)
100: return maxEffectiveTotalRangeChoice();
101: else
102: return maxEffectiveTotalRangeAllSeq();
103: }
104:
105: // if one of the max value of the particles is unbounded, return unbounded;
106: // otherwise return the sum of all max values
107: private int maxEffectiveTotalRangeAllSeq() {
108: int total = 0, one;
109: for (int i = 0; i < fParticleCount; i++) {
110: one = fParticles[i].maxEffectiveTotalRange();
111: if (one == SchemaSymbols.OCCURRENCE_UNBOUNDED)
112: return SchemaSymbols.OCCURRENCE_UNBOUNDED;
113: total += one;
114: }
115: return total;
116: }
117:
118: // if one of the max value of the particles is unbounded, return unbounded;
119: // otherwise return the max of all max values
120: private int maxEffectiveTotalRangeChoice() {
121: int max = 0, one;
122: if (fParticleCount > 0) {
123: max = fParticles[0].maxEffectiveTotalRange();
124: if (max == SchemaSymbols.OCCURRENCE_UNBOUNDED)
125: return SchemaSymbols.OCCURRENCE_UNBOUNDED;
126: }
127:
128: for (int i = 1; i < fParticleCount; i++) {
129: one = fParticles[i].maxEffectiveTotalRange();
130: if (one == SchemaSymbols.OCCURRENCE_UNBOUNDED)
131: return SchemaSymbols.OCCURRENCE_UNBOUNDED;
132: if (one > max)
133: max = one;
134: }
135: return max;
136: }
137:
138: /**
139: * get the string description of this particle
140: */
141: private String fDescription = null;
142:
143: public String toString() {
144: // REVISIT: Commented code may help to eliminate redundant parentheses (test first before committing)
145: if (fDescription == null) {
146: StringBuffer buffer = new StringBuffer();
147: if (fCompositor == MODELGROUP_ALL)
148: buffer.append("all(");
149: else
150: //if (fMinOccurs != 1 || fMaxOccurs != 1)
151: buffer.append('(');
152: if (fParticleCount > 0)
153: buffer.append(fParticles[0].toString());
154: for (int i = 1; i < fParticleCount; i++) {
155: if (fCompositor == MODELGROUP_CHOICE)
156: buffer.append('|');
157: else
158: buffer.append(',');
159: buffer.append(fParticles[i].toString());
160: }
161: //if (fCompositor == MODELGROUP_ALL || fMinOccurs != 1 || fMaxOccurs != 1)
162: buffer.append(')');
163: fDescription = buffer.toString();
164: }
165: return fDescription;
166: }
167:
168: public void reset() {
169: fCompositor = MODELGROUP_SEQUENCE;
170: fParticles = null;
171: fParticleCount = 0;
172: fDescription = null;
173: fAnnotations = null;
174: }
175:
176: /**
177: * Get the type of the object, i.e ELEMENT_DECLARATION.
178: */
179: public short getType() {
180: return XSConstants.MODEL_GROUP;
181: }
182:
183: /**
184: * The <code>name</code> of this <code>XSObject</code> depending on the
185: * <code>XSObject</code> type.
186: */
187: public String getName() {
188: return null;
189: }
190:
191: /**
192: * The namespace URI of this node, or <code>null</code> if it is
193: * unspecified. defines how a namespace URI is attached to schema
194: * components.
195: */
196: public String getNamespace() {
197: return null;
198: }
199:
200: /**
201: * {compositor} One of all, choice or sequence. The valid constants values
202: * are: ALL, CHOICE, SEQUENCE.
203: */
204: public short getCompositor() {
205: if (fCompositor == MODELGROUP_CHOICE)
206: return XSModelGroup.COMPOSITOR_CHOICE;
207: else if (fCompositor == MODELGROUP_SEQUENCE)
208: return XSModelGroup.COMPOSITOR_SEQUENCE;
209: else
210: return XSModelGroup.COMPOSITOR_ALL;
211: }
212:
213: /**
214: * {particles} A list of particles
215: */
216: public XSObjectList getParticles() {
217: return new XSObjectListImpl(fParticles, fParticleCount);
218: }
219:
220: /**
221: * Optional. Annotation.
222: */
223: public XSAnnotation getAnnotation() {
224: return (fAnnotations != null) ? (XSAnnotation) fAnnotations
225: .item(0) : null;
226: }
227:
228: /**
229: * Optional. Annotations.
230: */
231: public XSObjectList getAnnotations() {
232: return (fAnnotations != null) ? fAnnotations
233: : XSObjectListImpl.EMPTY_LIST;
234: }
235:
236: /**
237: * @see org.apache.xerces.xs.XSObject#getNamespaceItem()
238: */
239: public XSNamespaceItem getNamespaceItem() {
240: return null;
241: }
242:
243: } // class XSModelGroupImpl
|