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.xpath.XPathException;
25import com.sun.org.apache.xerces.internal.impl.xs.SchemaSymbols;
26import com.sun.org.apache.xerces.internal.impl.xs.identity.Field;
27import com.sun.org.apache.xerces.internal.impl.xs.identity.IdentityConstraint;
28import com.sun.org.apache.xerces.internal.impl.xs.identity.Selector;
29import com.sun.org.apache.xerces.internal.util.DOMUtil;
30import com.sun.org.apache.xerces.internal.util.XMLChar;
31import org.w3c.dom.Element;
32
33/**
34 * This class contains code that all three IdentityConstraint
35 * traversers (the XSDUniqueTraverser, XSDKeyTraverser and
36 * XSDKeyrefTraverser) rely upon.
37 *
38 * @xerces.internal
39 *
40 */
41class XSDAbstractIDConstraintTraverser extends XSDAbstractTraverser {
42
43    public XSDAbstractIDConstraintTraverser (XSDHandler handler,
44            XSAttributeChecker gAttrCheck) {
45        super(handler, gAttrCheck);
46    }
47
48    boolean traverseIdentityConstraint(IdentityConstraint ic,
49            Element icElem, XSDocumentInfo schemaDoc, Object [] icElemAttrs) {
50
51        // General Attribute Checking will have been done on icElem by caller
52
53        // check for <annotation> and get selector
54        Element sElem = DOMUtil.getFirstChildElement(icElem);
55        if(sElem == null) {
56            reportSchemaError("s4s-elt-must-match.2",
57                    new Object[]{"identity constraint", "(annotation?, selector, field+)"},
58                    icElem);
59            return false;
60        }
61
62        // General Attribute Checking on sElem
63        // first child could be an annotation
64        if (DOMUtil.getLocalName(sElem).equals(SchemaSymbols.ELT_ANNOTATION)) {
65            ic.addAnnotation(traverseAnnotationDecl(sElem, icElemAttrs, false, schemaDoc));
66            sElem = DOMUtil.getNextSiblingElement(sElem);
67            // if no more children report an error
68            if(sElem == null) {
69                reportSchemaError("s4s-elt-must-match.2", new Object[]{"identity constraint", "(annotation?, selector, field+)"}, icElem);
70                return false;
71            }
72        }
73        else {
74            String text = DOMUtil.getSyntheticAnnotation(icElem);
75            if (text != null) {
76                ic.addAnnotation(traverseSyntheticAnnotation(icElem, text, icElemAttrs, false, schemaDoc));
77            }
78        }
79
80        // must be <selector>
81        if(!DOMUtil.getLocalName(sElem).equals(SchemaSymbols.ELT_SELECTOR)) {
82            reportSchemaError("s4s-elt-must-match.1", new Object[]{"identity constraint", "(annotation?, selector, field+)", SchemaSymbols.ELT_SELECTOR}, sElem);
83            return false;
84        }
85        Object [] attrValues = fAttrChecker.checkAttributes(sElem, false, schemaDoc);
86
87        // make sure <selector>'s content is fine:
88        Element selChild = DOMUtil.getFirstChildElement(sElem);
89
90        if (selChild !=null) {
91            // traverse annotation if any
92            if (DOMUtil.getLocalName(selChild).equals(SchemaSymbols.ELT_ANNOTATION)) {
93                ic.addAnnotation(traverseAnnotationDecl(selChild, attrValues, false, schemaDoc));
94                selChild = DOMUtil.getNextSiblingElement(selChild);
95            }
96            else {
97                reportSchemaError("s4s-elt-must-match.1", new Object[]{SchemaSymbols.ELT_SELECTOR, "(annotation?)", DOMUtil.getLocalName(selChild)}, selChild);
98            }
99            if (selChild != null) {
100                reportSchemaError("s4s-elt-must-match.1", new Object [] {SchemaSymbols.ELT_SELECTOR, "(annotation?)", DOMUtil.getLocalName(selChild)}, selChild);
101            }
102        }
103        else {
104            String text = DOMUtil.getSyntheticAnnotation(sElem);
105            if (text != null) {
106                ic.addAnnotation(traverseSyntheticAnnotation(icElem, text, attrValues, false, schemaDoc));
107            }
108        }
109
110        String sText = ((String)attrValues[XSAttributeChecker.ATTIDX_XPATH]);
111        if(sText == null) {
112            reportSchemaError("s4s-att-must-appear", new Object [] {SchemaSymbols.ELT_SELECTOR, SchemaSymbols.ATT_XPATH}, sElem);
113            return false;
114        }
115        sText = XMLChar.trim(sText);
116
117        Selector.XPath sXpath = null;
118        try {
119            sXpath = new Selector.XPath(sText, fSymbolTable,
120                    schemaDoc.fNamespaceSupport);
121            Selector selector = new Selector(sXpath, ic);
122            ic.setSelector(selector);
123        }
124        catch (XPathException e) {
125            reportSchemaError(e.getKey(), new Object[]{sText}, sElem);
126            // put back attr values...
127            fAttrChecker.returnAttrArray(attrValues, schemaDoc);
128            return false;
129        }
130
131        // put back attr values...
132        fAttrChecker.returnAttrArray(attrValues, schemaDoc);
133
134        // get fields
135        Element fElem = DOMUtil.getNextSiblingElement(sElem);
136        if(fElem == null) {
137            reportSchemaError("s4s-elt-must-match.2", new Object[]{"identity constraint", "(annotation?, selector, field+)"}, sElem);
138            return false;
139        }
140        while (fElem != null) {
141            if(!DOMUtil.getLocalName(fElem).equals(SchemaSymbols.ELT_FIELD)) {
142                reportSchemaError("s4s-elt-must-match.1", new Object[]{"identity constraint", "(annotation?, selector, field+)", SchemaSymbols.ELT_FIELD}, fElem);
143                fElem = DOMUtil.getNextSiblingElement(fElem);
144                continue;
145            }
146
147            // General Attribute Checking
148            attrValues = fAttrChecker.checkAttributes(fElem, false, schemaDoc);
149
150            // and make sure <field>'s content is fine:
151            Element fieldChild = DOMUtil.getFirstChildElement(fElem);
152            if (fieldChild != null) {
153                // traverse annotation
154                if (DOMUtil.getLocalName(fieldChild).equals(SchemaSymbols.ELT_ANNOTATION)) {
155                    ic.addAnnotation(traverseAnnotationDecl(fieldChild, attrValues, false, schemaDoc));
156                    fieldChild = DOMUtil.getNextSiblingElement(fieldChild);
157                }
158            }
159            if (fieldChild != null) {
160                reportSchemaError("s4s-elt-must-match.1", new Object [] {SchemaSymbols.ELT_FIELD, "(annotation?)", DOMUtil.getLocalName(fieldChild)}, fieldChild);
161            }
162            else {
163                String text = DOMUtil.getSyntheticAnnotation(fElem);
164                if (text != null) {
165                    ic.addAnnotation(traverseSyntheticAnnotation(icElem, text, attrValues, false, schemaDoc));
166                }
167            }
168            String fText = ((String)attrValues[XSAttributeChecker.ATTIDX_XPATH]);
169            if (fText == null) {
170                reportSchemaError("s4s-att-must-appear", new Object [] {SchemaSymbols.ELT_FIELD, SchemaSymbols.ATT_XPATH}, fElem);
171                fAttrChecker.returnAttrArray(attrValues, schemaDoc);
172                return false;
173            }
174            fText = XMLChar.trim(fText);
175            try {
176                Field.XPath fXpath = new Field.XPath(fText, fSymbolTable,
177                        schemaDoc.fNamespaceSupport);
178                Field field = new Field(fXpath, ic);
179                ic.addField(field);
180            }
181            catch (XPathException e) {
182                reportSchemaError(e.getKey(), new Object[]{fText}, fElem);
183                // put back attr values...
184                fAttrChecker.returnAttrArray(attrValues, schemaDoc);
185                return false;
186            }
187            fElem = DOMUtil.getNextSiblingElement(fElem);
188            // put back attr values...
189            fAttrChecker.returnAttrArray(attrValues, schemaDoc);
190        }
191
192        return ic.getFieldCount() > 0;
193    } // traverseIdentityConstraint(IdentityConstraint,Element, XSDocumentInfo)
194} // XSDAbstractIDConstraintTraverser
195