| /* |
| * The Apache Software License, Version 1.1 |
| * |
| * |
| * Copyright (c) 2003 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 "Apache" 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 |
| * XMLBeans", 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) 2000-2003 BEA Systems |
| * Inc., <http://www.bea.com/>. For more information on the Apache Software |
| * Foundation, please see <http://www.apache.org/>. |
| */ |
| |
| package org.apache.xmlbeans.impl.schema; |
| |
| import org.apache.xmlbeans.SchemaType; |
| import org.apache.xmlbeans.XmlObject; |
| import org.apache.xmlbeans.SchemaParticle; |
| import org.apache.xmlbeans.QNameSet; |
| |
| import java.math.BigInteger; |
| |
| import java.util.*; |
| |
| import org.w3.x2001.xmlSchema.TopLevelElement; |
| import org.w3.x2001.xmlSchema.TopLevelAttribute; |
| import org.w3.x2001.xmlSchema.SimpleType; |
| import org.w3.x2001.xmlSchema.Attribute; |
| import org.w3.x2001.xmlSchema.Element; |
| import org.w3.x2001.xmlSchema.KeyrefDocument.Keyref; |
| import org.apache.xmlbeans.impl.common.XmlErrorContext; |
| import javax.xml.namespace.QName; |
| |
| public class StscResolver |
| { |
| /** |
| * Does a topo walk of all the types to resolve them. |
| */ |
| public static void resolveAll() |
| { |
| // resolve tree of types |
| StscState state = StscState.get(); |
| |
| SchemaType[] documentTypes = state.documentTypes(); |
| for (int i = 0 ; i < documentTypes.length ; i++) |
| resolveSubstitutionGroup((SchemaTypeImpl)documentTypes[i]); |
| |
| List allSeenTypes = new ArrayList(); |
| allSeenTypes.addAll(Arrays.asList(state.documentTypes())); |
| allSeenTypes.addAll(Arrays.asList(state.attributeTypes())); |
| allSeenTypes.addAll(Arrays.asList(state.redefinedGlobalTypes())); |
| allSeenTypes.addAll(Arrays.asList(state.globalTypes())); |
| |
| for (int i = 0; i < allSeenTypes.size(); i++) |
| { |
| SchemaType gType = (SchemaType)allSeenTypes.get(i); |
| resolveType((SchemaTypeImpl)gType); |
| allSeenTypes.addAll(Arrays.asList(gType.getAnonymousTypes())); |
| } |
| |
| // Resolve all keyref refs |
| resolveIdentityConstraints(); |
| } |
| |
| public static boolean resolveType(SchemaTypeImpl sImpl) |
| { |
| if (sImpl.isResolved()) |
| return true; |
| if (sImpl.isResolving()) |
| { |
| StscState.get().error("Cyclic dependency error", XmlErrorContext.CYCLIC_DEPENDENCY, sImpl.getParseObject()); |
| return false; // cyclic dependency error |
| } |
| // System.out.println("Resolving " + sImpl); |
| |
| sImpl.startResolving(); |
| |
| if (sImpl.isDocumentType()) |
| resolveDocumentType(sImpl); |
| else if (sImpl.isAttributeType()) |
| resolveAttributeType(sImpl); |
| else if (sImpl.isSimpleType()) |
| StscSimpleTypeResolver.resolveSimpleType(sImpl); |
| else |
| StscComplexTypeResolver.resolveComplexType(sImpl); |
| |
| sImpl.finishResolving(); |
| // System.out.println("Finished resolving " + sImpl); |
| return true; |
| } |
| |
| public static boolean resolveSubstitutionGroup(SchemaTypeImpl sImpl) |
| { |
| assert sImpl.isDocumentType(); |
| |
| if (sImpl.isSGResolved()) |
| return true; |
| if (sImpl.isSGResolving()) |
| { |
| StscState.get().error("Cyclic dependency error", XmlErrorContext.CYCLIC_DEPENDENCY, sImpl.getParseObject()); |
| return false; // cyclic dependency error |
| } |
| |
| sImpl.startResolvingSGs(); |
| |
| // Resolve substitution group |
| |
| TopLevelElement elt = (TopLevelElement)sImpl.getParseObject(); |
| SchemaTypeImpl substitutionGroup = null; |
| QName eltName = new QName(sImpl.getTargetNamespace(), elt.getName()); |
| |
| // BUG: How do I tell if the type is in this compilation unit? |
| if (elt.isSetSubstitutionGroup()) |
| { |
| substitutionGroup = StscState.get().findDocumentType(elt.getSubstitutionGroup(), |
| sImpl.getChameleonNamespace()); |
| |
| if (substitutionGroup == null) |
| StscState.get().notFoundError(elt.getSubstitutionGroup(), XmlErrorContext.ELEMENT_REF_NOT_FOUND, elt.xgetSubstitutionGroup()); |
| // recovery - ignore substitution group |
| else if (! resolveSubstitutionGroup(substitutionGroup) ) |
| substitutionGroup = null; |
| else |
| sImpl.setSubstitutionGroup(elt.getSubstitutionGroup()); |
| } |
| |
| // Walk up the chain of subtitution groups adding this schematype to each head's |
| // member list |
| while (substitutionGroup != null) |
| { |
| |
| substitutionGroup.addSubstitutionGroupMember(eltName); |
| |
| if (substitutionGroup.getSubstitutionGroup() == null) |
| break; |
| |
| substitutionGroup = StscState.get().findDocumentType( |
| substitutionGroup.getSubstitutionGroup(), substitutionGroup.getChameleonNamespace()); |
| |
| assert substitutionGroup != null : "Could not find document type for: " + substitutionGroup.getSubstitutionGroup(); |
| |
| if (! resolveSubstitutionGroup(substitutionGroup) ) |
| substitutionGroup = null; // cyclic dependency - no subst group |
| |
| } |
| |
| sImpl.finishResolvingSGs(); |
| return true; |
| |
| } |
| |
| public static void resolveDocumentType ( SchemaTypeImpl sImpl ) |
| { |
| assert sImpl.isResolving(); |
| |
| assert sImpl.isDocumentType(); |
| |
| |
| // translate the global element associated with this document type |
| // and construct a content model which allows just that element |
| |
| List anonTypes = new ArrayList(); |
| |
| SchemaGlobalElementImpl element = |
| (SchemaGlobalElementImpl) |
| StscTranslator.translateElement( |
| (Element) sImpl.getParseObject(), |
| sImpl.getTargetNamespace(), sImpl.isChameleon(), |
| anonTypes, sImpl ); |
| |
| SchemaLocalElementImpl contentModel = null; |
| |
| if (element != null) |
| { |
| StscState.get().addGlobalElement( element ); |
| |
| contentModel = new SchemaLocalElementImpl(); |
| |
| contentModel.setParticleType( SchemaParticle.ELEMENT ); |
| StscTranslator.copyGlobalElementToLocalElement( element, contentModel ); |
| contentModel.setMinOccurs( BigInteger.ONE ); |
| contentModel.setMaxOccurs( BigInteger.ONE ); |
| |
| contentModel.setTransitionNotes(QNameSet.EMPTY, true); |
| } |
| |
| Map elementPropertyModel = |
| StscComplexTypeResolver.buildContentPropertyModelByQName( |
| contentModel, sImpl ); |
| |
| SchemaTypeImpl baseType = sImpl.getSubstitutionGroup() == null ? |
| BuiltinSchemaTypeSystem.ST_ANY_TYPE : |
| StscState.get().findDocumentType(sImpl.getSubstitutionGroup(), |
| sImpl.isChameleon() ? sImpl.getTargetNamespace() : null) |
| ; |
| |
| sImpl.setBaseTypeRef( baseType.getRef() ); |
| sImpl.setBaseDepth( baseType.getBaseDepth() + 1 ); |
| sImpl.setDerivationType( SchemaType.DT_RESTRICTION ); |
| sImpl.setComplexTypeVariety( SchemaType.ELEMENT_CONTENT ); |
| |
| sImpl.setContentModel( |
| contentModel, new SchemaAttributeModelImpl(), |
| elementPropertyModel, Collections.EMPTY_MAP, false ); |
| |
| sImpl.setWildcardSummary( |
| QNameSet.EMPTY, false, QNameSet.EMPTY, false ); |
| |
| sImpl.setAnonymousTypeRefs( makeRefArray( anonTypes ) ); |
| |
| |
| |
| } |
| |
| public static void resolveAttributeType ( SchemaTypeImpl sImpl ) |
| { |
| assert sImpl.isResolving(); |
| |
| assert sImpl.isAttributeType(); |
| |
| List anonTypes = new ArrayList(); |
| |
| SchemaGlobalAttributeImpl attribute = |
| (SchemaGlobalAttributeImpl) StscTranslator.translateAttribute( |
| (Attribute) sImpl.getParseObject(), sImpl.getTargetNamespace(), |
| sImpl.isChameleon(), anonTypes, sImpl, null, false ); |
| |
| SchemaAttributeModelImpl attributeModel = new SchemaAttributeModelImpl(); |
| |
| if (attribute != null) |
| { |
| StscState.get().addGlobalAttribute( attribute ); |
| |
| SchemaLocalAttributeImpl attributeCopy = new SchemaLocalAttributeImpl(); |
| StscTranslator.copyGlobalAttributeToLocalAttribute( attribute, attributeCopy ); |
| attributeModel.addAttribute( attributeCopy ); |
| } |
| |
| sImpl.setBaseTypeRef( BuiltinSchemaTypeSystem.ST_ANY_TYPE.getRef() ); |
| sImpl.setBaseDepth( sImpl.getBaseDepth() + 1 ); |
| sImpl.setDerivationType( SchemaType.DT_RESTRICTION ); |
| sImpl.setComplexTypeVariety( SchemaType.EMPTY_CONTENT ); |
| |
| Map attributePropertyModel = |
| StscComplexTypeResolver.buildAttributePropertyModelByQName( |
| attributeModel, sImpl ); |
| |
| sImpl.setContentModel( |
| null, attributeModel, Collections.EMPTY_MAP, attributePropertyModel, false ); |
| |
| sImpl.setWildcardSummary( |
| QNameSet.EMPTY, false, QNameSet.EMPTY, false ); |
| |
| sImpl.setAnonymousTypeRefs( makeRefArray( anonTypes ) ); |
| } |
| |
| private static SchemaType.Ref[] makeRefArray(Collection typeList) |
| { |
| SchemaType.Ref[] result = new SchemaType.Ref[typeList.size()]; |
| int j = 0; |
| for (Iterator i = typeList.iterator(); i.hasNext(); j++) |
| result[j] = ((SchemaType)i.next()).getRef(); |
| return result; |
| } |
| |
| |
| public static void resolveIdentityConstraints() |
| { |
| StscState state = StscState.get(); |
| SchemaIdentityConstraintImpl[] idcs = state.idConstraints(); |
| |
| for (int i = 0 ; i < idcs.length ; i++) |
| { |
| if (!idcs[i].isResolved()) |
| { |
| Keyref xsdkr = (Keyref)idcs[i].getParseObject(); |
| QName keyName = xsdkr.getRefer(); |
| SchemaIdentityConstraintImpl key = null; |
| |
| key = state.findIdConstraint(keyName, idcs[i].getChameleonNamespace()); |
| if (key == null) |
| { |
| state.notFoundError(keyName, XmlErrorContext.IDC_NOT_FOUND, xsdkr); |
| } |
| else |
| { |
| if (key.getConstraintCategory() == SchemaIdentityConstraintImpl.CC_KEYREF) |
| state.error("Keyref cannot refer to another keyref.", |
| XmlErrorContext.IDC_NOT_FOUND, idcs[i].getParseObject()); |
| |
| if (key.getFields().length != idcs[i].getFields().length) |
| state.error("Keyref does not have same number of fields as key", |
| XmlErrorContext.IDC_NOT_FOUND, idcs[i].getParseObject()); |
| |
| idcs[i].setReferencedKey(key.getRef()); |
| } |
| } |
| } |
| } |
| |
| } |