View Javadoc
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 }