1 /*
2 * Copyright 2007 Werner Guttmann
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package org.exolab.castor.builder.binding;
17
18 import org.exolab.castor.xml.schema.AttributeDecl;
19 import org.exolab.castor.xml.schema.ComplexType;
20 import org.exolab.castor.xml.schema.ElementDecl;
21 import org.exolab.castor.xml.schema.Group;
22 import org.exolab.castor.xml.schema.ModelGroup;
23 import org.exolab.castor.xml.schema.Schema;
24 import org.exolab.castor.xml.schema.SimpleType;
25 import org.exolab.castor.xml.schema.Structure;
26
27 /**
28 * Helper class to assemble an XPATH expression to qualify the path of
29 * an XML schema structure from the XML schema root.
30 * @author <a href="mailto:werner DOT guttmann AT gmx DOT net">Werner Guttmann</a>
31 * @since 1.1
32 */
33 public class XPathHelper {
34
35 /**
36 * Initial size of the {@link StringBuffer} used to asseble the XPATH
37 * expression.
38 */
39 private static final int INITIAL_XPATH_SIZE = 50;
40
41 /**
42 * Deduces an XPATH expression qualifying the path from the schema root
43 * to the given structure in question.
44 * @param structure AN XML structure.
45 * @param location The XPATH expression to be created.
46 */
47 public static void getSchemaLocation(
48 final Structure structure,
49 final StringBuffer location) {
50 getSchemaLocation(structure, location, false);
51 }
52
53 /**
54 * Deduces an XPATH expression qualifying the path from the schema root to
55 * the given structure in question.
56 *
57 * @param structure
58 * AN XML structure.
59 * @param location
60 * The XPATH expression to be created.
61 * @param dealWithAnonTypes
62 * Indicates whether to include XPATH fragments for anonymous
63 * types.
64 */
65 public static void getSchemaLocation(
66 final Structure structure,
67 final StringBuffer location,
68 final boolean dealWithAnonTypes) {
69 if (structure == null) {
70 throw new IllegalArgumentException("Structure cannot be null");
71 }
72
73 if (location == null) {
74 throw new IllegalArgumentException("location cannot be null");
75 }
76
77 Structure parent = null;
78 switch (structure.getStructureType()) {
79 case Structure.ELEMENT:
80 parent = ((ElementDecl) structure).getParent();
81 if (parent.getStructureType() != Structure.SCHEMA) {
82 getSchemaLocation(parent, location, dealWithAnonTypes);
83 }
84 location.append(ExtendedBinding.PATH_SEPARATOR);
85 location.append(((ElementDecl) structure).getName());
86 if (parent instanceof Schema) {
87 Schema schema = (Schema) parent;
88 if (schema.getTargetNamespace() != null) {
89 String targetNamespace = schema.getTargetNamespace();
90 location.append("{" + targetNamespace + "}");
91 }
92 }
93 break;
94
95 case Structure.COMPLEX_TYPE:
96 ComplexType complexType = (ComplexType) structure;
97 parent = (complexType).getParent();
98 if (parent.getStructureType() != Structure.SCHEMA) {
99 getSchemaLocation(parent, location, dealWithAnonTypes);
100 }
101 if (complexType.getName() != null) {
102 location.append(ExtendedBinding.PATH_SEPARATOR);
103 location.append(ExtendedBinding.COMPLEXTYPE_ID);
104 location.append(((ComplexType) structure).getName());
105 }
106 // else if (dealWithAnonTypes){
107 // location.append(ExtendedBinding.PATH_SEPARATOR);
108 // location.append(ExtendedBinding.COMPLEXTYPE_ID);
109 // location.append("anonymous");
110 // }
111 break;
112
113 case Structure.SIMPLE_TYPE:
114 SimpleType simpleType = (SimpleType) structure;
115 parent = simpleType.getParent();
116 if (parent != null && parent.getStructureType() != Structure.SCHEMA) {
117 getSchemaLocation(parent, location, dealWithAnonTypes);
118 }
119
120 if (parent != null && simpleType.getName() != null) {
121 location.append(ExtendedBinding.PATH_SEPARATOR);
122 location.append(ExtendedBinding.ENUMTYPE_ID);
123 location.append(((SimpleType) structure).getName());
124 }
125 // else if (dealWithAnonTypes){
126 // location.append(ExtendedBinding.PATH_SEPARATOR);
127 // location.append(ExtendedBinding.ENUMTYPE_ID);
128 // location.append("anonymous");
129 // }
130 break;
131
132 case Structure.MODELGROUP:
133 ModelGroup group = (ModelGroup) structure;
134 parent = group.getParent();
135 if (parent.getStructureType() != Structure.SCHEMA) {
136 getSchemaLocation(parent, location, dealWithAnonTypes);
137 }
138 if (group.getName() != null) {
139 location.append(ExtendedBinding.PATH_SEPARATOR);
140 location.append(ExtendedBinding.GROUP_ID);
141 location.append(group.getName());
142 }
143 break;
144
145 case Structure.ATTRIBUTE:
146 parent = ((AttributeDecl) structure).getParent();
147 if (parent.getStructureType() != Structure.SCHEMA) {
148 getSchemaLocation(parent, location, dealWithAnonTypes);
149 }
150 location.append(ExtendedBinding.PATH_SEPARATOR);
151 location.append(ExtendedBinding.ATTRIBUTE_PREFIX);
152 location.append(((AttributeDecl) structure).getName());
153 break;
154
155 case Structure.GROUP:
156 // --we are inside a complexType
157 getSchemaLocation(((Group) structure).getParent(), location, dealWithAnonTypes);
158 break;
159
160 // case Structure.ATTRIBUTE_GROUP:
161 // //handle the real location
162
163 default:
164 break;
165 }
166 }
167
168 /**
169 * Returns a string (XPATH) representation of an XML Schema component. This
170 * representation is directly adapted from XPath and will used as a key to
171 * store the component bindings.
172 * <p>
173 * The location of a structure is composed of two parts:
174 * <ol>
175 * <li>the location of the parent structure</li>
176 * <li>the local location of the structure itself</li>
177 * </ol>
178 * <p>
179 * The local location is defined by:
180 * <ul>
181 * <li>If the structure is an <b>Element</b>: the location is the XPath
182 * representation "/element_name"</li>
183 * <li>If the structure is an <b>Attribute</b>: the location is the XPath
184 * representation "/@attribute_name"</li>
185 * <li>If the structure is a <b>ComplexType</b>: the location is
186 * "complexType:complexType_name"</li>
187 * <li>If the structure is a <b>SimpleType</b>: the location is
188 * "simpleType:simpleType_name"</li>
189 * <li>If the structure is a <b>Enumeration</b>: the location is
190 * "enumType:enumType_name"</li>
191 * <li>If the structure is a <b>ModelGroup</b>: the location is
192 * "group:group_name"</li>
193 * </ul>
194 * Note that only top-level groups and complexTypes are named and thus will
195 *
196 * @param structure the structure for which to return a representation.
197 * @param dealWithAnonTypes
198 * Indicates whether to include XPATH fragments for anonymous
199 * types.
200 * @return a string representation of an XML Schema component.
201 */
202 public static String getSchemaLocation(final Structure structure,
203 final boolean dealWithAnonTypes) {
204 if (structure == null) {
205 return null;
206 }
207 StringBuffer buffer = new StringBuffer(INITIAL_XPATH_SIZE);
208 getSchemaLocation(structure, buffer, dealWithAnonTypes);
209 return buffer.toString();
210 }
211
212 /**
213 * Returns a string (XPATH) representation of an XML Schema component. This
214 * representation is directly adapted from XPath and will used as a key to
215 * store the component bindings.
216 * @param structure the structure for which to return a representation
217 * @return a string representation of the XPATH identifying an XML Schema component
218 * @see #getSchemaLocation(Structure, boolean)
219 */
220 public static String getSchemaLocation(final Structure structure) {
221 if (structure == null) {
222 return null;
223 }
224 StringBuffer buffer = new StringBuffer(INITIAL_XPATH_SIZE);
225 getSchemaLocation(structure, buffer, false);
226 return buffer.toString();
227 }
228
229 }