/* * Copyright 2007 Werner Guttmann * * 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 org.exolab.castor.builder.binding; import org.exolab.castor.xml.schema.AttributeDecl; import org.exolab.castor.xml.schema.ComplexType; import org.exolab.castor.xml.schema.ElementDecl; import org.exolab.castor.xml.schema.Group; import org.exolab.castor.xml.schema.ModelGroup; import org.exolab.castor.xml.schema.Schema; import org.exolab.castor.xml.schema.SimpleType; import org.exolab.castor.xml.schema.Structure; /** * Helper class to assemble an XPATH expression to qualify the path of * an XML schema structure from the XML schema root. * @author <a href="mailto:werner DOT guttmann AT gmx DOT net">Werner Guttmann</a> * @since 1.1 */ public class XPathHelper { /** * Initial size of the {@link StringBuffer} used to asseble the XPATH * expression. */ private static final int INITIAL_XPATH_SIZE = 50; /** * Deduces an XPATH expression qualifying the path from the schema root * to the given structure in question. * @param structure AN XML structure. * @param location The XPATH expression to be created. */ public static void getSchemaLocation( final Structure structure, final StringBuffer location) { getSchemaLocation(structure, location, false); } /** * Deduces an XPATH expression qualifying the path from the schema root to * the given structure in question. * * @param structure * AN XML structure. * @param location * The XPATH expression to be created. * @param dealWithAnonTypes * Indicates whether to include XPATH fragments for anonymous * types. */ public static void getSchemaLocation( final Structure structure, final StringBuffer location, final boolean dealWithAnonTypes) { if (structure == null) { throw new IllegalArgumentException("Structure cannot be null"); } if (location == null) { throw new IllegalArgumentException("location cannot be null"); } Structure parent = null; switch (structure.getStructureType()) { case Structure.ELEMENT: parent = ((ElementDecl) structure).getParent(); if (parent.getStructureType() != Structure.SCHEMA) { getSchemaLocation(parent, location, dealWithAnonTypes); } location.append(ExtendedBinding.PATH_SEPARATOR); location.append(((ElementDecl) structure).getName()); if (parent instanceof Schema) { Schema schema = (Schema) parent; if (schema.getTargetNamespace() != null) { String targetNamespace = schema.getTargetNamespace(); location.append("{" + targetNamespace + "}"); } } break; case Structure.COMPLEX_TYPE: ComplexType complexType = (ComplexType) structure; parent = (complexType).getParent(); if (parent.getStructureType() != Structure.SCHEMA) { getSchemaLocation(parent, location, dealWithAnonTypes); } if (complexType.getName() != null) { location.append(ExtendedBinding.PATH_SEPARATOR); location.append(ExtendedBinding.COMPLEXTYPE_ID); location.append(((ComplexType) structure).getName()); } // else if (dealWithAnonTypes){ // location.append(ExtendedBinding.PATH_SEPARATOR); // location.append(ExtendedBinding.COMPLEXTYPE_ID); // location.append("anonymous"); // } break; case Structure.SIMPLE_TYPE: SimpleType simpleType = (SimpleType) structure; parent = simpleType.getParent(); if (parent != null && parent.getStructureType() != Structure.SCHEMA) { getSchemaLocation(parent, location, dealWithAnonTypes); } if (parent != null && simpleType.getName() != null) { location.append(ExtendedBinding.PATH_SEPARATOR); location.append(ExtendedBinding.ENUMTYPE_ID); location.append(((SimpleType) structure).getName()); } // else if (dealWithAnonTypes){ // location.append(ExtendedBinding.PATH_SEPARATOR); // location.append(ExtendedBinding.ENUMTYPE_ID); // location.append("anonymous"); // } break; case Structure.MODELGROUP: ModelGroup group = (ModelGroup) structure; parent = group.getParent(); if (parent.getStructureType() != Structure.SCHEMA) { getSchemaLocation(parent, location, dealWithAnonTypes); } if (group.getName() != null) { location.append(ExtendedBinding.PATH_SEPARATOR); location.append(ExtendedBinding.GROUP_ID); location.append(group.getName()); } break; case Structure.ATTRIBUTE: parent = ((AttributeDecl) structure).getParent(); if (parent.getStructureType() != Structure.SCHEMA) { getSchemaLocation(parent, location, dealWithAnonTypes); } location.append(ExtendedBinding.PATH_SEPARATOR); location.append(ExtendedBinding.ATTRIBUTE_PREFIX); location.append(((AttributeDecl) structure).getName()); break; case Structure.GROUP: // --we are inside a complexType getSchemaLocation(((Group) structure).getParent(), location, dealWithAnonTypes); break; // case Structure.ATTRIBUTE_GROUP: // //handle the real location default: break; } } /** * Returns a string (XPATH) representation of an XML Schema component. This * representation is directly adapted from XPath and will used as a key to * store the component bindings. * <p> * The location of a structure is composed of two parts: * <ol> * <li>the location of the parent structure</li> * <li>the local location of the structure itself</li> * </ol> * <p> * The local location is defined by: * <ul> * <li>If the structure is an <b>Element</b>: the location is the XPath * representation "/element_name"</li> * <li>If the structure is an <b>Attribute</b>: the location is the XPath * representation "/@attribute_name"</li> * <li>If the structure is a <b>ComplexType</b>: the location is * "complexType:complexType_name"</li> * <li>If the structure is a <b>SimpleType</b>: the location is * "simpleType:simpleType_name"</li> * <li>If the structure is a <b>Enumeration</b>: the location is * "enumType:enumType_name"</li> * <li>If the structure is a <b>ModelGroup</b>: the location is * "group:group_name"</li> * </ul> * Note that only top-level groups and complexTypes are named and thus will * * @param structure the structure for which to return a representation. * @param dealWithAnonTypes * Indicates whether to include XPATH fragments for anonymous * types. * @return a string representation of an XML Schema component. */ public static String getSchemaLocation(final Structure structure, final boolean dealWithAnonTypes) { if (structure == null) { return null; } StringBuffer buffer = new StringBuffer(INITIAL_XPATH_SIZE); getSchemaLocation(structure, buffer, dealWithAnonTypes); return buffer.toString(); } /** * Returns a string (XPATH) representation of an XML Schema component. This * representation is directly adapted from XPath and will used as a key to * store the component bindings. * @param structure the structure for which to return a representation * @return a string representation of the XPATH identifying an XML Schema component * @see #getSchemaLocation(Structure, boolean) */ public static String getSchemaLocation(final Structure structure) { if (structure == null) { return null; } StringBuffer buffer = new StringBuffer(INITIAL_XPATH_SIZE); getSchemaLocation(structure, buffer, false); return buffer.toString(); } }