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.dv.ValidatedInfo;
25import com.sun.org.apache.xerces.internal.impl.xs.identity.IdentityConstraint;
26import com.sun.org.apache.xerces.internal.impl.xs.util.XSNamedMapImpl;
27import com.sun.org.apache.xerces.internal.impl.xs.util.XSObjectListImpl;
28import com.sun.org.apache.xerces.internal.xni.QName;
29import com.sun.org.apache.xerces.internal.xs.ShortList;
30import com.sun.org.apache.xerces.internal.xs.XSAnnotation;
31import com.sun.org.apache.xerces.internal.xs.XSComplexTypeDefinition;
32import com.sun.org.apache.xerces.internal.xs.XSConstants;
33import com.sun.org.apache.xerces.internal.xs.XSElementDeclaration;
34import com.sun.org.apache.xerces.internal.xs.XSNamedMap;
35import com.sun.org.apache.xerces.internal.xs.XSNamespaceItem;
36import com.sun.org.apache.xerces.internal.xs.XSObjectList;
37import com.sun.org.apache.xerces.internal.xs.XSTypeDefinition;
38import com.sun.org.apache.xerces.internal.xs.XSValue;
39
40/**
41 * The XML representation for an element declaration
42 * schema component is an <element> element information item
43 *
44 * @xerces.internal
45 *
46 * @author Elena Litani, IBM
47 * @author Sandy Gao, IBM
48 */
49public class XSElementDecl implements XSElementDeclaration {
50
51    // scopes
52    public final static short     SCOPE_ABSENT        = 0;
53    public final static short     SCOPE_GLOBAL        = 1;
54    public final static short     SCOPE_LOCAL         = 2;
55
56    // name of the element
57    public String fName = null;
58    // target namespace of the element
59    public String fTargetNamespace = null;
60    // type of the element
61    public XSTypeDefinition fType = null;
62    public QName fUnresolvedTypeName = null;
63    // misc flag of the element: nillable/abstract/fixed
64    short fMiscFlags = 0;
65    public short fScope = XSConstants.SCOPE_ABSENT;
66    // enclosing complex type, when the scope is local
67    XSComplexTypeDecl fEnclosingCT = null;
68    // block set (disallowed substitutions) of the element
69    public short fBlock = XSConstants.DERIVATION_NONE;
70    // final set (substitution group exclusions) of the element
71    public short fFinal = XSConstants.DERIVATION_NONE;
72    // optional annotation
73    public XSObjectList fAnnotations = null;
74    // value constraint value
75    public ValidatedInfo fDefault = null;
76    // the substitution group affiliation of the element
77    public XSElementDecl fSubGroup = null;
78    // identity constraints
79    static final int INITIAL_SIZE = 2;
80    int fIDCPos = 0;
81    IdentityConstraint[] fIDConstraints = new IdentityConstraint[INITIAL_SIZE];
82    // The namespace schema information item corresponding to the target namespace
83    // of the element declaration, if it is globally declared; or null otherwise.
84    private XSNamespaceItem fNamespaceItem = null;
85
86    private static final short CONSTRAINT_MASK = 3;
87    private static final short NILLABLE        = 4;
88    private static final short ABSTRACT        = 8;
89
90    // methods to get/set misc flag
91    public void setConstraintType(short constraintType) {
92        // first clear the bits
93        fMiscFlags ^= (fMiscFlags & CONSTRAINT_MASK);
94        // then set the proper one
95        fMiscFlags |= (constraintType & CONSTRAINT_MASK);
96    }
97    public void setIsNillable() {
98        fMiscFlags |= NILLABLE;
99    }
100    public void setIsAbstract() {
101        fMiscFlags |= ABSTRACT;
102    }
103    public void setIsGlobal() {
104        fScope = SCOPE_GLOBAL;
105    }
106    public void setIsLocal(XSComplexTypeDecl enclosingCT) {
107        fScope = SCOPE_LOCAL;
108        fEnclosingCT = enclosingCT;
109    }
110
111    public void addIDConstraint(IdentityConstraint idc) {
112        if (fIDCPos == fIDConstraints.length) {
113            fIDConstraints = resize(fIDConstraints, fIDCPos*2);
114        }
115        fIDConstraints[fIDCPos++] = idc;
116    }
117
118    public IdentityConstraint[] getIDConstraints() {
119        if (fIDCPos == 0) {
120            return null;
121        }
122        if (fIDCPos < fIDConstraints.length) {
123            fIDConstraints = resize(fIDConstraints, fIDCPos);
124        }
125        return fIDConstraints;
126    }
127
128    static final IdentityConstraint[] resize(IdentityConstraint[] oldArray, int newSize) {
129        IdentityConstraint[] newArray = new IdentityConstraint[newSize];
130        System.arraycopy(oldArray, 0, newArray, 0, Math.min(oldArray.length, newSize));
131        return newArray;
132    }
133
134    /**
135     * get the string description of this element
136     */
137    private String fDescription = null;
138    public String toString() {
139        if (fDescription == null) {
140            if (fTargetNamespace != null) {
141                StringBuffer buffer = new StringBuffer(
142                    fTargetNamespace.length() +
143                    ((fName != null) ? fName.length() : 4) + 3);
144                buffer.append('"');
145                buffer.append(fTargetNamespace);
146                buffer.append('"');
147                buffer.append(':');
148                buffer.append(fName);
149                fDescription = buffer.toString();
150            }
151            else {
152                fDescription = fName;
153            }
154        }
155        return fDescription;
156    }
157
158    /**
159     * get the hash code
160     */
161    public int hashCode() {
162        int code = fName.hashCode();
163        if (fTargetNamespace != null)
164            code = (code<<16)+fTargetNamespace.hashCode();
165        return code;
166    }
167
168    /**
169     * whether two decls are the same
170     */
171    public boolean equals(Object o) {
172        return o == this;
173    }
174
175    /**
176      * Reset current element declaration
177      */
178    public void reset(){
179        fScope = XSConstants.SCOPE_ABSENT;
180        fName = null;
181        fTargetNamespace = null;
182        fType = null;
183        fUnresolvedTypeName = null;
184        fMiscFlags = 0;
185        fBlock = XSConstants.DERIVATION_NONE;
186        fFinal = XSConstants.DERIVATION_NONE;
187        fDefault = null;
188        fAnnotations = null;
189        fSubGroup = null;
190        // reset identity constraints
191        for (int i=0;i<fIDCPos;i++) {
192            fIDConstraints[i] = null;
193        }
194
195        fIDCPos = 0;
196    }
197
198    /**
199     * Get the type of the object, i.e ELEMENT_DECLARATION.
200     */
201    public short getType() {
202        return XSConstants.ELEMENT_DECLARATION;
203    }
204
205    /**
206     * The <code>name</code> of this <code>XSObject</code> depending on the
207     * <code>XSObject</code> type.
208     */
209    public String getName() {
210        return fName;
211    }
212
213    /**
214     * The namespace URI of this node, or <code>null</code> if it is
215     * unspecified.  defines how a namespace URI is attached to schema
216     * components.
217     */
218    public String getNamespace() {
219        return fTargetNamespace;
220    }
221
222    /**
223     * Either a simple type definition or a complex type definition.
224     */
225    public XSTypeDefinition getTypeDefinition() {
226        return fType;
227    }
228
229    /**
230     * Optional. Either global or a complex type definition (
231     * <code>ctDefinition</code>). This property is absent in the case of
232     * declarations within named model groups: their scope will be
233     * determined when they are used in the construction of complex type
234     * definitions.
235     */
236    public short getScope() {
237        return fScope;
238    }
239
240    /**
241     * Locally scoped declarations are available for use only within the
242     * complex type definition identified by the <code>scope</code>
243     * property.
244     */
245    public XSComplexTypeDefinition getEnclosingCTDefinition() {
246        return fEnclosingCT;
247    }
248
249    /**
250     * A value constraint: one of default, fixed.
251     */
252    public short getConstraintType() {
253        return (short)(fMiscFlags & CONSTRAINT_MASK);
254    }
255
256    /**
257     * A value constraint: The actual value (with respect to the {type
258     * definition})
259     */
260    public String getConstraintValue() {
261        // REVISIT: SCAPI: what's the proper representation
262        return getConstraintType() == XSConstants.VC_NONE ?
263               null :
264               fDefault.stringValue();
265    }
266
267    /**
268     * If {nillable} is true, then an element may also be valid if it carries
269     * the namespace qualified attribute with [local name] nil from
270     * namespace http://www.w3.org/2001/XMLSchema-instance and value true
271     * (see xsi:nil (2.6.2)) even if it has no text or element content
272     * despite a {content type} which would otherwise require content.
273     */
274    public boolean getNillable() {
275        return ((fMiscFlags & NILLABLE) != 0);
276    }
277
278    /**
279     * {identity-constraint definitions} A set of constraint definitions.
280     */
281    public XSNamedMap getIdentityConstraints() {
282        return new XSNamedMapImpl(fIDConstraints, fIDCPos);
283    }
284
285    /**
286     * {substitution group affiliation} Optional. A top-level element
287     * definition.
288     */
289    public XSElementDeclaration getSubstitutionGroupAffiliation() {
290        return fSubGroup;
291    }
292
293    /**
294     * Convenience method. Check if <code>exclusion</code> is a substitution
295     * group exclusion for this element declaration.
296     * @param exclusion Extension, restriction or none. Represents final
297     *   set for the element.
298     * @return True if <code>exclusion</code> is a part of the substitution
299     *   group exclusion subset.
300     */
301    public boolean isSubstitutionGroupExclusion(short exclusion) {
302        return (fFinal & exclusion) != 0;
303    }
304
305    /**
306     * Specifies if this declaration can be nominated as
307     * the {substitution group affiliation} of other
308     * element declarations having the same {type definition}
309     * or types derived therefrom.
310     *
311     * @return A bit flag representing {extension, restriction} or NONE.
312     */
313    public short getSubstitutionGroupExclusions() {
314        return fFinal;
315    }
316
317    /**
318     * Convenience method. Check if <code>disallowed</code> is a disallowed
319     * substitution for this element declaration.
320     * @param disallowed Substitution, extension, restriction or none.
321     *   Represents a block set for the element.
322     * @return True if <code>disallowed</code> is a part of the substitution
323     *   group exclusion subset.
324     */
325    public boolean isDisallowedSubstitution(short disallowed) {
326        return (fBlock & disallowed) != 0;
327    }
328
329    /**
330     * The supplied values for {disallowed substitutions}
331     *
332     * @return A bit flag representing {substitution, extension, restriction} or NONE.
333     */
334    public short getDisallowedSubstitutions() {
335        return fBlock;
336    }
337
338    /**
339     * {abstract} A boolean.
340     */
341    public boolean getAbstract() {
342        return ((fMiscFlags & ABSTRACT) != 0);
343    }
344
345    /**
346     * Optional. Annotation.
347     */
348    public XSAnnotation getAnnotation() {
349        return (fAnnotations != null) ? (XSAnnotation) fAnnotations.item(0) : null;
350    }
351
352    /**
353     * Optional. Annotations.
354     */
355    public XSObjectList getAnnotations() {
356        return (fAnnotations != null) ? fAnnotations : XSObjectListImpl.EMPTY_LIST;
357    }
358
359
360    /**
361     * @see org.apache.xerces.xs.XSObject#getNamespaceItem()
362     */
363    public XSNamespaceItem getNamespaceItem() {
364        return fNamespaceItem;
365    }
366
367    void setNamespaceItem(XSNamespaceItem namespaceItem) {
368        fNamespaceItem = namespaceItem;
369    }
370
371    public Object getActualVC() {
372        return getConstraintType() == XSConstants.VC_NONE ?
373               null :
374               fDefault.actualValue;
375    }
376
377    public short getActualVCType() {
378        return getConstraintType() == XSConstants.VC_NONE ?
379               XSConstants.UNAVAILABLE_DT :
380               fDefault.actualValueType;
381    }
382
383    public ShortList getItemValueTypes() {
384        return getConstraintType() == XSConstants.VC_NONE ?
385               null :
386               fDefault.itemValueTypes;
387    }
388
389    public XSValue getValueConstraintValue() {
390        return fDefault;
391    }
392
393} // class XSElementDecl
394