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