1/*
2 * reserved comment block
3 * DO NOT REMOVE OR ALTER!
4 */
5/*
6 * Licensed to the Apache Software Foundation (ASF) under one or more
7 * contributor license agreements.  See the NOTICE file distributed with
8 * this work for additional information regarding copyright ownership.
9 * The ASF licenses this file to You under the Apache License, Version 2.0
10 * (the "License"); you may not use this file except in compliance with
11 * the License.  You may obtain a copy of the License at
12 *
13 *      http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 */
21
22package com.sun.org.apache.xerces.internal.impl.xs;
23
24import com.sun.org.apache.xerces.internal.impl.xs.util.XSObjectListImpl;
25import com.sun.org.apache.xerces.internal.xs.XSConstants;
26import com.sun.org.apache.xerces.internal.xs.XSNamespaceItem;
27import com.sun.org.apache.xerces.internal.xs.XSObjectList;
28import com.sun.org.apache.xerces.internal.xs.XSParticle;
29import com.sun.org.apache.xerces.internal.xs.XSTerm;
30
31/**
32 * Store schema particle declaration.
33 *
34 * @xerces.internal
35 *
36 * @author Sandy Gao, IBM
37 *
38 */
39public class XSParticleDecl implements XSParticle {
40
41    // types of particles
42    public static final short PARTICLE_EMPTY        = 0;
43    public static final short PARTICLE_ELEMENT      = 1;
44    public static final short PARTICLE_WILDCARD     = 2;
45    public static final short PARTICLE_MODELGROUP   = 3;
46    public static final short PARTICLE_ZERO_OR_MORE = 4;
47    public static final short PARTICLE_ZERO_OR_ONE  = 5;
48    public static final short PARTICLE_ONE_OR_MORE  = 6;
49
50    // type of the particle
51    public short fType = PARTICLE_EMPTY;
52
53    // term of the particle
54    // for PARTICLE_ELEMENT : the element decl
55    // for PARTICLE_WILDCARD: the wildcard decl
56    // for PARTICLE_MODELGROUP: the model group
57    public XSTerm fValue = null;
58
59    // minimum occurrence of this particle
60    public int fMinOccurs = 1;
61    // maximum occurrence of this particle
62    public int fMaxOccurs = 1;
63    // optional annotation
64    public XSObjectList fAnnotations = null;
65
66    // clone this decl
67    public XSParticleDecl makeClone() {
68        XSParticleDecl particle = new XSParticleDecl();
69        particle.fType = fType;
70        particle.fMinOccurs = fMinOccurs;
71        particle.fMaxOccurs = fMaxOccurs;
72        particle.fDescription = fDescription;
73        particle.fValue = fValue;
74        particle.fAnnotations = fAnnotations;
75        return particle;
76    }
77
78    /**
79     * 3.9.6 Schema Component Constraint: Particle Emptiable
80     * whether this particle is emptible
81     */
82    public boolean emptiable() {
83        return minEffectiveTotalRange() == 0;
84    }
85
86    // whether this particle contains nothing
87    public boolean isEmpty() {
88        if (fType == PARTICLE_EMPTY)
89             return true;
90        if (fType == PARTICLE_ELEMENT || fType == PARTICLE_WILDCARD)
91            return false;
92
93        return ((XSModelGroupImpl)fValue).isEmpty();
94    }
95
96    /**
97     * 3.8.6 Effective Total Range (all and sequence) and
98     *       Effective Total Range (choice)
99     * The following methods are used to return min/max range for a particle.
100     * They are not exactly the same as it's described in the spec, but all the
101     * values from the spec are retrievable by these methods.
102     */
103    public int minEffectiveTotalRange() {
104        if (fType == XSParticleDecl.PARTICLE_EMPTY) {
105            return 0;
106        }
107        if (fType == PARTICLE_MODELGROUP) {
108            return ((XSModelGroupImpl)fValue).minEffectiveTotalRange() * fMinOccurs;
109        }
110        return fMinOccurs;
111    }
112
113    public int maxEffectiveTotalRange() {
114        if (fType == XSParticleDecl.PARTICLE_EMPTY) {
115            return 0;
116        }
117        if (fType == PARTICLE_MODELGROUP) {
118            int max = ((XSModelGroupImpl)fValue).maxEffectiveTotalRange();
119            if (max == SchemaSymbols.OCCURRENCE_UNBOUNDED)
120                return SchemaSymbols.OCCURRENCE_UNBOUNDED;
121            if (max != 0 && fMaxOccurs == SchemaSymbols.OCCURRENCE_UNBOUNDED)
122                return SchemaSymbols.OCCURRENCE_UNBOUNDED;
123            return max * fMaxOccurs;
124        }
125        return fMaxOccurs;
126    }
127
128    /**
129     * get the string description of this particle
130     */
131    private String fDescription = null;
132    public String toString() {
133        if (fDescription == null) {
134            StringBuffer buffer = new StringBuffer();
135            appendParticle(buffer);
136            if (!(fMinOccurs == 0 && fMaxOccurs == 0 ||
137                  fMinOccurs == 1 && fMaxOccurs == 1)) {
138                buffer.append('{').append(fMinOccurs);
139                if (fMaxOccurs == SchemaSymbols.OCCURRENCE_UNBOUNDED)
140                    buffer.append("-UNBOUNDED");
141                else if (fMinOccurs != fMaxOccurs)
142                    buffer.append('-').append(fMaxOccurs);
143                buffer.append('}');
144            }
145            fDescription = buffer.toString();
146        }
147        return fDescription;
148    }
149
150    /**
151     * append the string description of this particle to the string buffer
152     * this is for error message.
153     */
154    void appendParticle(StringBuffer buffer) {
155        switch (fType) {
156        case PARTICLE_EMPTY:
157            buffer.append("EMPTY");
158            break;
159        case PARTICLE_ELEMENT:
160            buffer.append(fValue.toString());
161            break;
162        case PARTICLE_WILDCARD:
163            buffer.append('(');
164            buffer.append(fValue.toString());
165            buffer.append(')');
166            break;
167        case PARTICLE_MODELGROUP:
168            buffer.append(fValue.toString());
169            break;
170        }
171    }
172
173    public void reset(){
174        fType = PARTICLE_EMPTY;
175        fValue = null;
176        fMinOccurs = 1;
177        fMaxOccurs = 1;
178        fDescription = null;
179        fAnnotations = null;
180    }
181
182    /**
183     * Get the type of the object, i.e ELEMENT_DECLARATION.
184     */
185    public short getType() {
186        return XSConstants.PARTICLE;
187    }
188
189    /**
190     * The <code>name</code> of this <code>XSObject</code> depending on the
191     * <code>XSObject</code> type.
192     */
193    public String getName() {
194        return null;
195    }
196
197    /**
198     * The namespace URI of this node, or <code>null</code> if it is
199     * unspecified.  defines how a namespace URI is attached to schema
200     * components.
201     */
202    public String getNamespace() {
203        return null;
204    }
205
206    /**
207     * {min occurs} determines the minimum number of terms that can occur.
208     */
209    public int getMinOccurs() {
210        return fMinOccurs;
211    }
212
213    /**
214     * {max occurs} whether the maxOccurs value is unbounded.
215     */
216    public boolean getMaxOccursUnbounded() {
217        return fMaxOccurs == SchemaSymbols.OCCURRENCE_UNBOUNDED;
218    }
219
220    /**
221     * {max occurs} determines the maximum number of terms that can occur.
222     */
223    public int getMaxOccurs() {
224        return fMaxOccurs;
225    }
226
227    /**
228     * {term} One of a model group, a wildcard, or an element declaration.
229     */
230    public XSTerm getTerm() {
231        return fValue;
232    }
233
234        /**
235         * @see org.apache.xerces.xs.XSObject#getNamespaceItem()
236         */
237        public XSNamespaceItem getNamespaceItem() {
238                return null;
239        }
240
241    /**
242     * Optional. Annotations.
243     */
244    public XSObjectList getAnnotations() {
245        return (fAnnotations != null) ? fAnnotations : XSObjectListImpl.EMPTY_LIST;
246    }
247
248} // class XSParticleDecl
249