| /* |
| * 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.XSSimpleType; |
| import org.apache.xerces.impl.dv.SchemaDVFactory; |
| import org.apache.xerces.impl.dv.XSFacets; |
| import org.apache.xerces.impl.dv.InvalidDatatypeFacetException; |
| import org.apache.xerces.impl.XMLErrorReporter; |
| import org.apache.xerces.impl.xs.XSConstraints; |
| import org.apache.xerces.impl.xs.SchemaGrammar; |
| import org.apache.xerces.impl.xs.SchemaSymbols; |
| import org.apache.xerces.impl.xs.XSComplexTypeDecl; |
| import org.apache.xerces.impl.xs.XSTypeDecl; |
| import org.apache.xerces.impl.xs.XSAttributeGroupDecl; |
| import org.apache.xerces.impl.xs.XSAttributeUse; |
| import org.apache.xerces.impl.xs.XSWildcardDecl; |
| import org.apache.xerces.impl.xs.XSParticleDecl; |
| 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.w3c.dom.Element; |
| import java.util.Hashtable; |
| |
| /** |
| * A complex type definition schema component traverser. |
| * |
| * <complexType |
| * abstract = boolean : false |
| * block = (#all | List of (extension | restriction)) |
| * final = (#all | List of (extension | restriction)) |
| * id = ID |
| * mixed = boolean : false |
| * name = NCName |
| * {any attributes with non-schema namespace . . .}> |
| * Content: (annotation?, (simpleContent | complexContent | |
| * ((group | all | choice | sequence)?, |
| * ((attribute | attributeGroup)*, anyAttribute?)))) |
| * </complexType> |
| * @version $Id$ |
| */ |
| |
| class XSDComplexTypeTraverser extends XSDAbstractParticleTraverser { |
| |
| |
| XSDComplexTypeTraverser (XSDHandler handler, |
| XSAttributeChecker gAttrCheck) { |
| super(handler, gAttrCheck); |
| } |
| |
| |
| private static final boolean DEBUG=false; |
| |
| private static XSParticleDecl fErrorContent=null; |
| private SchemaDVFactory schemaFactory = SchemaDVFactory.getInstance(); |
| |
| private class ComplexTypeRecoverableError extends Exception { |
| |
| Object[] errorSubstText=null; |
| ComplexTypeRecoverableError() { |
| super(); |
| } |
| ComplexTypeRecoverableError(String msgKey) { |
| super(msgKey); |
| } |
| ComplexTypeRecoverableError(String msgKey, Object[] args) { |
| super(msgKey); |
| errorSubstText=args; |
| } |
| |
| } |
| |
| /** |
| * Traverse local complexType declarations |
| * |
| * @param Element |
| * @param XSDocumentInfo |
| * @param SchemaGrammar |
| * @return XSComplexTypeDecl |
| */ |
| XSComplexTypeDecl traverseLocal(Element complexTypeNode, |
| XSDocumentInfo schemaDoc, |
| SchemaGrammar grammar) { |
| |
| |
| Object[] attrValues = fAttrChecker.checkAttributes(complexTypeNode, false, |
| schemaDoc); |
| String complexTypeName = genAnonTypeName(complexTypeNode); |
| XSComplexTypeDecl type = traverseComplexTypeDecl (complexTypeNode, |
| complexTypeName, attrValues, schemaDoc, grammar); |
| // need to add the type to the grammar for later constraint checking |
| grammar.addComplexTypeDecl(type); |
| type.setIsAnonymous(); |
| fAttrChecker.returnAttrArray(attrValues, schemaDoc); |
| |
| return type; |
| } |
| |
| /** |
| * Traverse global complexType declarations |
| * |
| * @param Element |
| * @param XSDocumentInfo |
| * @param SchemaGrammar |
| * @return XSComplexTypeDecXSComplexTypeDecl |
| */ |
| XSComplexTypeDecl traverseGlobal (Element complexTypeNode, |
| XSDocumentInfo schemaDoc, |
| SchemaGrammar grammar) { |
| |
| Object[] attrValues = fAttrChecker.checkAttributes(complexTypeNode, true, |
| schemaDoc); |
| String complexTypeName = (String) attrValues[XSAttributeChecker.ATTIDX_NAME]; |
| XSComplexTypeDecl type = traverseComplexTypeDecl (complexTypeNode, |
| complexTypeName, attrValues, schemaDoc, grammar); |
| if (complexTypeName == null) { |
| reportSchemaError("s4s-att-must-appear", new Object[]{SchemaSymbols.ELT_COMPLEXTYPE, SchemaSymbols.ATT_NAME}); |
| } else { |
| grammar.addGlobalTypeDecl(type); |
| } |
| // need to add the type to the grammar for later constraint checking |
| grammar.addComplexTypeDecl(type); |
| fAttrChecker.returnAttrArray(attrValues, schemaDoc); |
| |
| return type; |
| } |
| |
| |
| private XSComplexTypeDecl traverseComplexTypeDecl(Element complexTypeDecl, |
| String complexTypeName, |
| Object[] attrValues, |
| XSDocumentInfo schemaDoc, |
| SchemaGrammar grammar) { |
| |
| Boolean abstractAtt = (Boolean) attrValues[XSAttributeChecker.ATTIDX_ABSTRACT]; |
| XInt blockAtt = (XInt) attrValues[XSAttributeChecker.ATTIDX_BLOCK]; |
| Boolean mixedAtt = (Boolean) attrValues[XSAttributeChecker.ATTIDX_MIXED]; |
| XInt finalAtt = (XInt) attrValues[XSAttributeChecker.ATTIDX_FINAL]; |
| |
| XSComplexTypeDecl complexType = new XSComplexTypeDecl(); |
| complexType.fName = complexTypeName; |
| complexType.fTargetNamespace = schemaDoc.fTargetNamespace; |
| complexType.fBlock = blockAtt == null ? |
| schemaDoc.fBlockDefault : blockAtt.shortValue(); |
| complexType.fFinal = finalAtt == null ? |
| schemaDoc.fFinalDefault : finalAtt.shortValue(); |
| if (abstractAtt != null && abstractAtt.booleanValue()) |
| complexType.setIsAbstractType(); |
| |
| |
| Element child = null; |
| |
| try { |
| // --------------------------------------------------------------- |
| // First, handle any ANNOTATION declaration and get next child |
| // --------------------------------------------------------------- |
| child = DOMUtil.getFirstChildElement(complexTypeDecl); |
| |
| if (child != null) { |
| // traverse annotation if any |
| if (DOMUtil.getLocalName(child).equals(SchemaSymbols.ELT_ANNOTATION)) { |
| traverseAnnotationDecl(child, attrValues, false, schemaDoc); |
| child = DOMUtil.getNextSiblingElement(child); |
| } |
| if (child !=null && DOMUtil.getLocalName(child).equals(SchemaSymbols.ELT_ANNOTATION)) { |
| throw new ComplexTypeRecoverableError("src-ct.0.1", |
| new Object[]{complexType.fName,SchemaSymbols.ELT_ANNOTATION}); |
| } |
| } |
| // --------------------------------------------------------------- |
| // Process the content of the complex type definition |
| // --------------------------------------------------------------- |
| if (child==null) { |
| // |
| // EMPTY complexType with complexContent |
| // |
| |
| // set the base to the anyType |
| complexType.fBaseType = SchemaGrammar.fAnyType; |
| processComplexContent(child, complexType, mixedAtt.booleanValue(), false, |
| schemaDoc, grammar); |
| } |
| else if (DOMUtil.getLocalName(child).equals |
| (SchemaSymbols.ELT_SIMPLECONTENT)) { |
| // |
| // SIMPLE CONTENT |
| // |
| traverseSimpleContent(child, complexType, schemaDoc, grammar); |
| if (DOMUtil.getNextSiblingElement(child)!=null) { |
| String siblingName = DOMUtil.getLocalName(DOMUtil.getNextSiblingElement(child)); |
| throw new ComplexTypeRecoverableError("src-ct.0.1", |
| new Object[]{complexType.fName,siblingName}); |
| } |
| } |
| else if (DOMUtil.getLocalName(child).equals |
| (SchemaSymbols.ELT_COMPLEXCONTENT)) { |
| traverseComplexContent(child, complexType, mixedAtt.booleanValue(), |
| schemaDoc, grammar); |
| if (DOMUtil.getNextSiblingElement(child)!=null) { |
| String siblingName = DOMUtil.getLocalName(DOMUtil.getNextSiblingElement(child)); |
| throw new ComplexTypeRecoverableError("src-ct.0.1", |
| new Object[]{complexType.fName,siblingName}); |
| } |
| } |
| else { |
| // |
| // We must have .... |
| // GROUP, ALL, SEQUENCE or CHOICE, followed by optional attributes |
| // Note that it's possible that only attributes are specified. |
| // |
| |
| // set the base to the anyType |
| complexType.fBaseType = SchemaGrammar.fAnyType; |
| processComplexContent(child, complexType, mixedAtt.booleanValue(), false, |
| schemaDoc, grammar); |
| } |
| |
| } |
| catch (ComplexTypeRecoverableError e) { |
| handleComplexTypeError(e.getMessage(),e.errorSubstText, complexType); |
| } |
| |
| if (DEBUG) { |
| System.out.println(complexType.toString()); |
| } |
| return complexType; |
| |
| |
| } |
| |
| |
| private void traverseSimpleContent(Element simpleContentElement, |
| XSComplexTypeDecl typeInfo, |
| XSDocumentInfo schemaDoc, |
| SchemaGrammar grammar) |
| throws ComplexTypeRecoverableError { |
| |
| |
| String typeName = typeInfo.fName; |
| Object[] attrValues = fAttrChecker.checkAttributes(simpleContentElement, false, |
| schemaDoc); |
| |
| // ----------------------------------------------------------------------- |
| // Set content type |
| // ----------------------------------------------------------------------- |
| typeInfo.fContentType = XSComplexTypeDecl.CONTENTTYPE_SIMPLE; |
| typeInfo.fParticle = null; |
| |
| Element simpleContent = DOMUtil.getFirstChildElement(simpleContentElement); |
| if (simpleContent != null) { |
| // traverse annotation if any |
| if (DOMUtil.getLocalName(simpleContent).equals(SchemaSymbols.ELT_ANNOTATION)) { |
| traverseAnnotationDecl(simpleContent, attrValues, false, schemaDoc); |
| simpleContent = DOMUtil.getNextSiblingElement(simpleContent); |
| } |
| } |
| fAttrChecker.returnAttrArray(attrValues, schemaDoc); |
| |
| // If there are no children, return |
| if (simpleContent==null) { |
| throw new ComplexTypeRecoverableError("src-ct.0.2", |
| new Object[]{typeInfo.fName,SchemaSymbols.ELT_SIMPLECONTENT}); |
| } |
| |
| // ----------------------------------------------------------------------- |
| // The content should be either "restriction" or "extension" |
| // ----------------------------------------------------------------------- |
| String simpleContentName = DOMUtil.getLocalName(simpleContent); |
| if (simpleContentName.equals(SchemaSymbols.ELT_RESTRICTION)) |
| typeInfo.fDerivedBy = SchemaSymbols.RESTRICTION; |
| else if (simpleContentName.equals(SchemaSymbols.ELT_EXTENSION)) |
| typeInfo.fDerivedBy = SchemaSymbols.EXTENSION; |
| else { |
| throw new ComplexTypeRecoverableError("src-ct.0.1", |
| new Object[]{typeInfo.fName,simpleContentName}); |
| } |
| if (DOMUtil.getNextSiblingElement(simpleContent) != null) { |
| String siblingName = DOMUtil.getLocalName(DOMUtil.getNextSiblingElement(simpleContent)); |
| throw new ComplexTypeRecoverableError("src-ct.0.1", |
| new Object[]{typeInfo.fName,siblingName}); |
| } |
| |
| attrValues = fAttrChecker.checkAttributes(simpleContent, false, |
| schemaDoc); |
| QName baseTypeName = (QName) attrValues[XSAttributeChecker.ATTIDX_BASE]; |
| fAttrChecker.returnAttrArray(attrValues, schemaDoc); |
| |
| |
| // ----------------------------------------------------------------------- |
| // Need a base type. |
| // ----------------------------------------------------------------------- |
| if (baseTypeName==null) { |
| throw new ComplexTypeRecoverableError("src-ct.0.3", |
| new Object[]{typeInfo.fName}); |
| } |
| |
| XSTypeDecl type = (XSTypeDecl)fSchemaHandler.getGlobalDecl(schemaDoc, |
| XSDHandler.TYPEDECL_TYPE, baseTypeName); |
| if (type==null) |
| throw new ComplexTypeRecoverableError(); |
| |
| typeInfo.fBaseType = type; |
| |
| XSSimpleType baseValidator = null; |
| XSComplexTypeDecl baseComplexType = null; |
| int baseFinalSet = 0; |
| |
| // If the base type is complex, it must have simpleContent |
| if ((type.getXSType() == XSTypeDecl.COMPLEX_TYPE)) { |
| |
| baseComplexType = (XSComplexTypeDecl)type; |
| if (baseComplexType.fContentType != XSComplexTypeDecl.CONTENTTYPE_SIMPLE) { |
| throw new ComplexTypeRecoverableError("src-ct.2", |
| new Object[]{typeInfo.fName}); |
| } |
| baseFinalSet = baseComplexType.fFinal; |
| baseValidator = baseComplexType.fXSSimpleType; |
| } |
| else { |
| baseValidator = (XSSimpleType)type; |
| if (typeInfo.fDerivedBy == SchemaSymbols.RESTRICTION) { |
| throw new ComplexTypeRecoverableError("src-ct.2", |
| new Object[]{typeInfo.fName}); |
| } |
| baseFinalSet=baseValidator.getFinalSet(); |
| } |
| |
| // ----------------------------------------------------------------------- |
| // Check that the base permits the derivation |
| // ----------------------------------------------------------------------- |
| if ((baseFinalSet & typeInfo.fDerivedBy)!=0) { |
| String errorKey = (typeInfo.fDerivedBy==SchemaSymbols.EXTENSION) ? |
| "cos-ct-extends.1.1" : "derivation-ok-restriction.1"; |
| throw new ComplexTypeRecoverableError(errorKey, |
| new Object[]{typeInfo.fName}); |
| } |
| |
| // ----------------------------------------------------------------------- |
| // Skip over any potential annotations |
| // ----------------------------------------------------------------------- |
| simpleContent = DOMUtil.getFirstChildElement(simpleContent); |
| if (simpleContent != null) { |
| // traverse annotation if any |
| |
| if (DOMUtil.getLocalName(simpleContent).equals(SchemaSymbols.ELT_ANNOTATION)) { |
| traverseAnnotationDecl(simpleContent, null, false, schemaDoc); |
| simpleContent = DOMUtil.getNextSiblingElement(simpleContent); |
| } |
| |
| if (simpleContent !=null && |
| DOMUtil.getLocalName(simpleContent).equals(SchemaSymbols.ELT_ANNOTATION)){ |
| throw new ComplexTypeRecoverableError("src-ct.0.1", |
| new Object[]{typeName,SchemaSymbols.ELT_ANNOTATION}); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| // Process a RESTRICTION |
| // ----------------------------------------------------------------------- |
| if (typeInfo.fDerivedBy == SchemaSymbols.RESTRICTION) { |
| |
| // ----------------------------------------------------------------------- |
| // There may be a simple type definition in the restriction element |
| // The data type validator will be based on it, if specified |
| // ----------------------------------------------------------------------- |
| if (simpleContent !=null && |
| DOMUtil.getLocalName(simpleContent).equals(SchemaSymbols.ELT_SIMPLETYPE )) { |
| |
| XSSimpleType dv = fSchemaHandler.fSimpleTypeTraverser.traverseLocal( |
| simpleContent, schemaDoc, grammar); |
| if (dv == null) |
| throw new ComplexTypeRecoverableError(); |
| |
| //check that this datatype validator is validly derived from the base |
| //according to derivation-ok-restriction 5.1.1 |
| |
| if (!XSConstraints.checkSimpleDerivationOk(dv, baseValidator, |
| baseValidator.getFinalSet())) { |
| throw new ComplexTypeRecoverableError("derivation-ok-restriction.5.1.1", |
| new Object[]{typeName}); |
| } |
| baseValidator = dv; |
| simpleContent = DOMUtil.getNextSiblingElement(simpleContent); |
| } |
| |
| // ----------------------------------------------------------------------- |
| // Traverse any facets |
| // ----------------------------------------------------------------------- |
| Element attrNode = null; |
| XSFacets facetData = null; |
| short presentFacets = 0 ; |
| short fixedFacets = 0 ; |
| |
| if (simpleContent!=null) { |
| FacetInfo fi = traverseFacets(simpleContent, null, typeName, baseValidator, |
| schemaDoc, grammar); |
| attrNode = fi.nodeAfterFacets; |
| facetData = fi.facetdata; |
| presentFacets = fi.fPresentFacets; |
| fixedFacets = fi.fFixedFacets; |
| } |
| |
| typeInfo.fXSSimpleType = schemaFactory.createTypeRestriction(null,schemaDoc.fTargetNamespace,(short)0,baseValidator); |
| try{ |
| fValidationState.setNamespaceSupport(schemaDoc.fNamespaceSupport); |
| typeInfo.fXSSimpleType.applyFacets(facetData, presentFacets, fixedFacets, fValidationState); |
| }catch(InvalidDatatypeFacetException ex){ |
| reportGenericSchemaError(ex.getLocalizedMessage()); |
| } |
| |
| // ----------------------------------------------------------------------- |
| // Traverse any attributes |
| // ----------------------------------------------------------------------- |
| if (attrNode != null) { |
| if (!isAttrOrAttrGroup(attrNode)) { |
| throw new ComplexTypeRecoverableError("src-ct.0.1", |
| new Object[]{typeInfo.fName,DOMUtil.getLocalName(attrNode)}); |
| } |
| Element node=traverseAttrsAndAttrGrps(attrNode,typeInfo.fAttrGrp, |
| schemaDoc,grammar); |
| if (node!=null) { |
| throw new ComplexTypeRecoverableError("src-ct.0.1", |
| new Object[]{typeInfo.fName,DOMUtil.getLocalName(node)}); |
| } |
| } |
| |
| mergeAttributes(baseComplexType.fAttrGrp, typeInfo.fAttrGrp, typeName, false); |
| // Prohibited uses must be removed after merge for RESTRICTION |
| typeInfo.fAttrGrp.removeProhibitedAttrs(); |
| |
| String errorCode=typeInfo.fAttrGrp.validRestrictionOf(baseComplexType.fAttrGrp); |
| if (errorCode != null) { |
| throw new ComplexTypeRecoverableError(errorCode, |
| new Object[]{typeInfo.fName}); |
| } |
| |
| } |
| // ----------------------------------------------------------------------- |
| // Process a EXTENSION |
| // ----------------------------------------------------------------------- |
| else { |
| typeInfo.fXSSimpleType = baseValidator; |
| if (simpleContent != null) { |
| // ----------------------------------------------------------------------- |
| // Traverse any attributes |
| // ----------------------------------------------------------------------- |
| Element attrNode = simpleContent; |
| if (!isAttrOrAttrGroup(attrNode)) { |
| throw new ComplexTypeRecoverableError("src-ct.0.1", |
| new Object[]{typeInfo.fName,DOMUtil.getLocalName(attrNode)}); |
| } |
| Element node=traverseAttrsAndAttrGrps(attrNode,typeInfo.fAttrGrp, |
| schemaDoc,grammar); |
| |
| if (node!=null) { |
| throw new ComplexTypeRecoverableError("src-ct.0.1", |
| new Object[]{typeInfo.fName,DOMUtil.getLocalName(node)}); |
| } |
| // Remove prohibited uses. Should be done prior to any merge. |
| typeInfo.fAttrGrp.removeProhibitedAttrs(); |
| |
| if (baseComplexType != null) { |
| mergeAttributes(baseComplexType.fAttrGrp, typeInfo.fAttrGrp, typeName, true); |
| } |
| } |
| } |
| |
| } |
| |
| private void traverseComplexContent(Element complexContentElement, |
| XSComplexTypeDecl typeInfo, |
| boolean mixedOnType, XSDocumentInfo schemaDoc, |
| SchemaGrammar grammar) |
| throws ComplexTypeRecoverableError { |
| |
| |
| String typeName = typeInfo.fName; |
| Object[] attrValues = fAttrChecker.checkAttributes(complexContentElement, false, |
| schemaDoc); |
| |
| |
| // ----------------------------------------------------------------------- |
| // Determine if this is mixed content |
| // ----------------------------------------------------------------------- |
| boolean mixedContent = mixedOnType; |
| Boolean mixedAtt = (Boolean) attrValues[XSAttributeChecker.ATTIDX_MIXED]; |
| if (mixedAtt != null) { |
| mixedContent = mixedAtt.booleanValue(); |
| } |
| |
| |
| // ----------------------------------------------------------------------- |
| // Since the type must have complex content, set the simple type validators |
| // to null |
| // ----------------------------------------------------------------------- |
| typeInfo.fXSSimpleType = null; |
| |
| Element complexContent = DOMUtil.getFirstChildElement(complexContentElement); |
| if (complexContent != null) { |
| // traverse annotation if any |
| if (DOMUtil.getLocalName(complexContent).equals(SchemaSymbols.ELT_ANNOTATION)) { |
| traverseAnnotationDecl(complexContent, attrValues, false, schemaDoc); |
| complexContent = DOMUtil.getNextSiblingElement(complexContent); |
| } |
| } |
| |
| fAttrChecker.returnAttrArray(attrValues, schemaDoc); |
| // If there are no children, return |
| if (complexContent==null) { |
| throw new ComplexTypeRecoverableError("src-ct.0.2", |
| new Object[]{typeName,SchemaSymbols.ELT_COMPLEXCONTENT}); |
| } |
| |
| // ----------------------------------------------------------------------- |
| // The content should be either "restriction" or "extension" |
| // ----------------------------------------------------------------------- |
| String complexContentName = DOMUtil.getLocalName(complexContent); |
| if (complexContentName.equals(SchemaSymbols.ELT_RESTRICTION)) |
| typeInfo.fDerivedBy = SchemaSymbols.RESTRICTION; |
| else if (complexContentName.equals(SchemaSymbols.ELT_EXTENSION)) |
| typeInfo.fDerivedBy = SchemaSymbols.EXTENSION; |
| else { |
| throw new ComplexTypeRecoverableError("src-ct.0.1", |
| new Object[]{typeName, complexContentName}); |
| } |
| if (DOMUtil.getNextSiblingElement(complexContent) != null) { |
| String siblingName = DOMUtil.getLocalName(DOMUtil.getNextSiblingElement(complexContent)); |
| throw new ComplexTypeRecoverableError("src-ct.0.1", |
| new Object[]{typeName, siblingName}); |
| } |
| |
| attrValues = fAttrChecker.checkAttributes(complexContent, false, |
| schemaDoc); |
| QName baseTypeName = (QName) attrValues[XSAttributeChecker.ATTIDX_BASE]; |
| fAttrChecker.returnAttrArray(attrValues, schemaDoc); |
| |
| |
| // ----------------------------------------------------------------------- |
| // Need a base type. Check that it's a complex type |
| // ----------------------------------------------------------------------- |
| if (baseTypeName==null) { |
| throw new ComplexTypeRecoverableError("src-ct.0.3", |
| new Object[]{typeName}); |
| } |
| |
| XSTypeDecl type = (XSTypeDecl)fSchemaHandler.getGlobalDecl(schemaDoc, |
| XSDHandler.TYPEDECL_TYPE, baseTypeName); |
| |
| if (type==null) |
| throw new ComplexTypeRecoverableError(); |
| |
| if (! (type instanceof XSComplexTypeDecl)) { |
| throw new ComplexTypeRecoverableError("src-ct.1", |
| new Object[]{typeName}); |
| } |
| XSComplexTypeDecl baseType = (XSComplexTypeDecl)type; |
| typeInfo.fBaseType = baseType; |
| |
| // ----------------------------------------------------------------------- |
| // Check that the base permits the derivation |
| // ----------------------------------------------------------------------- |
| if ((baseType.fFinal & typeInfo.fDerivedBy)!=0) { |
| String errorKey = (typeInfo.fDerivedBy==SchemaSymbols.EXTENSION) ? |
| "cos-ct-extends.1.1" : "derivation-ok-restriction.1"; |
| throw new ComplexTypeRecoverableError(errorKey, |
| new Object[]{typeInfo.fName}); |
| } |
| |
| // ----------------------------------------------------------------------- |
| // Skip over any potential annotations |
| // ----------------------------------------------------------------------- |
| complexContent = DOMUtil.getFirstChildElement(complexContent); |
| |
| if (complexContent != null) { |
| // traverse annotation if any |
| if (DOMUtil.getLocalName(complexContent).equals(SchemaSymbols.ELT_ANNOTATION)) { |
| traverseAnnotationDecl(complexContent, null, false, schemaDoc); |
| complexContent = DOMUtil.getNextSiblingElement(complexContent); |
| } |
| if (complexContent !=null && |
| DOMUtil.getLocalName(complexContent).equals(SchemaSymbols.ELT_ANNOTATION)){ |
| throw new ComplexTypeRecoverableError("src-ct.0.1", |
| new Object[]{typeName,SchemaSymbols.ELT_ANNOTATION}); |
| } |
| } |
| // ----------------------------------------------------------------------- |
| // Process the content. Note: should I try to catch any complexType errors |
| // here in order to return the attr array? |
| // ----------------------------------------------------------------------- |
| processComplexContent(complexContent, typeInfo, mixedContent, true, schemaDoc, |
| grammar); |
| |
| // ----------------------------------------------------------------------- |
| // Compose the final content and attribute uses |
| // ----------------------------------------------------------------------- |
| XSParticleDecl baseContent = baseType.fParticle; |
| if (typeInfo.fDerivedBy==SchemaSymbols.RESTRICTION) { |
| |
| // This is an RESTRICTION |
| |
| if (typeInfo.fParticle==null && (!(baseContent==null || |
| baseContent.emptiable()))) { |
| throw new ComplexTypeRecoverableError("derivation-ok-restriction.5.2", |
| new Object[]{typeName}); |
| } |
| if (typeInfo.fParticle!=null && baseContent==null) { |
| //REVISIT - need better error msg |
| throw new ComplexTypeRecoverableError("derivation-ok-restriction.5.3", |
| new Object[]{typeName}); |
| } |
| |
| mergeAttributes(baseType.fAttrGrp, typeInfo.fAttrGrp, typeName, false); |
| String error = typeInfo.fAttrGrp.validRestrictionOf(baseType.fAttrGrp); |
| if (error != null) { |
| throw new ComplexTypeRecoverableError(error, |
| new Object[]{typeName}); |
| } |
| |
| // Remove prohibited uses. Must be done after merge for RESTRICTION. |
| typeInfo.fAttrGrp.removeProhibitedAttrs(); |
| |
| } |
| else { |
| |
| // This is an EXTENSION |
| |
| // |
| // Check if the contentType of the base is consistent with the new type |
| // cos-ct-extends.1.4.2.2 |
| if (baseType.fContentType != XSComplexTypeDecl.CONTENTTYPE_EMPTY) { |
| if (((baseType.fContentType == |
| XSComplexTypeDecl.CONTENTTYPE_ELEMENT) && |
| mixedContent) || |
| ((baseType.fContentType == |
| XSComplexTypeDecl.CONTENTTYPE_MIXED) && !mixedContent)) { |
| |
| throw new ComplexTypeRecoverableError("cos-ct-extends.1.4.2.2.2.2.1", |
| new Object[]{typeName}); |
| } |
| |
| } |
| |
| // Create the particle |
| if (typeInfo.fParticle == null) { |
| typeInfo.fParticle = baseContent; |
| } |
| else if (baseContent==null) { |
| } |
| else { |
| if (typeInfo.fParticle.fType == XSParticleDecl.PARTICLE_ALL || |
| baseType.fParticle.fType == XSParticleDecl.PARTICLE_ALL) { |
| throw new ComplexTypeRecoverableError("cos-all-limited.1.2", |
| new Object[]{typeName}); |
| } |
| XSParticleDecl temp = new XSParticleDecl(); |
| temp.fType = XSParticleDecl.PARTICLE_SEQUENCE; |
| temp.fValue = baseContent; |
| temp.fOtherValue = typeInfo.fParticle; |
| typeInfo.fParticle = temp; |
| } |
| |
| // Set the contentType |
| if (mixedContent) |
| typeInfo.fContentType = XSComplexTypeDecl.CONTENTTYPE_MIXED; |
| else if (typeInfo.fParticle == null) |
| typeInfo.fContentType = XSComplexTypeDecl.CONTENTTYPE_EMPTY; |
| else |
| typeInfo.fContentType = XSComplexTypeDecl.CONTENTTYPE_ELEMENT; |
| |
| // Remove prohibited uses. Must be done before merge for EXTENSION. |
| typeInfo.fAttrGrp.removeProhibitedAttrs(); |
| mergeAttributes(baseType.fAttrGrp, typeInfo.fAttrGrp, typeName, true); |
| |
| } |
| |
| } // end of traverseComplexContent |
| |
| |
| // This method merges attribute uses from the base, into the derived set. |
| // The first duplicate attribute, if any, is returned. |
| // LM: may want to merge with attributeGroup processing. |
| private void mergeAttributes(XSAttributeGroupDecl fromAttrGrp, |
| XSAttributeGroupDecl toAttrGrp, |
| String typeName, |
| boolean extension) |
| throws ComplexTypeRecoverableError { |
| |
| XSAttributeUse[] attrUseS = fromAttrGrp.getAttributeUses(); |
| XSAttributeUse existingAttrUse, duplicateAttrUse = null; |
| for (int i=0; i<attrUseS.length; i++) { |
| existingAttrUse = toAttrGrp.getAttributeUse(attrUseS[i].fAttrDecl.fTargetNamespace, |
| attrUseS[i].fAttrDecl.fName); |
| if (existingAttrUse == null) { |
| String idName = toAttrGrp.addAttributeUse(attrUseS[i]); |
| if (idName != null) { |
| throw new ComplexTypeRecoverableError("ct-props-correct.5", |
| new Object[]{typeName, idName, attrUseS[i].fAttrDecl.fName}); |
| } |
| } |
| else { |
| if (extension) { |
| throw new ComplexTypeRecoverableError("ct-props-correct.4", |
| new Object[]{typeName, existingAttrUse.fAttrDecl.fName}); |
| } |
| } |
| } |
| |
| // For extension, the wildcard must be formed by doing a union of the wildcards |
| if (extension) { |
| if (toAttrGrp.fAttributeWC==null) { |
| toAttrGrp.fAttributeWC = fromAttrGrp.fAttributeWC; |
| } |
| else if (fromAttrGrp.fAttributeWC != null) { |
| toAttrGrp.fAttributeWC = toAttrGrp.fAttributeWC.performUnionWith(fromAttrGrp.fAttributeWC, toAttrGrp.fAttributeWC.fProcessContents); |
| } |
| |
| } |
| } |
| |
| |
| |
| private void processComplexContent(Element complexContentChild, |
| XSComplexTypeDecl typeInfo, |
| boolean isMixed, boolean isDerivation, |
| XSDocumentInfo schemaDoc, SchemaGrammar grammar) |
| throws ComplexTypeRecoverableError { |
| |
| Element attrNode = null; |
| XSParticleDecl particle = null; |
| String typeName = typeInfo.fName; |
| |
| if (complexContentChild != null) { |
| // ------------------------------------------------------------- |
| // GROUP, ALL, SEQUENCE or CHOICE, followed by attributes, if specified. |
| // Note that it's possible that only attributes are specified. |
| // ------------------------------------------------------------- |
| |
| |
| String childName = DOMUtil.getLocalName(complexContentChild); |
| |
| if (childName.equals(SchemaSymbols.ELT_GROUP)) { |
| |
| particle = fSchemaHandler.fGroupTraverser.traverseLocal(complexContentChild, |
| schemaDoc, grammar); |
| attrNode = DOMUtil.getNextSiblingElement(complexContentChild); |
| } |
| else if (childName.equals(SchemaSymbols.ELT_SEQUENCE)) { |
| particle = traverseSequence(complexContentChild,schemaDoc,grammar, |
| NOT_ALL_CONTEXT); |
| attrNode = DOMUtil.getNextSiblingElement(complexContentChild); |
| } |
| else if (childName.equals(SchemaSymbols.ELT_CHOICE)) { |
| particle = traverseChoice(complexContentChild,schemaDoc,grammar, |
| NOT_ALL_CONTEXT); |
| attrNode = DOMUtil.getNextSiblingElement(complexContentChild); |
| } |
| else if (childName.equals(SchemaSymbols.ELT_ALL)) { |
| particle = traverseAll(complexContentChild,schemaDoc,grammar, |
| PROCESSING_ALL_GP); |
| attrNode = DOMUtil.getNextSiblingElement(complexContentChild); |
| } |
| else { |
| // Should be attributes here - will check below... |
| attrNode = complexContentChild; |
| } |
| } |
| |
| typeInfo.fParticle = particle; |
| |
| // ----------------------------------------------------------------------- |
| // Set the content type |
| // ----------------------------------------------------------------------- |
| |
| if (isMixed) { |
| typeInfo.fContentType = XSComplexTypeDecl.CONTENTTYPE_MIXED; |
| } |
| else if (typeInfo.fParticle == null) |
| typeInfo.fContentType = XSComplexTypeDecl.CONTENTTYPE_EMPTY; |
| else |
| typeInfo.fContentType = XSComplexTypeDecl.CONTENTTYPE_ELEMENT; |
| |
| |
| // ------------------------------------------------------------- |
| // Now, process attributes |
| // ------------------------------------------------------------- |
| if (attrNode != null) { |
| if (!isAttrOrAttrGroup(attrNode)) { |
| throw new ComplexTypeRecoverableError("src-ct.0.1", |
| new Object[]{typeInfo.fName,DOMUtil.getLocalName(attrNode)}); |
| } |
| Element node = |
| traverseAttrsAndAttrGrps(attrNode,typeInfo.fAttrGrp,schemaDoc,grammar); |
| if (node!=null) { |
| throw new ComplexTypeRecoverableError("src-ct.0.1", |
| new Object[]{typeInfo.fName,DOMUtil.getLocalName(node)}); |
| } |
| // Only remove prohibited attribute uses if this isn't a derived type |
| // Derivation-specific code worries about this elsewhere |
| if (!isDerivation) { |
| typeInfo.fAttrGrp.removeProhibitedAttrs(); |
| } |
| } |
| |
| |
| |
| } // end processComplexContent |
| |
| |
| private boolean isAttrOrAttrGroup(Element e) { |
| String elementName = DOMUtil.getLocalName(e); |
| |
| if (elementName.equals(SchemaSymbols.ELT_ATTRIBUTE) || |
| elementName.equals(SchemaSymbols.ELT_ATTRIBUTEGROUP) || |
| elementName.equals(SchemaSymbols.ELT_ANYATTRIBUTE)) |
| return true; |
| else |
| return false; |
| } |
| |
| private void traverseSimpleContentDecl(Element simpleContentDecl, |
| XSComplexTypeDecl typeInfo) { |
| } |
| |
| private void traverseComplexContentDecl(Element complexContentDecl, |
| XSComplexTypeDecl typeInfo, |
| boolean mixedOnComplexTypeDecl) { |
| } |
| |
| /* |
| * Generate a name for an anonymous type |
| */ |
| private String genAnonTypeName(Element complexTypeDecl) { |
| |
| // Generate a unique name for the anonymous type by concatenating together the |
| // names of parent nodes |
| // The name is quite good for debugging/error purposes, but we may want to |
| // revisit how this is done for performance reasons (LM). |
| String typeName; |
| Element node = DOMUtil.getParent(complexTypeDecl); |
| typeName="#AnonType_"; |
| while (node != null && (node != DOMUtil.getRoot(DOMUtil.getDocument(node)))) { |
| typeName = typeName+node.getAttribute(SchemaSymbols.ATT_NAME); |
| node = DOMUtil.getParent(node); |
| } |
| return typeName; |
| } |
| |
| |
| private void handleComplexTypeError(String messageId,Object[] args, |
| XSComplexTypeDecl typeInfo) { |
| |
| if (messageId!=null) { |
| reportSchemaError(messageId, args); |
| } |
| |
| // |
| // Mock up the typeInfo structure so that there won't be problems during |
| // validation |
| // |
| typeInfo.fContentType = XSComplexTypeDecl.CONTENTTYPE_MIXED; |
| typeInfo.fParticle = getErrorContent(); |
| |
| return; |
| |
| } |
| |
| private static XSParticleDecl getErrorContent() { |
| if (fErrorContent==null) { |
| fErrorContent = new XSParticleDecl(); |
| fErrorContent.fType = XSParticleDecl.PARTICLE_SEQUENCE; |
| XSParticleDecl particle = new XSParticleDecl(); |
| XSWildcardDecl wildcard = new XSWildcardDecl(); |
| wildcard.fProcessContents = XSWildcardDecl.WILDCARD_SKIP; |
| particle.fType = XSParticleDecl.PARTICLE_WILDCARD; |
| particle.fValue = wildcard; |
| particle.fMinOccurs = 0; |
| particle.fMaxOccurs = SchemaSymbols.OCCURRENCE_UNBOUNDED; |
| fErrorContent.fValue = particle; |
| fErrorContent.fOtherValue = null; |
| } |
| return fErrorContent; |
| } |
| } |