001: /*
002: * Copyright 2007 Werner Guttmann
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.exolab.castor.builder.binding;
017:
018: import org.exolab.castor.xml.schema.AttributeDecl;
019: import org.exolab.castor.xml.schema.ComplexType;
020: import org.exolab.castor.xml.schema.ElementDecl;
021: import org.exolab.castor.xml.schema.Group;
022: import org.exolab.castor.xml.schema.ModelGroup;
023: import org.exolab.castor.xml.schema.SimpleType;
024: import org.exolab.castor.xml.schema.Structure;
025:
026: /**
027: * Helper class to assemble an XPATH expression to qualify the path of
028: * an XML schema structure from the XML schema root.
029: * @author <a href="mailto:werner DOT guttmann AT gmx DOT net">Werner Guttmann</a>
030: * @since 1.1
031: */
032: public class XPathHelper {
033:
034: /**
035: * Initial size of the {@link StringBuffer} used to asseble the XPATH
036: * expression.
037: */
038: private static final int INITIAL_XPATH_SIZE = 50;
039:
040: /**
041: * Deduces an XPATH expression qualifying the path from the schema root
042: * to the given structure in question.
043: * @param structure AN XML structure.
044: * @param location The XPATH expression to be created.
045: */
046: public static void getSchemaLocation(final Structure structure,
047: final StringBuffer location) {
048: getSchemaLocation(structure, location, false);
049: }
050:
051: /**
052: * Deduces an XPATH expression qualifying the path from the schema root to
053: * the given structure in question.
054: *
055: * @param structure
056: * AN XML structure.
057: * @param location
058: * The XPATH expression to be created.
059: * @param dealWithAnonTypes
060: * Indicates whether to include XPATH fragments for anonymous
061: * types.
062: */
063: public static void getSchemaLocation(final Structure structure,
064: final StringBuffer location, final boolean dealWithAnonTypes) {
065: if (structure == null) {
066: throw new IllegalArgumentException(
067: "Structure cannot be null");
068: }
069:
070: if (location == null) {
071: throw new IllegalArgumentException(
072: "location cannot be null");
073: }
074:
075: Structure parent = null;
076: switch (structure.getStructureType()) {
077: case Structure.ELEMENT:
078: parent = ((ElementDecl) structure).getParent();
079: if (parent.getStructureType() != Structure.SCHEMA) {
080: getSchemaLocation(parent, location, dealWithAnonTypes);
081: }
082: location.append(ExtendedBinding.PATH_SEPARATOR);
083: location.append(((ElementDecl) structure).getName());
084: break;
085:
086: case Structure.COMPLEX_TYPE:
087: ComplexType complexType = (ComplexType) structure;
088: parent = (complexType).getParent();
089: if (parent.getStructureType() != Structure.SCHEMA) {
090: getSchemaLocation(parent, location, dealWithAnonTypes);
091: }
092: if (complexType.getName() != null) {
093: location.append(ExtendedBinding.PATH_SEPARATOR);
094: location.append(ExtendedBinding.COMPLEXTYPE_ID);
095: location.append(((ComplexType) structure).getName());
096: }
097: // else if (dealWithAnonTypes){
098: // location.append(ExtendedBinding.PATH_SEPARATOR);
099: // location.append(ExtendedBinding.COMPLEXTYPE_ID);
100: // location.append("anonymous");
101: // }
102: break;
103:
104: case Structure.SIMPLE_TYPE:
105: SimpleType simpleType = (SimpleType) structure;
106: parent = simpleType.getParent();
107: if (parent != null
108: && parent.getStructureType() != Structure.SCHEMA) {
109: getSchemaLocation(parent, location, dealWithAnonTypes);
110: }
111:
112: if (parent != null && simpleType.getName() != null) {
113: location.append(ExtendedBinding.PATH_SEPARATOR);
114: location.append(ExtendedBinding.ENUMTYPE_ID);
115: location.append(((SimpleType) structure).getName());
116: }
117: // else if (dealWithAnonTypes){
118: // location.append(ExtendedBinding.PATH_SEPARATOR);
119: // location.append(ExtendedBinding.ENUMTYPE_ID);
120: // location.append("anonymous");
121: // }
122: break;
123:
124: case Structure.MODELGROUP:
125: ModelGroup group = (ModelGroup) structure;
126: parent = group.getParent();
127: if (parent.getStructureType() != Structure.SCHEMA) {
128: getSchemaLocation(parent, location, dealWithAnonTypes);
129: }
130: if (group.getName() != null) {
131: location.append(ExtendedBinding.PATH_SEPARATOR);
132: location.append(ExtendedBinding.GROUP_ID);
133: location.append(group.getName());
134: }
135: break;
136:
137: case Structure.ATTRIBUTE:
138: parent = ((AttributeDecl) structure).getParent();
139: if (parent.getStructureType() != Structure.SCHEMA) {
140: getSchemaLocation(parent, location, dealWithAnonTypes);
141: }
142: location.append(ExtendedBinding.PATH_SEPARATOR);
143: location.append(ExtendedBinding.ATTRIBUTE_PREFIX);
144: location.append(((AttributeDecl) structure).getName());
145: break;
146:
147: case Structure.GROUP:
148: // --we are inside a complexType
149: getSchemaLocation(((Group) structure).getParent(),
150: location, dealWithAnonTypes);
151: break;
152:
153: // case Structure.ATTRIBUTE_GROUP:
154: // //handle the real location
155:
156: default:
157: break;
158: }
159: }
160:
161: /**
162: * Returns a string (XPATH) representation of an XML Schema component. This
163: * representation is directly adapted from XPath and will used as a key to
164: * store the component bindings.
165: * <p>
166: * The location of a structure is composed of two parts:
167: * <ol>
168: * <li>the location of the parent structure</li>
169: * <li>the local location of the structure itself</li>
170: * </ol>
171: * <p>
172: * The local location is defined by:
173: * <ul>
174: * <li>If the structure is an <b>Element</b>: the location is the XPath
175: * representation "/element_name"</li>
176: * <li>If the structure is an <b>Attribute</b>: the location is the XPath
177: * representation "/@attribute_name"</li>
178: * <li>If the structure is a <b>ComplexType</b>: the location is
179: * "complexType:complexType_name"</li>
180: * <li>If the structure is a <b>SimpleType</b>: the location is
181: * "simpleType:simpleType_name"</li>
182: * <li>If the structure is a <b>Enumeration</b>: the location is
183: * "enumType:enumType_name"</li>
184: * <li>If the structure is a <b>ModelGroup</b>: the location is
185: * "group:group_name"</li>
186: * </ul>
187: * Note that only top-level groups and complexTypes are named and thus will
188: *
189: * @param structure the structure for which to return a representation.
190: * @param dealWithAnonTypes
191: * Indicates whether to include XPATH fragments for anonymous
192: * types.
193: * @return a string representation of an XML Schema component.
194: */
195: public static String getSchemaLocation(final Structure structure,
196: final boolean dealWithAnonTypes) {
197: if (structure == null) {
198: return null;
199: }
200: StringBuffer buffer = new StringBuffer(INITIAL_XPATH_SIZE);
201: getSchemaLocation(structure, buffer, dealWithAnonTypes);
202: return buffer.toString();
203: }
204:
205: /**
206: * Returns a string (XPATH) representation of an XML Schema component. This
207: * representation is directly adapted from XPath and will used as a key to
208: * store the component bindings.
209: * @param structure the structure for which to return a representation
210: * @return a string representation of the XPATH identifying an XML Schema component
211: * @see #getSchemaLocation(Structure, boolean)
212: */
213: public static String getSchemaLocation(final Structure structure) {
214: if (structure == null) {
215: return null;
216: }
217: StringBuffer buffer = new StringBuffer(INITIAL_XPATH_SIZE);
218: getSchemaLocation(structure, buffer, false);
219: return buffer.toString();
220: }
221:
222: }
|