Package org.apache.xerces.impl.xs.traversers

Source Code of org.apache.xerces.impl.xs.traversers.XSDSimpleTypeTraverser

/*
* The Apache Software License, Version 1.1
*
*
* Copyright (c) 2001 The Apache Software Foundation.  All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in
*    the documentation and/or other materials provided with the
*    distribution.
*
* 3. The end-user documentation included with the redistribution,
*    if any, must include the following acknowledgment:
*       "This product includes software developed by the
*        Apache Software Foundation (http://www.apache.org/)."
*    Alternately, this acknowledgment may appear in the software itself,
*    if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Xerces" and "Apache Software Foundation" must
*    not be used to endorse or promote products derived from this
*    software without prior written permission. For written
*    permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
*    nor may "Apache" appear in their name, without prior written
*    permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation and was
* originally based on software copyright (c) 2001, International
* Business Machines, Inc., http://www.apache.org.  For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/

package org.apache.xerces.impl.xs.traversers;

import org.apache.xerces.impl.dv.SchemaDVFactory;
import org.apache.xerces.impl.dv.XSSimpleType;
import org.apache.xerces.impl.dv.XSUnionSimpleType;
import org.apache.xerces.impl.dv.InvalidDatatypeFacetException;
import org.apache.xerces.impl.dv.XSFacets;
import org.apache.xerces.impl.XMLErrorReporter;
import org.apache.xerces.impl.xs.SchemaGrammar;
import org.apache.xerces.impl.xs.SchemaSymbols;

import org.apache.xerces.util.DOMUtil;
import org.apache.xerces.impl.xs.util.XInt;
import org.apache.xerces.impl.xs.util.XIntPool;
import org.apache.xerces.xni.QName;
import org.apache.xerces.util.NamespaceSupport;

import org.w3c.dom.Element;
import org.w3c.dom.Attr;
import org.w3c.dom.Node;

import java.lang.reflect.*;
import java.util.Hashtable;
import java.util.Vector;
import java.util.StringTokenizer;

/**
* The simple type definition schema component traverser.
*
* <simpleType
*   final = (#all | (list | union | restriction))
*   id = ID
*   name = NCName
*   {any attributes with non-schema namespace . . .}>
*   Content: (annotation?, (restriction | list | union))
* </simpleType>
*
* <restriction
*   base = QName
*   id = ID
*   {any attributes with non-schema namespace . . .}>
*   Content: (annotation?, (simpleType?, (minExclusive | minInclusive | maxExclusive | maxInclusive | totalDigits | fractionDigits | length | minLength | maxLength | enumeration | whiteSpace | pattern)*))
* </restriction>
*
* <list
*   id = ID
*   itemType = QName
*   {any attributes with non-schema namespace . . .}>
*   Content: (annotation?, (simpleType?))
* </list>
*
* <union
*   id = ID
*   memberTypes = List of QName
*   {any attributes with non-schema namespace . . .}>
*   Content: (annotation?, (simpleType*))
* </union>
*
* @author Elena Litani, IBM
* @author Neeraj Bajaj, Sun Microsystems, Inc.
* @version $Id: XSDSimpleTypeTraverser.java,v 1.5 2001/12/14 20:04:16 sandygao Exp $
*/
class XSDSimpleTypeTraverser extends XSDAbstractTraverser {

    //private data
    private String fListName = "";

    private int fSimpleTypeAnonCount = 0;
    private final QName fQName = new QName();
    private final SchemaDVFactory schemaFactory = SchemaDVFactory.getInstance();

    XSDSimpleTypeTraverser (XSDHandler handler,
                            XSAttributeChecker gAttrCheck) {
        super(handler, gAttrCheck);
    }

    //return qualified name of simpleType or empty string if error occured
    XSSimpleType traverseGlobal(Element elmNode,
                                     XSDocumentInfo schemaDoc,
                                     SchemaGrammar grammar) {
        // General Attribute Checking
        Object[] attrValues = fAttrChecker.checkAttributes(elmNode, true, schemaDoc);
        String nameAtt = (String)attrValues[XSAttributeChecker.ATTIDX_NAME];
        XSSimpleType type = traverseSimpleTypeDecl(elmNode, attrValues, schemaDoc, grammar, true);
        fAttrChecker.returnAttrArray(attrValues, schemaDoc);

        if (nameAtt == null)
            reportSchemaError("s4s-att-must-appear", new Object[]{SchemaSymbols.ELT_SIMPLETYPE, SchemaSymbols.ATT_NAME});

        return type;
    }

    XSSimpleType traverseLocal(Element elmNode,
                                    XSDocumentInfo schemaDoc,
                                    SchemaGrammar grammar) {

        Object[] attrValues = fAttrChecker.checkAttributes(elmNode, false, schemaDoc);
        XSSimpleType type = traverseSimpleTypeDecl (elmNode, attrValues, schemaDoc, grammar, false);
        fAttrChecker.returnAttrArray(attrValues, schemaDoc);

        return type;
    }

    private XSSimpleType traverseSimpleTypeDecl(Element simpleTypeDecl, Object[] attrValues,
                                                XSDocumentInfo schemaDoc,
                                                SchemaGrammar grammar, boolean isGlobal) {

        String nameProperty  = (String)attrValues[XSAttributeChecker.ATTIDX_NAME];
        String qualifiedName = nameProperty;

        //---------------------------------------------------
        // set qualified name
        //---------------------------------------------------
        if (nameProperty == null) { // anonymous simpleType
            qualifiedName = schemaDoc.fTargetNamespace == null?
                ",#s#"+(fSimpleTypeAnonCount++):
                schemaDoc.fTargetNamespace+",#S#"+(fSimpleTypeAnonCount++);
            //REVISIT:
            // add to symbol table?
        }
        else {
            qualifiedName = schemaDoc.fTargetNamespace == null?
                ","+nameProperty:
                schemaDoc.fTargetNamespace+","+nameProperty;
            //REVISIT:
            // add to symbol table?

        }

        //----------------------------------------------------------
        // REVISIT!
        // update _final_ registry
        //----------------------------------------------------------
        XInt finalAttr = (XInt)attrValues[XSAttributeChecker.ATTIDX_FINAL];
        int finalProperty = finalAttr == null ? schemaDoc.fFinalDefault : finalAttr.intValue();

        //----------------------------------------------------------
        //annotation?,(list|restriction|union)
        //----------------------------------------------------------
        Element content = DOMUtil.getFirstChildElement(simpleTypeDecl);
        if (content != null) {
            // traverse annotation if any
            if (DOMUtil.getLocalName(content).equals(SchemaSymbols.ELT_ANNOTATION)) {
                traverseAnnotationDecl(content, attrValues, false, schemaDoc);
                content = DOMUtil.getNextSiblingElement(content);
            }
        }

        if (content == null) {
            reportSchemaError("dt-simpleType", new Object[]{SchemaSymbols.ELT_SIMPLETYPE, nameProperty, "(annotation?, (restriction | list | union))"});
            return null;
        }

        // General Attribute Checking
        Object[] contentAttrs = fAttrChecker.checkAttributes(content, false, schemaDoc);
        // REVISIT: when to return the array
        fAttrChecker.returnAttrArray(contentAttrs, schemaDoc);

        //----------------------------------------------------------------------
        //use content.getLocalName for the cases there "xsd:" is a prefix, ei. "xsd:list"
        //----------------------------------------------------------------------
        String varietyProperty =  DOMUtil.getLocalName(content);
        QName baseTypeName = null;
        Vector memberTypes = null;
        Vector dTValidators = null;
        int size = 0;
        boolean list = false;
        boolean union = false;
        boolean restriction = false;
        int numOfTypes = 0; //list/restriction = 1, union = "+"

        if (varietyProperty.equals(SchemaSymbols.ELT_LIST)) { //traverse List
            baseTypeName = (QName)contentAttrs[XSAttributeChecker.ATTIDX_ITEMTYPE];
            list = true;
            if (fListName.length() != 0) { // parent is <list> datatype
                reportCosListOfAtomic(qualifiedName);
                return null;
            }
            else {
                fListName = qualifiedName;
            }
        }
        else if (varietyProperty.equals(SchemaSymbols.ELT_RESTRICTION)) { //traverse Restriction
            baseTypeName = (QName)contentAttrs[XSAttributeChecker.ATTIDX_BASE];
            //content.getAttribute( SchemaSymbols.ATT_BASE );
            restriction= true;
        }
        else if (varietyProperty.equals(SchemaSymbols.ELT_UNION)) { //traverse union
            union = true;
            memberTypes = (Vector)contentAttrs[XSAttributeChecker.ATTIDX_MEMBERTYPES];
            //content.getAttribute( SchemaSymbols.ATT_MEMBERTYPES);
            if (memberTypes != null) {
                size = memberTypes.size();
            }
            else {
                size = 1; //at least one must be seen as <simpleType> decl
            }
            dTValidators = new Vector (size, 2);
        }
        else {
            Object[] args = { varietyProperty};
            reportSchemaError("dt-unsupported-derivation", args);
        }
        if (DOMUtil.getNextSiblingElement(content) != null) {
            reportSchemaError("dt-simpleType", new Object[]{SchemaSymbols.ELT_SIMPLETYPE, nameProperty, "(annotation?, (restriction | list | union))"});
        }

        XSSimpleType baseValidator = null;
        if (baseTypeName == null && memberTypes == null) {
            //---------------------------
            //must 'see' <simpleType>
            //---------------------------

            //content = {annotation?,simpleType?...}
            content = DOMUtil.getFirstChildElement(content);

            //check content (annotation?, ...)
            if (content != null) {
                // traverse annotation if any
                if (DOMUtil.getLocalName(content).equals(SchemaSymbols.ELT_ANNOTATION)) {
                    traverseAnnotationDecl(content, attrValues, false, schemaDoc);
                    content = DOMUtil.getNextSiblingElement(content);
                }
            }
            if (content == null) {
                reportSchemaError("dt-simpleType", new Object[]{SchemaSymbols.ELT_SIMPLETYPE, nameProperty, "(annotation?, (restriction | list | union))"});
                return null;
            }
            if (DOMUtil.getLocalName(content).equals( SchemaSymbols.ELT_SIMPLETYPE )) {
                baseValidator = traverseLocal(content, schemaDoc, grammar);
                if (baseValidator != null && union) {
                    if (baseValidator.getVariety() == XSSimpleType.VARIETY_UNION) {
                        XSSimpleType[] types = ((XSUnionSimpleType)baseValidator).getMemberTypes();
                        for (int i = 0; i < types.length; i++)
                            dTValidators.addElement(types[i]);
                    } else {
                        dTValidators.addElement(baseValidator);
                    }
                }
                if (baseValidator == null) {
                    Object[] args = {content.getAttribute( SchemaSymbols.ATT_BASE )};
                    reportSchemaError("dt-unknown-basetype", args);
                    return (XSSimpleType)SchemaGrammar.SG_SchemaNS.getGlobalTypeDecl(SchemaSymbols.ATTVAL_ANYSIMPLETYPE);
                }
            }
            else {
                Object[] args = { simpleTypeDecl.getAttribute( SchemaSymbols.ATT_NAME )};
                reportSchemaError("dt-simpleType",new Object[]{SchemaSymbols.ELT_SIMPLETYPE, nameProperty, "(annotation?, (restriction | list | union))"});
                return (XSSimpleType)SchemaGrammar.SG_SchemaNS.getGlobalTypeDecl(SchemaSymbols.ATTVAL_ANYSIMPLETYPE);
            }
        }
        else {
            //-----------------------------
            //base was provided - get proper validator.
            //-----------------------------
            numOfTypes = 1;
            if (union) {
                numOfTypes= size;
            }
            //--------------------------------------------------------------------
            // this loop is also where we need to find out whether the type being used as
            // a base (or itemType or whatever) allows such things.
            //--------------------------------------------------------------------
            short baseRefContext = restriction ? SchemaSymbols.RESTRICTION :
                                   (union ? SchemaSymbols.UNION : SchemaSymbols.LIST);
            for (int i=0; i<numOfTypes; i++) {  //find all validators
                if (union) {
                    baseTypeName = (QName)memberTypes.elementAt(i);
                }
                baseValidator = findDTValidator ( simpleTypeDecl, baseTypeName, baseRefContext, schemaDoc);
                if (baseValidator == null) {
                    Object[] args = { content.getAttribute( SchemaSymbols.ATT_BASE ), nameProperty};
                    reportSchemaError("dt-unknown-basetype", args);
                    baseValidator = (XSSimpleType)SchemaGrammar.SG_SchemaNS.getGlobalTypeDecl(SchemaSymbols.ATTVAL_ANYSIMPLETYPE);
                }
                // ------------------------------
                // (variety is list)cos-list-of-atomic
                // ------------------------------
                if (fListName.length() != 0) {
                    if (baseValidator.getVariety() == XSSimpleType.VARIETY_LIST) {
                        reportCosListOfAtomic(qualifiedName);
                        return null;
                    }
                    //-----------------------------------------------------
                    // if baseValidator is of type (union) need to look
                    // at Union validators to make sure that List is not one of them
                    //-----------------------------------------------------
                    if (isListDatatype(baseValidator)) {
                        reportCosListOfAtomic(qualifiedName);
                        return null;

                    }

                }
                if (union) {
                    if (baseValidator.getVariety() == XSSimpleType.VARIETY_UNION) {
                        XSSimpleType[] types = ((XSUnionSimpleType)baseValidator).getMemberTypes();
                        for (int j = 0; j < types.length; j++)
                            dTValidators.addElement(types[j]);
                    } else {
                        dTValidators.addElement(baseValidator);
                    }
                }
            }
        } //end - base is available

        // ------------------------------------------
        // move to next child
        // <base==empty)->[simpleType]->[facets]  OR
        // <base!=empty)->[facets]
        // ------------------------------------------
        if (baseTypeName == null) {
            content = DOMUtil.getNextSiblingElement( content );
        }
        else {
            content = DOMUtil.getFirstChildElement(content);
            if (content != null) {
                // traverse annotation if any
                if (DOMUtil.getLocalName(content).equals(SchemaSymbols.ELT_ANNOTATION)) {
                    traverseAnnotationDecl(content, attrValues, false, schemaDoc);
                    content = DOMUtil.getNextSiblingElement(content);
                }
            }
        }

        // ------------------------------------------
        //get more types for union if any
        // ------------------------------------------
        if (union) {
            if (memberTypes != null) {
                if (content != null) {
                    // traverse annotation if any
                    if (DOMUtil.getLocalName(content).equals(SchemaSymbols.ELT_ANNOTATION)) {
                        traverseAnnotationDecl(content, attrValues, false, schemaDoc);
                        content = DOMUtil.getNextSiblingElement(content);
                    }
                }
                if (content !=null) {
                    if (DOMUtil.getLocalName(content).equals(SchemaSymbols.ELT_ANNOTATION)) {
                        Object[] args = {nameProperty};
                        reportSchemaError("dt-union-memberType", args);
                    }
                }
            }
            while (content!=null) {
                baseValidator = traverseLocal(content, schemaDoc, grammar);
                if (baseValidator != null) {
                    if (fListName.length() != 0 && baseValidator.getVariety() == XSSimpleType.VARIETY_LIST) {
                        reportCosListOfAtomic(qualifiedName);
                        return null;
                    }
                    if (baseValidator.getVariety() == XSSimpleType.VARIETY_UNION) {
                        XSSimpleType[] types = ((XSUnionSimpleType)baseValidator).getMemberTypes();
                        for (int i = 0; i < types.length; i++)
                            dTValidators.addElement(types[i]);
                    } else {
                        dTValidators.addElement(baseValidator);
                    }
                }
                if (baseValidator == null) {
                    Object[] args = { content.getAttribute( SchemaSymbols.ATT_BASE ), nameProperty};
                    reportSchemaError("dt-unknown-basetype", args);
                    baseValidator = (XSSimpleType)SchemaGrammar.SG_SchemaNS.getGlobalTypeDecl(SchemaSymbols.ATTVAL_ANYSIMPLETYPE);
                }
                content   = DOMUtil.getNextSiblingElement( content );
            }
        } // end - traverse Union

        if (fListName.length() != 0) {
            // reset fListName, meaning that we are done with
            // traversing <list> and its itemType resolves to atomic value
            if (fListName.equals(qualifiedName)) {
                fListName = SchemaSymbols.EMPTY_STRING;
            }
        }

        XSFacets facetData = null;
        short presentFacets = 0;
        short fixedFacets = 0 ;

        if (restriction && content != null) { //we are on the facets now..
            FacetInfo fi = traverseFacets(content, contentAttrs,nameProperty, baseValidator, schemaDoc, grammar);
            content = fi.nodeAfterFacets;
            if (content != null) {
                content = null;
                reportSchemaError("s4s-elt-must-match", new Object[]{SchemaSymbols.ELT_RESTRICTION, "(annotation?, (simpleType?, (minExclusive | minInclusive | maxExclusive | maxInclusive | totalDigits | fractionDigits | length | minLength | maxLength | enumeration | whiteSpace | pattern)*))"});
            }
            facetData = fi.facetdata ;
            presentFacets = fi.fPresentFacets;
            fixedFacets = fi.fFixedFacets;
        }
        else if (list && content!=null) {
            // report error - must not have any children!
            if (baseTypeName !=null) {
                // traverse annotation if any
                if (DOMUtil.getLocalName(content).equals(SchemaSymbols.ELT_ANNOTATION)) {
                    traverseAnnotationDecl(content, attrValues, false, schemaDoc);
                    content = DOMUtil.getNextSiblingElement(content);
                }
                if (content !=null) {
                    Object[] args = {nameProperty};
                    reportSchemaError("dt-list-itemType", args);
                }
            }
            else {
                reportSchemaError("s4s-elt-must-match", new Object[]{SchemaSymbols.ELT_LIST, "(annotation?, (simpleType?))"});
            }
        }
        else if (union && content!=null) {
            //report error - must not have any children!
            reportSchemaError("s4s-elt-must-match", new Object[]{SchemaSymbols.ELT_UNION, "(annotation?, (simpleType?))"});
        }

        XSSimpleType newDecl = null;
        if (list) {
            newDecl = schemaFactory.createTypeList(nameProperty, schemaDoc.fTargetNamespace, (short)finalProperty, baseValidator);
        }
        else if (restriction) {
            newDecl = schemaFactory.createTypeRestriction(nameProperty, schemaDoc.fTargetNamespace, (short)finalProperty, baseValidator);
            try {
                fValidationState.setNamespaceSupport(schemaDoc.fNamespaceSupport);
                newDecl.applyFacets(facetData , presentFacets , fixedFacets, fValidationState);
            } catch (InvalidDatatypeFacetException ex) {
                reportGenericSchemaError("facet error when creating type '" + qualifiedName + "': " + ex.getLocalizedMessage());
            }
        }
        else { //union
            XSSimpleType[] memberDecls = new XSSimpleType[dTValidators.size()];
            for (int i = 0; i < dTValidators.size(); i++)
                memberDecls[i] = (XSSimpleType)dTValidators.elementAt(i);
            newDecl = schemaFactory.createTypeUnion(nameProperty, schemaDoc.fTargetNamespace, (short)finalProperty, memberDecls);
        }

        // if it's a global type without a name, return null
        if (nameProperty == null && isGlobal) {
            return null;
        }

        // don't add global components without name to the grammar
        if (newDecl != null && isGlobal) {
            grammar.addGlobalTypeDecl(newDecl);
        }

        return newDecl;
    }

    private void reportCosListOfAtomic (String qualifiedName) {
        fListName = "";
        reportSchemaError("cos-list-of-atomic", new Object[]{qualifiedName});
    }

    //@param: elm - top element
    //@param: baseTypeStr - type (base/itemType/memberTypes)
    //@param: baseRefContext:  whether the caller is using this type as a base for restriction, union or list
    //return XSSimpleType available for the baseTypeStr, null if not found or disallowed.
    // also throws an error if the base type won't allow itself to be used in this context.
    // REVISIT: can this code be re-used?
    private XSSimpleType findDTValidator (Element elm, QName baseTypeStr, short baseRefContext, XSDocumentInfo schemaDoc) {
        if(baseTypeStr == null)
            return null;

        if (baseTypeStr.uri != null && baseTypeStr.uri.equals(SchemaSymbols.URI_SCHEMAFORSCHEMA) &&
            (baseTypeStr.localpart.equals(SchemaSymbols.ATTVAL_ANYSIMPLETYPE) ||
             baseTypeStr.localpart.equals(SchemaSymbols.ATTVAL_ANYTYPE)) &&
            baseRefContext == SchemaSymbols.RESTRICTION) {
            String base = baseTypeStr.localpart;
            reportSchemaError("dt-unknown-basetype", new Object[] {
                                       DOMUtil.getAttrValue(elm, SchemaSymbols.ATT_NAME), DOMUtil.getAttrValue(elm, SchemaSymbols.ATT_BASE)});
            return  (XSSimpleType)SchemaGrammar.SG_SchemaNS.getGlobalTypeDecl(SchemaSymbols.ATTVAL_ANYSIMPLETYPE);
        }

        XSSimpleType baseType = null;
        baseType = (XSSimpleType)fSchemaHandler.getGlobalDecl(schemaDoc, fSchemaHandler.TYPEDECL_TYPE, baseTypeStr);
        if (baseType != null) {
            if ((baseType.getFinalSet() & baseRefContext) != 0) {
                reportSchemaError("dt-restiction-final",new Object[] { baseTypeStr.rawname} );
            }
        }
        return baseType;
    }

    // find if union datatype validator has list datatype member.
    private boolean isListDatatype(XSSimpleType validator) {
        if (validator.getVariety() == XSSimpleType.VARIETY_LIST)
            return true;

        if (validator.getVariety() == XSSimpleType.VARIETY_UNION) {
            XSSimpleType[] temp = ((XSUnionSimpleType)validator).getMemberTypes();
            for (int i = 0; i < temp.length; i++) {
                if (temp[i].getVariety() == XSSimpleType.VARIETY_LIST) {
                    return true;
                }
            }
        }

        return false;
    }//isListDatatype(XSSimpleTypeDecl):boolean

}//class XSDSimpleTypeTraverser
TOP

Related Classes of org.apache.xerces.impl.xs.traversers.XSDSimpleTypeTraverser

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.