/* * reserved comment block * DO NOT REMOVE OR ALTER! */ /* * Copyright 2001-2005 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.sun.org.apache.xerces.internal.impl.xs.traversers; import com.sun.org.apache.xerces.internal.impl.dv.InvalidDatatypeFacetException; import com.sun.org.apache.xerces.internal.impl.dv.SchemaDVFactory; import com.sun.org.apache.xerces.internal.impl.dv.XSFacets; import com.sun.org.apache.xerces.internal.impl.dv.XSSimpleType; import com.sun.org.apache.xerces.internal.impl.dv.xs.XSSimpleTypeDecl; import com.sun.org.apache.xerces.internal.impl.xs.SchemaGrammar; import com.sun.org.apache.xerces.internal.impl.xs.SchemaSymbols; import com.sun.org.apache.xerces.internal.impl.xs.XSAnnotationImpl; import com.sun.org.apache.xerces.internal.impl.xs.XSAttributeGroupDecl; import com.sun.org.apache.xerces.internal.impl.xs.XSAttributeUseImpl; import com.sun.org.apache.xerces.internal.impl.xs.XSComplexTypeDecl; import com.sun.org.apache.xerces.internal.impl.xs.XSConstraints; import com.sun.org.apache.xerces.internal.impl.xs.XSModelGroupImpl; import com.sun.org.apache.xerces.internal.impl.xs.XSParticleDecl; import com.sun.org.apache.xerces.internal.impl.xs.XSWildcardDecl; import com.sun.org.apache.xerces.internal.impl.xs.util.XInt; import com.sun.org.apache.xerces.internal.impl.xs.util.XSObjectListImpl; import com.sun.org.apache.xerces.internal.util.DOMUtil; import com.sun.org.apache.xerces.internal.xni.QName; import com.sun.org.apache.xerces.internal.xs.XSAttributeUse; import com.sun.org.apache.xerces.internal.xs.XSConstants; import com.sun.org.apache.xerces.internal.xs.XSObjectList; import com.sun.org.apache.xerces.internal.xs.XSTypeDefinition; import org.w3c.dom.Element; /** * A complex type definition schema component traverser. * * * Content: (annotation?, (simpleContent | complexContent | * ((group | all | choice | sequence)?, * ((attribute | attributeGroup)*, anyAttribute?)))) * * * @xerces.internal * */ class XSDComplexTypeTraverser extends XSDAbstractParticleTraverser { // size of stack to hold globals: private final static int GLOBAL_NUM = 11; private static XSParticleDecl fErrorContent = null; private static XSWildcardDecl fErrorWildcard = null; private static XSParticleDecl getErrorContent() { if (fErrorContent == null) { XSParticleDecl particle = new XSParticleDecl(); particle.fType = XSParticleDecl.PARTICLE_WILDCARD; particle.fValue = getErrorWildcard(); particle.fMinOccurs = 0; particle.fMaxOccurs = SchemaSymbols.OCCURRENCE_UNBOUNDED; XSModelGroupImpl group = new XSModelGroupImpl(); group.fCompositor = XSModelGroupImpl.MODELGROUP_SEQUENCE; group.fParticleCount = 1; group.fParticles = new XSParticleDecl[1]; group.fParticles[0] = particle; XSParticleDecl errorContent = new XSParticleDecl(); errorContent.fType = XSParticleDecl.PARTICLE_MODELGROUP; errorContent.fValue = group; fErrorContent = errorContent; } return fErrorContent; } private static XSWildcardDecl getErrorWildcard() { if (fErrorWildcard == null) { XSWildcardDecl wildcard = new XSWildcardDecl(); wildcard.fProcessContents = XSWildcardDecl.PC_SKIP; fErrorWildcard = wildcard; } return fErrorWildcard; } // globals for building XSComplexTypeDecls private String fName = null; private String fTargetNamespace = null; private short fDerivedBy = XSConstants.DERIVATION_RESTRICTION; private short fFinal = XSConstants.DERIVATION_NONE; private short fBlock = XSConstants.DERIVATION_NONE; private short fContentType = XSComplexTypeDecl.CONTENTTYPE_EMPTY; private XSTypeDefinition fBaseType = null; private XSAttributeGroupDecl fAttrGrp = null; private XSSimpleType fXSSimpleType = null; private XSParticleDecl fParticle = null; private boolean fIsAbstract = false; private XSComplexTypeDecl fComplexTypeDecl = null; private XSAnnotationImpl [] fAnnotations = null; // our own little stack to retain state when getGlobalDecls is called: private Object [] fGlobalStore = null; private int fGlobalStorePos = 0; XSDComplexTypeTraverser (XSDHandler handler, XSAttributeChecker gAttrCheck) { super(handler, gAttrCheck); } private static final boolean DEBUG=false; private static final class ComplexTypeRecoverableError extends Exception { private static final long serialVersionUID = 6802729912091130335L; Object[] errorSubstText=null; Element errorElem = null; ComplexTypeRecoverableError() { super(); } ComplexTypeRecoverableError(String msgKey, Object[] args, Element e) { super(msgKey); errorSubstText=args; errorElem = e; } } /** * 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); contentBackup(); XSComplexTypeDecl type = traverseComplexTypeDecl (complexTypeNode, complexTypeName, attrValues, schemaDoc, grammar); contentRestore(); // need to add the type to the grammar for later constraint checking grammar.addComplexTypeDecl(type, fSchemaHandler.element2Locator(complexTypeNode)); 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]; contentBackup(); XSComplexTypeDecl type = traverseComplexTypeDecl (complexTypeNode, complexTypeName, attrValues, schemaDoc, grammar); contentRestore(); // need to add the type to the grammar for later constraint checking grammar.addComplexTypeDecl(type, fSchemaHandler.element2Locator(complexTypeNode)); if (complexTypeName == null) { reportSchemaError("s4s-att-must-appear", new Object[]{SchemaSymbols.ELT_COMPLEXTYPE, SchemaSymbols.ATT_NAME}, complexTypeNode); type = null; } else { if (grammar.getGlobalTypeDecl(type.getName()) == null) { grammar.addGlobalComplexTypeDecl(type); } // also add it to extended map final String loc = fSchemaHandler.schemaDocument2SystemId(schemaDoc); final XSTypeDefinition type2 = grammar.getGlobalTypeDecl(type.getName(), loc); if (type2 == null) { grammar.addGlobalComplexTypeDecl(type, loc); } // handle duplicates if (fSchemaHandler.fTolerateDuplicates) { if (type2 != null) { if (type2 instanceof XSComplexTypeDecl) { type = (XSComplexTypeDecl) type2; } } fSchemaHandler.addGlobalTypeDecl(type); } } fAttrChecker.returnAttrArray(attrValues, schemaDoc); return type; } private XSComplexTypeDecl traverseComplexTypeDecl(Element complexTypeDecl, String complexTypeName, Object[] attrValues, XSDocumentInfo schemaDoc, SchemaGrammar grammar) { fComplexTypeDecl = new XSComplexTypeDecl(); fAttrGrp = new XSAttributeGroupDecl(); 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]; fName = complexTypeName; fComplexTypeDecl.setName(fName); fTargetNamespace = schemaDoc.fTargetNamespace; fBlock = blockAtt == null ? schemaDoc.fBlockDefault : blockAtt.shortValue(); fFinal = finalAtt == null ? schemaDoc.fFinalDefault : finalAtt.shortValue(); //discard valid Block/Final 'Default' values that are invalid for Block/Final fBlock &= (XSConstants.DERIVATION_EXTENSION | XSConstants.DERIVATION_RESTRICTION); fFinal &= (XSConstants.DERIVATION_EXTENSION | XSConstants.DERIVATION_RESTRICTION); fIsAbstract = (abstractAtt != null && abstractAtt.booleanValue()); fAnnotations = null; Element child = null; try { // --------------------------------------------------------------- // First, handle any ANNOTATION declaration and get next child // --------------------------------------------------------------- child = DOMUtil.getFirstChildElement(complexTypeDecl); if(child != null) { if (DOMUtil.getLocalName(child).equals(SchemaSymbols.ELT_ANNOTATION)) { addAnnotation(traverseAnnotationDecl(child, attrValues, false, schemaDoc)); child = DOMUtil.getNextSiblingElement(child); } else { String text = DOMUtil.getSyntheticAnnotation(complexTypeDecl); if (text != null) { addAnnotation(traverseSyntheticAnnotation(complexTypeDecl, text, attrValues, false, schemaDoc)); } } if (child !=null && DOMUtil.getLocalName(child).equals(SchemaSymbols.ELT_ANNOTATION)) { throw new ComplexTypeRecoverableError("s4s-elt-invalid-content.1", new Object[]{fName,SchemaSymbols.ELT_ANNOTATION}, child); } } else { String text = DOMUtil.getSyntheticAnnotation(complexTypeDecl); if (text != null) { addAnnotation(traverseSyntheticAnnotation(complexTypeDecl, text, attrValues, false, schemaDoc)); } } // --------------------------------------------------------------- // Process the content of the complex type definition // --------------------------------------------------------------- if (child==null) { // // EMPTY complexType with complexContent // // set the base to the anyType fBaseType = SchemaGrammar.fAnyType; fDerivedBy = XSConstants.DERIVATION_RESTRICTION; processComplexContent(child, mixedAtt.booleanValue(), false, schemaDoc, grammar); } else if (DOMUtil.getLocalName(child).equals (SchemaSymbols.ELT_SIMPLECONTENT)) { // // SIMPLE CONTENT // traverseSimpleContent(child, schemaDoc, grammar); Element elemTmp = DOMUtil.getNextSiblingElement(child); if (elemTmp != null) { String siblingName = DOMUtil.getLocalName(elemTmp); throw new ComplexTypeRecoverableError("s4s-elt-invalid-content.1", new Object[]{fName,siblingName}, elemTmp); } } else if (DOMUtil.getLocalName(child).equals (SchemaSymbols.ELT_COMPLEXCONTENT)) { traverseComplexContent(child, mixedAtt.booleanValue(), schemaDoc, grammar); Element elemTmp = DOMUtil.getNextSiblingElement(child); if (elemTmp != null) { String siblingName = DOMUtil.getLocalName(elemTmp); throw new ComplexTypeRecoverableError("s4s-elt-invalid-content.1", new Object[]{fName,siblingName}, elemTmp); } } 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 fBaseType = SchemaGrammar.fAnyType; fDerivedBy = XSConstants.DERIVATION_RESTRICTION; processComplexContent(child, mixedAtt.booleanValue(), false, schemaDoc, grammar); } } catch (ComplexTypeRecoverableError e) { handleComplexTypeError(e.getMessage(), e.errorSubstText, e.errorElem); } if (DEBUG) { System.out.println(fName); } fComplexTypeDecl.setValues(fName, fTargetNamespace, fBaseType, fDerivedBy, fFinal, fBlock, fContentType, fIsAbstract, fAttrGrp, fXSSimpleType, fParticle, new XSObjectListImpl(fAnnotations, fAnnotations == null? 0 : fAnnotations.length)); return fComplexTypeDecl; } private void traverseSimpleContent(Element simpleContentElement, XSDocumentInfo schemaDoc, SchemaGrammar grammar) throws ComplexTypeRecoverableError { Object[] simpleContentAttrValues = fAttrChecker.checkAttributes(simpleContentElement, false, schemaDoc); // ----------------------------------------------------------------------- // Set content type // ----------------------------------------------------------------------- fContentType = XSComplexTypeDecl.CONTENTTYPE_SIMPLE; fParticle = null; Element simpleContent = DOMUtil.getFirstChildElement(simpleContentElement); if (simpleContent != null && DOMUtil.getLocalName(simpleContent).equals(SchemaSymbols.ELT_ANNOTATION)) { addAnnotation(traverseAnnotationDecl(simpleContent, simpleContentAttrValues, false, schemaDoc)); simpleContent = DOMUtil.getNextSiblingElement(simpleContent); } else { String text = DOMUtil.getSyntheticAnnotation(simpleContentElement); if (text != null) { addAnnotation(traverseSyntheticAnnotation(simpleContentElement, text, simpleContentAttrValues, false, schemaDoc)); } } // If there are no children, return if (simpleContent==null) { fAttrChecker.returnAttrArray(simpleContentAttrValues, schemaDoc); throw new ComplexTypeRecoverableError("s4s-elt-invalid-content.2", new Object[]{fName,SchemaSymbols.ELT_SIMPLECONTENT}, simpleContentElement); } // ----------------------------------------------------------------------- // The content should be either "restriction" or "extension" // ----------------------------------------------------------------------- String simpleContentName = DOMUtil.getLocalName(simpleContent); if (simpleContentName.equals(SchemaSymbols.ELT_RESTRICTION)) fDerivedBy = XSConstants.DERIVATION_RESTRICTION; else if (simpleContentName.equals(SchemaSymbols.ELT_EXTENSION)) fDerivedBy = XSConstants.DERIVATION_EXTENSION; else { fAttrChecker.returnAttrArray(simpleContentAttrValues, schemaDoc); throw new ComplexTypeRecoverableError("s4s-elt-invalid-content.1", new Object[]{fName,simpleContentName}, simpleContent); } Element elemTmp = DOMUtil.getNextSiblingElement(simpleContent); if (elemTmp != null) { fAttrChecker.returnAttrArray(simpleContentAttrValues, schemaDoc); String siblingName = DOMUtil.getLocalName(elemTmp); throw new ComplexTypeRecoverableError("s4s-elt-invalid-content.1", new Object[]{fName,siblingName}, elemTmp); } Object [] derivationTypeAttrValues = fAttrChecker.checkAttributes(simpleContent, false, schemaDoc); QName baseTypeName = (QName) derivationTypeAttrValues[XSAttributeChecker.ATTIDX_BASE]; // ----------------------------------------------------------------------- // Need a base type. // ----------------------------------------------------------------------- if (baseTypeName==null) { fAttrChecker.returnAttrArray(simpleContentAttrValues, schemaDoc); fAttrChecker.returnAttrArray(derivationTypeAttrValues, schemaDoc); throw new ComplexTypeRecoverableError("s4s-att-must-appear", new Object[]{simpleContentName, "base"}, simpleContent); } XSTypeDefinition type = (XSTypeDefinition)fSchemaHandler.getGlobalDecl(schemaDoc, XSDHandler.TYPEDECL_TYPE, baseTypeName, simpleContent); if (type==null) { fAttrChecker.returnAttrArray(simpleContentAttrValues, schemaDoc); fAttrChecker.returnAttrArray(derivationTypeAttrValues, schemaDoc); throw new ComplexTypeRecoverableError(); } fBaseType = type; XSSimpleType baseValidator = null; XSComplexTypeDecl baseComplexType = null; int baseFinalSet = 0; // If the base type is complex, it must have simpleContent if ((type.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE)) { baseComplexType = (XSComplexTypeDecl)type; baseFinalSet = baseComplexType.getFinal(); // base is a CT with simple content (both restriction and extension are OK) if (baseComplexType.getContentType() == XSComplexTypeDecl.CONTENTTYPE_SIMPLE) { baseValidator = (XSSimpleType)baseComplexType.getSimpleType(); } // base is a CT with mixed/emptiable content (only restriction is OK) else if (fDerivedBy == XSConstants.DERIVATION_RESTRICTION && baseComplexType.getContentType() == XSComplexTypeDecl.CONTENTTYPE_MIXED && ((XSParticleDecl)baseComplexType.getParticle()).emptiable()) { } else { fAttrChecker.returnAttrArray(simpleContentAttrValues, schemaDoc); fAttrChecker.returnAttrArray(derivationTypeAttrValues, schemaDoc); throw new ComplexTypeRecoverableError("src-ct.2.1", new Object[]{fName, baseComplexType.getName()}, simpleContent); } } else { baseValidator = (XSSimpleType)type; // base is a ST (only extension is OK) if (fDerivedBy == XSConstants.DERIVATION_RESTRICTION) { fAttrChecker.returnAttrArray(simpleContentAttrValues, schemaDoc); fAttrChecker.returnAttrArray(derivationTypeAttrValues, schemaDoc); throw new ComplexTypeRecoverableError("src-ct.2.1", new Object[]{fName, baseValidator.getName()}, simpleContent); } baseFinalSet=baseValidator.getFinal(); } // ----------------------------------------------------------------------- // Check that the base permits the derivation // ----------------------------------------------------------------------- if ((baseFinalSet & fDerivedBy)!=0) { fAttrChecker.returnAttrArray(simpleContentAttrValues, schemaDoc); fAttrChecker.returnAttrArray(derivationTypeAttrValues, schemaDoc); String errorKey = (fDerivedBy==XSConstants.DERIVATION_EXTENSION) ? "cos-ct-extends.1.1" : "derivation-ok-restriction.1"; throw new ComplexTypeRecoverableError(errorKey, new Object[]{fName, fBaseType.getName()}, simpleContent); } // ----------------------------------------------------------------------- // Skip over any potential annotations // ----------------------------------------------------------------------- Element scElement = simpleContent; simpleContent = DOMUtil.getFirstChildElement(simpleContent); if (simpleContent != null) { // traverse annotation if any if (DOMUtil.getLocalName(simpleContent).equals(SchemaSymbols.ELT_ANNOTATION)) { addAnnotation(traverseAnnotationDecl(simpleContent, derivationTypeAttrValues, false, schemaDoc)); simpleContent = DOMUtil.getNextSiblingElement(simpleContent); } else { String text = DOMUtil.getSyntheticAnnotation(scElement); if (text != null) { addAnnotation(traverseSyntheticAnnotation(scElement, text, derivationTypeAttrValues, false, schemaDoc)); } } if (simpleContent !=null && DOMUtil.getLocalName(simpleContent).equals(SchemaSymbols.ELT_ANNOTATION)){ fAttrChecker.returnAttrArray(simpleContentAttrValues, schemaDoc); fAttrChecker.returnAttrArray(derivationTypeAttrValues, schemaDoc); throw new ComplexTypeRecoverableError("s4s-elt-invalid-content.1", new Object[]{fName,SchemaSymbols.ELT_ANNOTATION}, simpleContent); } } else { String text = DOMUtil.getSyntheticAnnotation(scElement); if (text != null) { addAnnotation(traverseSyntheticAnnotation(scElement, text, derivationTypeAttrValues, false, schemaDoc)); } } // ----------------------------------------------------------------------- // Process a RESTRICTION // ----------------------------------------------------------------------- if (fDerivedBy == XSConstants.DERIVATION_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) { fAttrChecker.returnAttrArray(simpleContentAttrValues, schemaDoc); fAttrChecker.returnAttrArray(derivationTypeAttrValues, schemaDoc); throw new ComplexTypeRecoverableError(); } //check that this datatype validator is validly derived from the base //according to derivation-ok-restriction 5.1.2.1 if (baseValidator != null && !XSConstraints.checkSimpleDerivationOk(dv, baseValidator, baseValidator.getFinal())) { fAttrChecker.returnAttrArray(simpleContentAttrValues, schemaDoc); fAttrChecker.returnAttrArray(derivationTypeAttrValues, schemaDoc); throw new ComplexTypeRecoverableError("derivation-ok-restriction.5.2.2.1", new Object[]{fName, dv.getName(), baseValidator.getName()}, simpleContent); } baseValidator = dv; simpleContent = DOMUtil.getNextSiblingElement(simpleContent); } // this only happens when restricting a mixed/emptiable CT // but there is no , which is required if (baseValidator == null) { fAttrChecker.returnAttrArray(simpleContentAttrValues, schemaDoc); fAttrChecker.returnAttrArray(derivationTypeAttrValues, schemaDoc); throw new ComplexTypeRecoverableError("src-ct.2.2", new Object[]{fName}, simpleContent); } // ----------------------------------------------------------------------- // Traverse any facets // ----------------------------------------------------------------------- Element attrNode = null; XSFacets facetData = null; short presentFacets = 0 ; short fixedFacets = 0 ; if (simpleContent!=null) { FacetInfo fi = traverseFacets(simpleContent, baseValidator, schemaDoc); attrNode = fi.nodeAfterFacets; facetData = fi.facetdata; presentFacets = fi.fPresentFacets; fixedFacets = fi.fFixedFacets; } String name = genAnonTypeName(simpleContentElement); fXSSimpleType = fSchemaHandler.fDVFactory.createTypeRestriction(name,schemaDoc.fTargetNamespace,(short)0,baseValidator,null); try{ fValidationState.setNamespaceSupport(schemaDoc.fNamespaceSupport); fXSSimpleType.applyFacets(facetData, presentFacets, fixedFacets, fValidationState); }catch(InvalidDatatypeFacetException ex){ reportSchemaError(ex.getKey(), ex.getArgs(), simpleContent); // Recreate the type, ignoring the facets fXSSimpleType = fSchemaHandler.fDVFactory.createTypeRestriction(name,schemaDoc.fTargetNamespace,(short)0,baseValidator,null); } if (fXSSimpleType instanceof XSSimpleTypeDecl) { ((XSSimpleTypeDecl)fXSSimpleType).setAnonymous(true); } // ----------------------------------------------------------------------- // Traverse any attributes // ----------------------------------------------------------------------- if (attrNode != null) { if (!isAttrOrAttrGroup(attrNode)) { fAttrChecker.returnAttrArray(simpleContentAttrValues, schemaDoc); fAttrChecker.returnAttrArray(derivationTypeAttrValues, schemaDoc); throw new ComplexTypeRecoverableError("s4s-elt-invalid-content.1", new Object[]{fName,DOMUtil.getLocalName(attrNode)}, attrNode); } Element node=traverseAttrsAndAttrGrps(attrNode,fAttrGrp, schemaDoc,grammar,fComplexTypeDecl); if (node!=null) { fAttrChecker.returnAttrArray(simpleContentAttrValues, schemaDoc); fAttrChecker.returnAttrArray(derivationTypeAttrValues, schemaDoc); throw new ComplexTypeRecoverableError("s4s-elt-invalid-content.1", new Object[]{fName,DOMUtil.getLocalName(node)}, node); } } try { mergeAttributes(baseComplexType.getAttrGrp(), fAttrGrp, fName, false, simpleContentElement); } catch (ComplexTypeRecoverableError e) { fAttrChecker.returnAttrArray(simpleContentAttrValues, schemaDoc); fAttrChecker.returnAttrArray(derivationTypeAttrValues, schemaDoc); throw e; } // Prohibited uses must be removed after merge for RESTRICTION fAttrGrp.removeProhibitedAttrs(); Object[] errArgs=fAttrGrp.validRestrictionOf(fName, baseComplexType.getAttrGrp()); if (errArgs != null) { fAttrChecker.returnAttrArray(simpleContentAttrValues, schemaDoc); fAttrChecker.returnAttrArray(derivationTypeAttrValues, schemaDoc); throw new ComplexTypeRecoverableError((String)errArgs[errArgs.length-1], errArgs, attrNode); } } // ----------------------------------------------------------------------- // Process a EXTENSION // ----------------------------------------------------------------------- else { fXSSimpleType = baseValidator; if (simpleContent != null) { // ----------------------------------------------------------------------- // Traverse any attributes // ----------------------------------------------------------------------- Element attrNode = simpleContent; if (!isAttrOrAttrGroup(attrNode)) { fAttrChecker.returnAttrArray(simpleContentAttrValues, schemaDoc); fAttrChecker.returnAttrArray(derivationTypeAttrValues, schemaDoc); throw new ComplexTypeRecoverableError("s4s-elt-invalid-content.1", new Object[]{fName,DOMUtil.getLocalName(attrNode)}, attrNode); } Element node=traverseAttrsAndAttrGrps(attrNode,fAttrGrp, schemaDoc,grammar,fComplexTypeDecl); if (node!=null) { fAttrChecker.returnAttrArray(simpleContentAttrValues, schemaDoc); fAttrChecker.returnAttrArray(derivationTypeAttrValues, schemaDoc); throw new ComplexTypeRecoverableError("s4s-elt-invalid-content.1", new Object[]{fName,DOMUtil.getLocalName(node)}, node); } // Remove prohibited uses. Should be done prior to any merge. fAttrGrp.removeProhibitedAttrs(); } if (baseComplexType != null) { try { mergeAttributes(baseComplexType.getAttrGrp(), fAttrGrp, fName, true, simpleContentElement); } catch (ComplexTypeRecoverableError e) { fAttrChecker.returnAttrArray(simpleContentAttrValues, schemaDoc); fAttrChecker.returnAttrArray(derivationTypeAttrValues, schemaDoc); throw e; } } } // and finally, since we've nothing more to traverse, we can // return the attributes (and thereby reset the namespace support) fAttrChecker.returnAttrArray(simpleContentAttrValues, schemaDoc); fAttrChecker.returnAttrArray(derivationTypeAttrValues, schemaDoc); } private void traverseComplexContent(Element complexContentElement, boolean mixedOnType, XSDocumentInfo schemaDoc, SchemaGrammar grammar) throws ComplexTypeRecoverableError { Object[] complexContentAttrValues = fAttrChecker.checkAttributes(complexContentElement, false, schemaDoc); // ----------------------------------------------------------------------- // Determine if this is mixed content // ----------------------------------------------------------------------- boolean mixedContent = mixedOnType; Boolean mixedAtt = (Boolean) complexContentAttrValues[XSAttributeChecker.ATTIDX_MIXED]; if (mixedAtt != null) { mixedContent = mixedAtt.booleanValue(); } // ----------------------------------------------------------------------- // Since the type must have complex content, set the simple type validators // to null // ----------------------------------------------------------------------- fXSSimpleType = null; Element complexContent = DOMUtil.getFirstChildElement(complexContentElement); if (complexContent != null && DOMUtil.getLocalName(complexContent).equals(SchemaSymbols.ELT_ANNOTATION)) { addAnnotation(traverseAnnotationDecl(complexContent, complexContentAttrValues, false, schemaDoc)); complexContent = DOMUtil.getNextSiblingElement(complexContent); } else { String text = DOMUtil.getSyntheticAnnotation(complexContentElement); if (text != null) { addAnnotation(traverseSyntheticAnnotation(complexContentElement, text, complexContentAttrValues, false, schemaDoc)); } } // If there are no children, return if (complexContent==null) { fAttrChecker.returnAttrArray(complexContentAttrValues, schemaDoc); throw new ComplexTypeRecoverableError("s4s-elt-invalid-content.2", new Object[]{fName,SchemaSymbols.ELT_COMPLEXCONTENT}, complexContentElement); } // ----------------------------------------------------------------------- // The content should be either "restriction" or "extension" // ----------------------------------------------------------------------- String complexContentName = DOMUtil.getLocalName(complexContent); if (complexContentName.equals(SchemaSymbols.ELT_RESTRICTION)) fDerivedBy = XSConstants.DERIVATION_RESTRICTION; else if (complexContentName.equals(SchemaSymbols.ELT_EXTENSION)) fDerivedBy = XSConstants.DERIVATION_EXTENSION; else { fAttrChecker.returnAttrArray(complexContentAttrValues, schemaDoc); throw new ComplexTypeRecoverableError("s4s-elt-invalid-content.1", new Object[]{fName, complexContentName}, complexContent); } Element elemTmp = DOMUtil.getNextSiblingElement(complexContent); if (elemTmp != null) { fAttrChecker.returnAttrArray(complexContentAttrValues, schemaDoc); String siblingName = DOMUtil.getLocalName(elemTmp); throw new ComplexTypeRecoverableError("s4s-elt-invalid-content.1", new Object[]{fName, siblingName}, elemTmp); } Object[] derivationTypeAttrValues = fAttrChecker.checkAttributes(complexContent, false, schemaDoc); QName baseTypeName = (QName) derivationTypeAttrValues[XSAttributeChecker.ATTIDX_BASE]; // ----------------------------------------------------------------------- // Need a base type. Check that it's a complex type // ----------------------------------------------------------------------- if (baseTypeName==null) { fAttrChecker.returnAttrArray(complexContentAttrValues, schemaDoc); fAttrChecker.returnAttrArray(derivationTypeAttrValues, schemaDoc); throw new ComplexTypeRecoverableError("s4s-att-must-appear", new Object[]{complexContentName, "base"}, complexContent); } XSTypeDefinition type = (XSTypeDefinition)fSchemaHandler.getGlobalDecl(schemaDoc, XSDHandler.TYPEDECL_TYPE, baseTypeName, complexContent); if (type==null) { fAttrChecker.returnAttrArray(complexContentAttrValues, schemaDoc); fAttrChecker.returnAttrArray(derivationTypeAttrValues, schemaDoc); throw new ComplexTypeRecoverableError(); } if (! (type instanceof XSComplexTypeDecl)) { fAttrChecker.returnAttrArray(complexContentAttrValues, schemaDoc); fAttrChecker.returnAttrArray(derivationTypeAttrValues, schemaDoc); throw new ComplexTypeRecoverableError("src-ct.1", new Object[]{fName, type.getName()}, complexContent); } XSComplexTypeDecl baseType = (XSComplexTypeDecl)type; fBaseType = baseType; // ----------------------------------------------------------------------- // Check that the base permits the derivation // ----------------------------------------------------------------------- if ((baseType.getFinal() & fDerivedBy)!=0) { fAttrChecker.returnAttrArray(complexContentAttrValues, schemaDoc); fAttrChecker.returnAttrArray(derivationTypeAttrValues, schemaDoc); String errorKey = (fDerivedBy==XSConstants.DERIVATION_EXTENSION) ? "cos-ct-extends.1.1" : "derivation-ok-restriction.1"; throw new ComplexTypeRecoverableError(errorKey, new Object[]{fName, fBaseType.getName()}, complexContent); } // ----------------------------------------------------------------------- // Skip over any potential annotations // ----------------------------------------------------------------------- complexContent = DOMUtil.getFirstChildElement(complexContent); if (complexContent != null) { // traverse annotation if any if (DOMUtil.getLocalName(complexContent).equals(SchemaSymbols.ELT_ANNOTATION)) { addAnnotation(traverseAnnotationDecl(complexContent, derivationTypeAttrValues, false, schemaDoc)); complexContent = DOMUtil.getNextSiblingElement(complexContent); } else { String text = DOMUtil.getSyntheticAnnotation(complexContent); if (text != null) { addAnnotation(traverseSyntheticAnnotation(complexContent, text, derivationTypeAttrValues, false, schemaDoc)); } } if (complexContent !=null && DOMUtil.getLocalName(complexContent).equals(SchemaSymbols.ELT_ANNOTATION)){ fAttrChecker.returnAttrArray(complexContentAttrValues, schemaDoc); fAttrChecker.returnAttrArray(derivationTypeAttrValues, schemaDoc); throw new ComplexTypeRecoverableError("s4s-elt-invalid-content.1", new Object[]{fName,SchemaSymbols.ELT_ANNOTATION}, complexContent); } } else { String text = DOMUtil.getSyntheticAnnotation(complexContent); if (text != null) { addAnnotation(traverseSyntheticAnnotation(complexContent, text, derivationTypeAttrValues, false, schemaDoc)); } } // ----------------------------------------------------------------------- // Process the content. Note: should I try to catch any complexType errors // here in order to return the attr array? // ----------------------------------------------------------------------- try { processComplexContent(complexContent, mixedContent, true, schemaDoc, grammar); } catch (ComplexTypeRecoverableError e) { fAttrChecker.returnAttrArray(complexContentAttrValues, schemaDoc); fAttrChecker.returnAttrArray(derivationTypeAttrValues, schemaDoc); throw e; } // ----------------------------------------------------------------------- // Compose the final content and attribute uses // ----------------------------------------------------------------------- XSParticleDecl baseContent = (XSParticleDecl)baseType.getParticle(); if (fDerivedBy==XSConstants.DERIVATION_RESTRICTION) { // This is an RESTRICTION // N.B. derivation-ok-restriction.5.3 is checked under schema // full checking. That's because we need to wait until locals are // traversed so that occurrence information is correct. if (fContentType == XSComplexTypeDecl.CONTENTTYPE_MIXED && baseType.getContentType() != XSComplexTypeDecl.CONTENTTYPE_MIXED) { fAttrChecker.returnAttrArray(complexContentAttrValues, schemaDoc); fAttrChecker.returnAttrArray(derivationTypeAttrValues, schemaDoc); throw new ComplexTypeRecoverableError("derivation-ok-restriction.5.4.1.2", new Object[]{fName, baseType.getName()}, complexContent); } try { mergeAttributes(baseType.getAttrGrp(), fAttrGrp, fName, false, complexContent); } catch (ComplexTypeRecoverableError e) { fAttrChecker.returnAttrArray(complexContentAttrValues, schemaDoc); fAttrChecker.returnAttrArray(derivationTypeAttrValues, schemaDoc); throw e; } // Remove prohibited uses. Must be done after merge for RESTRICTION. fAttrGrp.removeProhibitedAttrs(); if (baseType != SchemaGrammar.fAnyType) { Object[] errArgs = fAttrGrp.validRestrictionOf(fName, baseType.getAttrGrp()); if (errArgs != null) { fAttrChecker.returnAttrArray(complexContentAttrValues, schemaDoc); fAttrChecker.returnAttrArray(derivationTypeAttrValues, schemaDoc); throw new ComplexTypeRecoverableError((String)errArgs[errArgs.length-1], errArgs, complexContent); } } } else { // This is an EXTENSION // Create the particle if (fParticle == null) { fContentType = baseType.getContentType(); fXSSimpleType = (XSSimpleType)baseType.getSimpleType(); fParticle = baseContent; } else if (baseType.getContentType() == XSComplexTypeDecl.CONTENTTYPE_EMPTY) { } else { // // Check if the contentType of the base is consistent with the new type // cos-ct-extends.1.4.3.2 if (fContentType == XSComplexTypeDecl.CONTENTTYPE_ELEMENT && baseType.getContentType() != XSComplexTypeDecl.CONTENTTYPE_ELEMENT) { fAttrChecker.returnAttrArray(complexContentAttrValues, schemaDoc); fAttrChecker.returnAttrArray(derivationTypeAttrValues, schemaDoc); throw new ComplexTypeRecoverableError("cos-ct-extends.1.4.3.2.2.1.a", new Object[]{fName}, complexContent); } else if (fContentType == XSComplexTypeDecl.CONTENTTYPE_MIXED && baseType.getContentType() != XSComplexTypeDecl.CONTENTTYPE_MIXED) { fAttrChecker.returnAttrArray(complexContentAttrValues, schemaDoc); fAttrChecker.returnAttrArray(derivationTypeAttrValues, schemaDoc); throw new ComplexTypeRecoverableError("cos-ct-extends.1.4.3.2.2.1.b", new Object[]{fName}, complexContent); } // if the content of either type is an "all" model group, error. if (fParticle.fType == XSParticleDecl.PARTICLE_MODELGROUP && ((XSModelGroupImpl)fParticle.fValue).fCompositor == XSModelGroupImpl.MODELGROUP_ALL || ((XSParticleDecl)baseType.getParticle()).fType == XSParticleDecl.PARTICLE_MODELGROUP && ((XSModelGroupImpl)(((XSParticleDecl)baseType.getParticle())).fValue).fCompositor == XSModelGroupImpl.MODELGROUP_ALL) { fAttrChecker.returnAttrArray(complexContentAttrValues, schemaDoc); fAttrChecker.returnAttrArray(derivationTypeAttrValues, schemaDoc); throw new ComplexTypeRecoverableError("cos-all-limited.1.2", new Object[]{}, complexContent); } // the "sequence" model group to contain both particles XSModelGroupImpl group = new XSModelGroupImpl(); group.fCompositor = XSModelGroupImpl.MODELGROUP_SEQUENCE; group.fParticleCount = 2; group.fParticles = new XSParticleDecl[2]; group.fParticles[0] = (XSParticleDecl)baseType.getParticle(); group.fParticles[1] = fParticle; group.fAnnotations = XSObjectListImpl.EMPTY_LIST; // the particle to contain the above sequence XSParticleDecl particle = new XSParticleDecl(); particle.fType = XSParticleDecl.PARTICLE_MODELGROUP; particle.fValue = group; particle.fAnnotations = XSObjectListImpl.EMPTY_LIST; fParticle = particle; } // Remove prohibited uses. Must be done before merge for EXTENSION. fAttrGrp.removeProhibitedAttrs(); try { mergeAttributes(baseType.getAttrGrp(), fAttrGrp, fName, true, complexContent); } catch (ComplexTypeRecoverableError e) { fAttrChecker.returnAttrArray(complexContentAttrValues, schemaDoc); fAttrChecker.returnAttrArray(derivationTypeAttrValues, schemaDoc); throw e; } } // and *finally* we can legitimately return the attributes! fAttrChecker.returnAttrArray(complexContentAttrValues, schemaDoc); fAttrChecker.returnAttrArray(derivationTypeAttrValues, schemaDoc); } // end of traverseComplexContent // This method merges attribute uses from the base, into the derived set. // LM: may want to merge with attributeGroup processing. private void mergeAttributes(XSAttributeGroupDecl fromAttrGrp, XSAttributeGroupDecl toAttrGrp, String typeName, boolean extension, Element elem) throws ComplexTypeRecoverableError { XSObjectList attrUseS = fromAttrGrp.getAttributeUses(); XSAttributeUseImpl oneAttrUse = null; int attrCount = attrUseS.getLength(); for (int i=0; i> 16); fContentType = (short)i; i = ((Integer)(fGlobalStore[--fGlobalStorePos])).intValue(); fDerivedBy = (short)(i >> 16); fFinal = (short)i; fTargetNamespace = (String)fGlobalStore[--fGlobalStorePos]; fName = (String)fGlobalStore[--fGlobalStorePos]; fIsAbstract = ((Boolean)fGlobalStore[--fGlobalStorePos]).booleanValue(); fComplexTypeDecl = (XSComplexTypeDecl)fGlobalStore[--fGlobalStorePos]; } private void addAnnotation(XSAnnotationImpl annotation) { if(annotation == null) return; // it isn't very likely that there will be more than one annotation // in a complexType decl. This saves us fromhaving to push/pop // one more object from the fGlobalStore, and that's bound // to be a savings for most applications if(fAnnotations == null) { fAnnotations = new XSAnnotationImpl[1]; } else { XSAnnotationImpl [] tempArray = new XSAnnotationImpl[fAnnotations.length + 1]; System.arraycopy(fAnnotations, 0, tempArray, 0, fAnnotations.length); fAnnotations = tempArray; } fAnnotations[fAnnotations.length-1] = annotation; } }