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.traversers;
23
24import com.sun.org.apache.xerces.internal.impl.dv.InvalidDatatypeValueException;
25import com.sun.org.apache.xerces.internal.impl.dv.ValidatedInfo;
26import com.sun.org.apache.xerces.internal.impl.dv.XSSimpleType;
27import com.sun.org.apache.xerces.internal.impl.xs.SchemaGrammar;
28import com.sun.org.apache.xerces.internal.impl.xs.SchemaSymbols;
29import com.sun.org.apache.xerces.internal.impl.xs.XSAnnotationImpl;
30import com.sun.org.apache.xerces.internal.impl.xs.XSAttributeDecl;
31import com.sun.org.apache.xerces.internal.impl.xs.XSAttributeUseImpl;
32import com.sun.org.apache.xerces.internal.impl.xs.XSComplexTypeDecl;
33import com.sun.org.apache.xerces.internal.impl.xs.util.XInt;
34import com.sun.org.apache.xerces.internal.impl.xs.util.XSObjectListImpl;
35import com.sun.org.apache.xerces.internal.util.DOMUtil;
36import com.sun.org.apache.xerces.internal.util.XMLSymbols;
37import com.sun.org.apache.xerces.internal.xni.QName;
38import com.sun.org.apache.xerces.internal.xs.XSConstants;
39import com.sun.org.apache.xerces.internal.xs.XSObjectList;
40import com.sun.org.apache.xerces.internal.xs.XSTypeDefinition;
41import org.w3c.dom.Element;
42
43/**
44 * The attribute declaration schema component traverser.
45 *
46 * <attribute
47 *   default = string
48 *   fixed = string
49 *   form = (qualified | unqualified)
50 *   id = ID
51 *   name = NCName
52 *   ref = QName
53 *   type = QName
54 *   use = (optional | prohibited | required) : optional
55 *   {any attributes with non-schema namespace . . .}>
56 *   Content: (annotation?, (simpleType?))
57 * </attribute>
58 *
59 * @xerces.internal
60 *
61 * @author Sandy Gao, IBM
62 * @author Neeraj Bajaj, Sun Microsystems, inc.
63 */
64class XSDAttributeTraverser extends XSDAbstractTraverser {
65
66    public XSDAttributeTraverser (XSDHandler handler,
67            XSAttributeChecker gAttrCheck) {
68        super(handler, gAttrCheck);
69    }
70
71    protected XSAttributeUseImpl traverseLocal(Element attrDecl,
72            XSDocumentInfo schemaDoc,
73            SchemaGrammar grammar,
74            XSComplexTypeDecl enclosingCT) {
75
76        // General Attribute Checking
77        Object[] attrValues = fAttrChecker.checkAttributes(attrDecl, false, schemaDoc);
78
79        String defaultAtt = (String) attrValues[XSAttributeChecker.ATTIDX_DEFAULT];
80        String fixedAtt   = (String) attrValues[XSAttributeChecker.ATTIDX_FIXED];
81        String nameAtt    = (String) attrValues[XSAttributeChecker.ATTIDX_NAME];
82        QName  refAtt     = (QName)  attrValues[XSAttributeChecker.ATTIDX_REF];
83        XInt   useAtt     = (XInt)   attrValues[XSAttributeChecker.ATTIDX_USE];
84
85        // get 'attribute declaration'
86        XSAttributeDecl attribute = null;
87        XSAnnotationImpl annotation = null;
88        if (attrDecl.getAttributeNode(SchemaSymbols.ATT_REF) != null) {
89            if (refAtt != null) {
90                attribute = (XSAttributeDecl)fSchemaHandler.getGlobalDecl(schemaDoc, XSDHandler.ATTRIBUTE_TYPE, refAtt, attrDecl);
91
92                Element child = DOMUtil.getFirstChildElement(attrDecl);
93                if (child != null && DOMUtil.getLocalName(child).equals(SchemaSymbols.ELT_ANNOTATION)) {
94                    annotation = traverseAnnotationDecl(child, attrValues, false, schemaDoc);
95                    child = DOMUtil.getNextSiblingElement(child);
96                }
97                else {
98                    String text = DOMUtil.getSyntheticAnnotation(attrDecl);
99                    if (text != null) {
100                        annotation = traverseSyntheticAnnotation(attrDecl, text, attrValues, false, schemaDoc);
101                    }
102                }
103
104                if (child != null) {
105                    reportSchemaError("src-attribute.3.2", new Object[]{refAtt.rawname}, child);
106                }
107                // for error reporting
108                nameAtt = refAtt.localpart;
109            } else {
110                attribute = null;
111            }
112        } else {
113            attribute = traverseNamedAttr(attrDecl, attrValues, schemaDoc, grammar, false, enclosingCT);
114        }
115
116        // get 'value constraint'
117        short consType = XSConstants.VC_NONE;
118        if (defaultAtt != null) {
119            consType = XSConstants.VC_DEFAULT;
120        } else if (fixedAtt != null) {
121            consType = XSConstants.VC_FIXED;
122            defaultAtt = fixedAtt;
123            fixedAtt = null;
124        }
125
126        XSAttributeUseImpl attrUse = null;
127        if (attribute != null) {
128            if (fSchemaHandler.fDeclPool !=null) {
129                attrUse = fSchemaHandler.fDeclPool.getAttributeUse();
130            } else {
131                attrUse = new XSAttributeUseImpl();
132            }
133            attrUse.fAttrDecl = attribute;
134            attrUse.fUse = useAtt.shortValue();
135            attrUse.fConstraintType = consType;
136            if (defaultAtt != null) {
137                attrUse.fDefault = new ValidatedInfo();
138                attrUse.fDefault.normalizedValue = defaultAtt;
139            }
140            // Get the annotation associated witht the local attr decl
141            if (attrDecl.getAttributeNode(SchemaSymbols.ATT_REF) == null) {
142                attrUse.fAnnotations = attribute.getAnnotations();
143            } else {
144                XSObjectList annotations;
145                if (annotation != null) {
146                    annotations = new XSObjectListImpl();
147                    ((XSObjectListImpl) annotations).addXSObject(annotation);
148                } else {
149                    annotations = XSObjectListImpl.EMPTY_LIST;
150                }
151                attrUse.fAnnotations = annotations;
152            }
153        }
154
155        //src-attribute
156
157        // 1 default and fixed must not both be present.
158        if (defaultAtt != null && fixedAtt != null) {
159            reportSchemaError("src-attribute.1", new Object[]{nameAtt}, attrDecl);
160        }
161
162        // 2 If default and use are both present, use must have the actual value optional.
163        if (consType == XSConstants.VC_DEFAULT &&
164                useAtt != null && useAtt.intValue() != SchemaSymbols.USE_OPTIONAL) {
165            reportSchemaError("src-attribute.2", new Object[]{nameAtt}, attrDecl);
166            // Recover by honouring the default value
167            attrUse.fUse = SchemaSymbols.USE_OPTIONAL;
168        }
169
170        // a-props-correct
171
172        if (defaultAtt != null && attrUse != null) {
173            // 2 if there is a {value constraint}, the canonical lexical representation of its value must be valid with respect to the {type definition} as defined in String Valid (3.14.4).
174            fValidationState.setNamespaceSupport(schemaDoc.fNamespaceSupport);
175            try {
176                checkDefaultValid(attrUse);
177            }
178            catch (InvalidDatatypeValueException ide) {
179                reportSchemaError (ide.getKey(), ide.getArgs(), attrDecl);
180                reportSchemaError ("a-props-correct.2", new Object[]{nameAtt, defaultAtt}, attrDecl);
181                // Recover by removing the default value
182                attrUse.fDefault = null;
183                attrUse.fConstraintType = XSConstants.VC_NONE;
184            }
185
186            // 3 If the {type definition} is or is derived from ID then there must not be a {value constraint}.
187            if (((XSSimpleType)attribute.getTypeDefinition()).isIDType() ) {
188                reportSchemaError ("a-props-correct.3", new Object[]{nameAtt}, attrDecl);
189                // Recover by removing the default value
190                attrUse.fDefault = null;
191                attrUse.fConstraintType = XSConstants.VC_NONE;
192            }
193
194            // check 3.5.6 constraint
195            // Attribute Use Correct
196            // 2 If the {attribute declaration} has a fixed {value constraint}, then if the attribute use itself has a {value constraint}, it must also be fixed and its value must match that of the {attribute declaration}'s {value constraint}.
197            if (attrUse.fAttrDecl.getConstraintType() == XSConstants.VC_FIXED &&
198                    attrUse.fConstraintType != XSConstants.VC_NONE) {
199                if (attrUse.fConstraintType != XSConstants.VC_FIXED ||
200                        !attrUse.fAttrDecl.getValInfo().actualValue.equals(attrUse.fDefault.actualValue)) {
201                    reportSchemaError ("au-props-correct.2", new Object[]{nameAtt, attrUse.fAttrDecl.getValInfo().stringValue()}, attrDecl);
202                    // Recover by using the decl's {value constraint}
203                    attrUse.fDefault = attrUse.fAttrDecl.getValInfo();
204                    attrUse.fConstraintType = XSConstants.VC_FIXED;
205                }
206            }
207        }
208
209        fAttrChecker.returnAttrArray(attrValues, schemaDoc);
210        return attrUse;
211    }
212
213    protected XSAttributeDecl traverseGlobal(Element attrDecl,
214            XSDocumentInfo schemaDoc,
215            SchemaGrammar grammar) {
216
217        // General Attribute Checking
218        Object[] attrValues = fAttrChecker.checkAttributes(attrDecl, true, schemaDoc);
219        XSAttributeDecl attribute = traverseNamedAttr(attrDecl, attrValues, schemaDoc, grammar, true, null);
220        fAttrChecker.returnAttrArray(attrValues, schemaDoc);
221        return attribute;
222
223    }
224
225    /**
226     * Traverse a globally declared attribute.
227     *
228     * @param  attrDecl
229     * @param  attrValues
230     * @param  schemaDoc
231     * @param  grammar
232     * @param  isGlobal
233     * @return the attribute declaration index
234     */
235    XSAttributeDecl traverseNamedAttr(Element attrDecl,
236            Object[] attrValues,
237            XSDocumentInfo schemaDoc,
238            SchemaGrammar grammar,
239            boolean isGlobal,
240            XSComplexTypeDecl enclosingCT) {
241
242        String  defaultAtt = (String) attrValues[XSAttributeChecker.ATTIDX_DEFAULT];
243        String  fixedAtt   = (String) attrValues[XSAttributeChecker.ATTIDX_FIXED];
244        XInt    formAtt    = (XInt)   attrValues[XSAttributeChecker.ATTIDX_FORM];
245        String  nameAtt    = (String) attrValues[XSAttributeChecker.ATTIDX_NAME];
246        QName   typeAtt    = (QName)  attrValues[XSAttributeChecker.ATTIDX_TYPE];
247
248        // Step 1: get declaration information
249        XSAttributeDecl attribute = null;
250        if (fSchemaHandler.fDeclPool !=null) {
251            attribute = fSchemaHandler.fDeclPool.getAttributeDecl();
252        } else {
253            attribute = new XSAttributeDecl();
254        }
255
256        // get 'name'
257        if (nameAtt != null)
258            nameAtt = fSymbolTable.addSymbol(nameAtt);
259
260        // get 'target namespace'
261        String tnsAtt = null;
262        XSComplexTypeDecl enclCT = null;
263        short scope = XSAttributeDecl.SCOPE_ABSENT;
264        if (isGlobal) {
265            tnsAtt = schemaDoc.fTargetNamespace;
266            scope = XSAttributeDecl.SCOPE_GLOBAL;
267        }
268        else {
269            if (enclosingCT != null) {
270                enclCT = enclosingCT;
271                scope = XSAttributeDecl.SCOPE_LOCAL;
272            }
273            if (formAtt != null) {
274                if (formAtt.intValue() == SchemaSymbols.FORM_QUALIFIED)
275                    tnsAtt = schemaDoc.fTargetNamespace;
276            } else if (schemaDoc.fAreLocalAttributesQualified) {
277                tnsAtt = schemaDoc.fTargetNamespace;
278            }
279        }
280        // get 'value constraint'
281        // for local named attribute, value constraint is absent
282        ValidatedInfo attDefault = null;
283        short constraintType = XSConstants.VC_NONE;
284        if (isGlobal) {
285            if (fixedAtt != null) {
286                attDefault = new ValidatedInfo();
287                attDefault.normalizedValue = fixedAtt;
288                constraintType = XSConstants.VC_FIXED;
289            } else if (defaultAtt != null) {
290                attDefault = new ValidatedInfo();
291                attDefault.normalizedValue = defaultAtt;
292                constraintType = XSConstants.VC_DEFAULT;
293            }
294        }
295
296        // get 'annotation'
297        Element child = DOMUtil.getFirstChildElement(attrDecl);
298        XSAnnotationImpl annotation = null;
299        if (child != null && DOMUtil.getLocalName(child).equals(SchemaSymbols.ELT_ANNOTATION)) {
300            annotation = traverseAnnotationDecl(child, attrValues, false, schemaDoc);
301            child = DOMUtil.getNextSiblingElement(child);
302        }
303        else {
304            String text = DOMUtil.getSyntheticAnnotation(attrDecl);
305            if (text != null) {
306                annotation = traverseSyntheticAnnotation(attrDecl, text, attrValues, false, schemaDoc);
307            }
308        }
309
310        // get 'type definition'
311        XSSimpleType attrType = null;
312        boolean haveAnonType = false;
313
314        // Handle Anonymous type if there is one
315        if (child != null) {
316            String childName = DOMUtil.getLocalName(child);
317
318            if (childName.equals(SchemaSymbols.ELT_SIMPLETYPE)) {
319                attrType = fSchemaHandler.fSimpleTypeTraverser.traverseLocal(child, schemaDoc, grammar);
320                haveAnonType = true;
321                child = DOMUtil.getNextSiblingElement(child);
322            }
323        }
324
325        // Handle type attribute
326        if (attrType == null && typeAtt != null) {
327            XSTypeDefinition type = (XSTypeDefinition)fSchemaHandler.getGlobalDecl(schemaDoc, XSDHandler.TYPEDECL_TYPE, typeAtt, attrDecl);
328            if (type != null && type.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE) {
329                attrType = (XSSimpleType)type;
330            }
331            else {
332                reportSchemaError("src-resolve", new Object[]{typeAtt.rawname, "simpleType definition"}, attrDecl);
333                if (type == null) {
334                        attribute.fUnresolvedTypeName = typeAtt;
335                }
336            }
337        }
338
339        if (attrType == null) {
340            attrType = SchemaGrammar.fAnySimpleType;
341        }
342
343        XSObjectList annotations;
344        if (annotation != null) {
345            annotations = new XSObjectListImpl();
346            ((XSObjectListImpl)annotations).addXSObject(annotation);
347        } else {
348            annotations = XSObjectListImpl.EMPTY_LIST;
349        }
350        attribute.setValues(nameAtt, tnsAtt, attrType, constraintType, scope,
351                attDefault, enclCT, annotations);
352
353        // Step 3: check against schema for schemas
354
355        // required attributes
356        if (nameAtt == null) {
357            if (isGlobal)
358                reportSchemaError("s4s-att-must-appear", new Object[]{SchemaSymbols.ELT_ATTRIBUTE, SchemaSymbols.ATT_NAME}, attrDecl);
359            else
360                reportSchemaError("src-attribute.3.1", null, attrDecl);
361            nameAtt = NO_NAME;
362        }
363
364        // element
365        if (child != null) {
366            reportSchemaError("s4s-elt-must-match.1", new Object[]{nameAtt, "(annotation?, (simpleType?))", DOMUtil.getLocalName(child)}, child);
367        }
368
369        // Step 4: check 3.2.3 constraints
370
371        // src-attribute
372
373        // 1 default and fixed must not both be present.
374        if (defaultAtt != null && fixedAtt != null) {
375            reportSchemaError("src-attribute.1", new Object[]{nameAtt}, attrDecl);
376        }
377
378        // 2 If default and use are both present, use must have the actual value optional.
379        // This is checked in "traverse" method
380
381        // 3 If the item's parent is not <schema>, then all of the following must be true:
382        // 3.1 One of ref or name must be present, but not both.
383        // This is checked in XSAttributeChecker
384
385        // 3.2 If ref is present, then all of <simpleType>, form and type must be absent.
386        // Attributes are checked in XSAttributeChecker, elements are checked in "traverse" method
387
388        // 4 type and <simpleType> must not both be present.
389        if (haveAnonType && (typeAtt != null)) {
390            reportSchemaError( "src-attribute.4", new Object[]{nameAtt}, attrDecl);
391        }
392
393        // Step 5: check 3.2.6 constraints
394        // check for NOTATION type
395        checkNotationType(nameAtt, attrType, attrDecl);
396
397        // a-props-correct
398
399        // 2 if there is a {value constraint}, the canonical lexical representation of its value must be valid with respect to the {type definition} as defined in String Valid (3.14.4).
400        if (attDefault != null) {
401            fValidationState.setNamespaceSupport(schemaDoc.fNamespaceSupport);
402            try {
403                checkDefaultValid(attribute);
404            }
405            catch (InvalidDatatypeValueException ide) {
406                reportSchemaError (ide.getKey(), ide.getArgs(), attrDecl);
407                reportSchemaError ("a-props-correct.2", new Object[]{nameAtt, attDefault.normalizedValue}, attrDecl);
408                // Recover by removing the default value
409                attDefault = null;
410                constraintType = XSConstants.VC_NONE;
411                attribute.setValues(nameAtt, tnsAtt, attrType, constraintType, scope,
412                        attDefault, enclCT, annotations);
413            }
414        }
415
416        // 3 If the {type definition} is or is derived from ID then there must not be a {value constraint}.
417        if (attDefault != null) {
418            if (attrType.isIDType() ) {
419                reportSchemaError ("a-props-correct.3", new Object[]{nameAtt}, attrDecl);
420                // Recover by removing the default value
421                attDefault = null;
422                constraintType = XSConstants.VC_NONE;
423                attribute.setValues(nameAtt, tnsAtt, attrType, constraintType, scope,
424                        attDefault, enclCT, annotations);
425            }
426        }
427
428        // no-xmlns
429
430        // The {name} of an attribute declaration must not match xmlns.
431        if (nameAtt != null && nameAtt.equals(XMLSymbols.PREFIX_XMLNS)) {
432            reportSchemaError("no-xmlns", null, attrDecl);
433            return null;
434        }
435
436        // no-xsi
437
438        // The {target namespace} of an attribute declaration, whether local or top-level, must not match http://www.w3.org/2001/XMLSchema-instance (unless it is one of the four built-in declarations given in the next section).
439        if (tnsAtt != null && tnsAtt.equals(SchemaSymbols.URI_XSI)) {
440            reportSchemaError("no-xsi", new Object[]{SchemaSymbols.URI_XSI}, attrDecl);
441            return null;
442        }
443
444        // Attribute without a name. Return null.
445        if (nameAtt.equals(NO_NAME))
446            return null;
447
448        // Step 2: register attribute decl to the grammar
449        if (isGlobal) {
450            if (grammar.getGlobalAttributeDecl(nameAtt) == null) {
451                grammar.addGlobalAttributeDecl(attribute);
452            }
453
454            // also add it to extended map
455            final String loc = fSchemaHandler.schemaDocument2SystemId(schemaDoc);
456            final XSAttributeDecl attribute2 = grammar.getGlobalAttributeDecl(nameAtt, loc);
457            if (attribute2  == null) {
458                grammar.addGlobalAttributeDecl(attribute, loc);
459            }
460
461            if (fSchemaHandler.fTolerateDuplicates) {
462                if (attribute2  != null) {
463                    attribute = attribute2;
464                }
465                fSchemaHandler.addGlobalAttributeDecl(attribute);
466            }
467        }
468
469        return attribute;
470    }
471
472    // throws an error if the constraint value is invalid for the given type
473    void checkDefaultValid(XSAttributeDecl attribute) throws InvalidDatatypeValueException {
474        // validate the original lexical rep, and set the actual value
475        ((XSSimpleType)attribute.getTypeDefinition()).validate(attribute.getValInfo().normalizedValue, fValidationState, attribute.getValInfo());
476        // validate the canonical lexical rep
477        ((XSSimpleType)attribute.getTypeDefinition()).validate(attribute.getValInfo().stringValue(), fValidationState, attribute.getValInfo());
478    }
479
480    // throws an error if the constraint value is invalid for the given type
481    void checkDefaultValid(XSAttributeUseImpl attrUse) throws InvalidDatatypeValueException {
482        // validate the original lexical rep, and set the actual value
483        ((XSSimpleType)attrUse.fAttrDecl.getTypeDefinition()).validate(attrUse.fDefault.normalizedValue, fValidationState, attrUse.fDefault);
484        // validate the canonical lexical rep
485        ((XSSimpleType)attrUse.fAttrDecl.getTypeDefinition()).validate(attrUse.fDefault.stringValue(), fValidationState, attrUse.fDefault);
486    }
487
488}
489