View Javadoc
1   // $Id:XSModelHelper.java 62 2008-04-20 12:28:56Z me $
2   /*
3    * xsAnalyzer - XML schema analyzing tool. Copyright (C) 2008 Michael Engelhardt
4    * 
5    * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public
6    * License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later
7    * version.
8    * 
9    * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
10   * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
11   * 
12   * You should have received a copy of the GNU General Public License along with this program; if not, write to the Free
13   * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
14   */
15  /**
16   * 
17   */
18  package de.mindcrimeilab.xsanalyzer.util;
19  
20  import java.io.File;
21  import java.net.URI;
22  import java.net.URISyntaxException;
23  import java.util.ArrayList;
24  import java.util.Collection;
25  import java.util.Collections;
26  import java.util.HashSet;
27  import java.util.LinkedList;
28  import java.util.List;
29  import java.util.Set;
30  
31  import org.apache.commons.lang.builder.EqualsBuilder;
32  import org.apache.commons.logging.Log;
33  import org.apache.commons.logging.LogFactory;
34  import org.apache.xerces.impl.xs.XSGroupDecl;
35  import org.apache.xerces.xs.StringList;
36  import org.apache.xerces.xs.XSAttributeDeclaration;
37  import org.apache.xerces.xs.XSConstants;
38  import org.apache.xerces.xs.XSElementDeclaration;
39  import org.apache.xerces.xs.XSModel;
40  import org.apache.xerces.xs.XSModelGroup;
41  import org.apache.xerces.xs.XSNamedMap;
42  import org.apache.xerces.xs.XSNamespaceItem;
43  import org.apache.xerces.xs.XSNamespaceItemList;
44  import org.apache.xerces.xs.XSObject;
45  import org.apache.xerces.xs.XSObjectList;
46  import org.apache.xerces.xs.XSParticle;
47  import org.apache.xerces.xs.XSSimpleTypeDefinition;
48  import org.apache.xerces.xs.XSTerm;
49  import org.apache.xerces.xs.XSTypeDefinition;
50  
51  /**
52   * @author Michael Engelhardt<me@mindcrime-ilab.de>
53   * @author $Author:me $
54   * @version $Revision:62 $
55   * 
56   */
57  public abstract class XSModelHelper {
58  
59      private static final Log logger = LogFactory.getLog("xsAnalyzerApplicationLogger");
60  
61      public static Set<? extends XSTypeDefinition> getComponents(XSModel model, List<XSNamespaceItem> namespaces) {
62          short[] selectedTypes = { XSTypeDefinition.SIMPLE_TYPE, XSTypeDefinition.COMPLEX_TYPE};
63          return XSModelHelper.getComponents(model, namespaces, selectedTypes);
64      }
65  
66      /**
67       * Returns all public and global types for a given set of namespaces
68       * 
69       * @param model
70       *            schema
71       * @param namespaces
72       *            List of namespaces
73       * @return
74       */
75      public static Set<? extends XSTypeDefinition> getComponents(XSModel model, List<XSNamespaceItem> namespaces, short[] selectedTypes) {
76          final Set<XSTypeDefinition> tmp = new HashSet<XSTypeDefinition>();
77  
78          for (short type : selectedTypes) {
79              for (XSNamespaceItem ns : namespaces) {
80  
81                  XSNamedMap xsmap = model.getComponentsByNamespace(type, ns.getSchemaNamespace());
82  
83                  if (xsmap != null) {
84                      for (int i = 0; i < xsmap.getLength(); ++i) {
85                          if (null != xsmap.item(i)) {
86                              tmp.add((XSTypeDefinition) xsmap.item(i));
87                          }
88                      }
89                  }
90              }
91          }
92          return Collections.unmodifiableSet(tmp);
93      }
94  
95      /**
96       * Returns all public and global elements for given set of namespaces
97       * 
98       * @param model
99       *            schema
100      * @param namespaces
101      *            List of namespaces
102      * @return
103      */
104     public static List<XSElementDeclaration> getElements(XSModel model, List<XSNamespaceItem> namespaces) {
105 
106         final List<XSElementDeclaration> elements = new LinkedList<XSElementDeclaration>();
107 
108         for (XSNamespaceItem ns : namespaces) {
109             XSNamedMap xsmap = model.getComponentsByNamespace(XSConstants.ELEMENT_DECLARATION, ns.getSchemaNamespace());
110 
111             if (xsmap != null) {
112                 for (int i = 0; i < xsmap.getLength(); ++i) {
113                     if (null != xsmap.item(i)) {
114                         elements.add((XSElementDeclaration) xsmap.item(i));
115                     }
116                 }
117 
118             }
119         }
120         return Collections.unmodifiableList(elements);
121     }
122 
123     public static List<XSGroupDecl> getGroups(XSModel model, List<XSNamespaceItem> namespaces) {
124 
125         final List<XSGroupDecl> groups = new LinkedList<XSGroupDecl>();
126 
127         for (XSNamespaceItem ns : namespaces) {
128             XSNamedMap xsmap = model.getComponentsByNamespace(XSConstants.MODEL_GROUP_DEFINITION, ns.getSchemaNamespace());
129 
130             if (xsmap != null) {
131                 for (int i = 0; i < xsmap.getLength(); ++i) {
132                     if (null != xsmap.item(i)) {
133                         groups.add((XSGroupDecl) xsmap.item(i));
134                     }
135                 }
136 
137             }
138         }
139         return Collections.unmodifiableList(groups);
140     }
141 
142     public static List<XSNamespaceItem> getNamespaceItemsAsList(XSModel model) {
143         final XSNamespaceItemList namespaceItems = model.getNamespaceItems();
144         final List<XSNamespaceItem> list = new ArrayList<XSNamespaceItem>(namespaceItems.getLength());
145         for (int i = 0; i < namespaceItems.getLength(); ++i) {
146             list.add(namespaceItems.item(i));
147         }
148         return list;
149     }
150 
151     /**
152      * Check if both values have the same name and namespace definition.
153      * 
154      * @param lhs
155      * @param rhs
156      * @return true if both have same name and namespace value
157      */
158     public static boolean isSameTypeDefinition(final XSObject lhs, final XSObject rhs) {
159         final boolean ret;
160         if (null == lhs && null == rhs) {
161             ret = true;
162         }
163         else if (null != lhs && null != rhs) {
164             EqualsBuilder equalsBuilder = new EqualsBuilder();
165             ret = equalsBuilder.append(lhs.getName(), rhs.getName()).append(lhs.getNamespace(), rhs.getNamespace()).isEquals();
166         }
167         else {
168             ret = false;
169         }
170         return ret;
171     }
172 
173     @SuppressWarnings("unchecked")
174     public static Collection<XSObject> flat(XSObjectList list) {
175         Collection<XSObject> collection = new ArrayList<XSObject>();
176         for (int i = 0; i < list.getLength(); i++) {
177             final Object item = list.item(i);
178             if (item instanceof XSParticle) {
179                 XSTerm term = ((XSParticle) item).getTerm();
180                 if (term instanceof XSModelGroup) {
181                     collection.addAll(XSModelHelper.flat(((XSModelGroup) term).getParticles()));
182                 }
183 
184                 else {
185                     XSModelHelper.logger.debug("Adding element of class [" + item.getClass().getName() + "]");
186                     collection.add((XSObject) item);
187                 }
188             }
189             else {
190                 XSModelHelper.logger.debug("Adding element of class [" + item.getClass().getName() + "]");
191                 collection.add((XSObject) item);
192             }
193         }
194         return collection;
195     }
196 
197     public static <T> void addComponents(XSNamedMap map, List<T> list) {
198         for (int i = 0; i < map.getLength(); ++i) {
199             list.add((T) map.item(i));
200         }
201     }
202 
203     /**
204      * @param object
205      * @return
206      */
207     public static XSTypeDefinition getBaseType(XSObject object) {
208         final XSTypeDefinition type;
209         switch (object.getType()) {
210             case XSConstants.TYPE_DEFINITION:
211                 final XSTypeDefinition typedef = ((XSTypeDefinition) object);
212                 if (typedef.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE) {
213                     type = XSModelHelper.getBaseType((XSSimpleTypeDefinition) typedef);
214                 }
215                 else {
216                     type = typedef.getBaseType();
217                 }
218                 break;
219             case XSConstants.ELEMENT_DECLARATION:
220                 type = ((XSElementDeclaration) object).getTypeDefinition();
221                 break;
222             case XSConstants.ATTRIBUTE_DECLARATION:
223                 type = ((XSAttributeDeclaration) object).getTypeDefinition();
224                 break;
225             case XSConstants.NOTATION_DECLARATION:
226             case XSConstants.MODEL_GROUP_DEFINITION:
227             default:
228                 throw new RuntimeException(XSModelHelper.class.getName() + ": Unknown Type [" + object.getType() + "]!");
229         }
230         return type;
231     }
232 
233     public static XSTypeDefinition getBaseType(XSSimpleTypeDefinition stypedef) {
234         return (stypedef.getVariety() == XSSimpleTypeDefinition.VARIETY_LIST) ? null : stypedef.getBaseType();
235     }
236 
237     /**
238      * Get target namespace from model.
239      * 
240      * @param model
241      * @param schema
242      * @return
243      */
244     public static XSNamespaceItem getTargetNamespace(XSModel model, File schema) {
245         /*
246          * Maybe simply use the dom/sax api?
247          */
248         XSNamespaceItemList namespaces = model.getNamespaceItems();
249         final URI absolutePath = schema.getAbsoluteFile().toURI();
250         for (int i = 0; i < namespaces.getLength(); ++i) {
251             XSNamespaceItem namespace = namespaces.item(i);
252             StringList documentLocations = namespace.getDocumentLocations();
253             for (int j = 0; j < documentLocations.getLength(); ++j) {
254 
255                 try {
256                     URI fname = new URI(documentLocations.item(j));
257                     XSModelHelper.logger.debug("Namespace [" + namespace.getSchemaNamespace() + "] file [" + fname + "] absolute path [" + absolutePath + "]");
258                     if (absolutePath.equals(fname)) { return namespace; }
259                 }
260                 catch (URISyntaxException e) {
261                     e.printStackTrace();
262                     XSModelHelper.logger.error("Cannot construct URI from document location [" + documentLocations.item(i) + "] for namespace [" + namespace + "].", e);
263                 }
264 
265             }
266         }
267         return null;
268     }
269 
270     public static String compositorToString(short compositor) {
271         final String ret;
272         switch (compositor) {
273             case XSModelGroup.COMPOSITOR_ALL:
274                 ret = "ALL";
275                 break;
276             case XSModelGroup.COMPOSITOR_CHOICE:
277                 ret = "CHOICE";
278                 break;
279             case XSModelGroup.COMPOSITOR_SEQUENCE:
280                 ret = "SEQUENCE";
281                 break;
282             default:
283                 throw new RuntimeException("Unexpected branch selection - Not implemented");
284         }
285         return ret;
286     }
287 }