1 // Copyright 2008, Google Inc. All rights reserved.
2 //
3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are met:
5 //
6 //  1. Redistributions of source code must retain the above copyright notice,
7 //     this list of conditions and the following disclaimer.
8 //  2. Redistributions in binary form must reproduce the above copyright notice,
9 //     this list of conditions and the following disclaimer in the documentation
10 //     and/or other materials provided with the distribution.
11 //  3. Neither the name of Google Inc. nor the names of its contributors may be
12 //     used to endorse or promote products derived from this software without
13 //     specific prior written permission.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
16 // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
17 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
18 // EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21 // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22 // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
24 // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 
26 // This file contains the declaration of the XsdFile class.
27 
28 #ifndef KML_XSD_XSD_FILE_H__
29 #define KML_XSD_XSD_FILE_H__
30 
31 #include <map>
32 #include <stack>
33 #include <vector>
34 #include "boost/scoped_ptr.hpp"
35 #include "kml/base/xmlns.h"
36 #include "kml/xsd/xsd_element.h"
37 #include "kml/xsd/xsd_complex_type.h"
38 #include "kml/xsd/xsd_schema.h"
39 #include "kml/xsd/xsd_simple_type.h"
40 #include "kml/xsd/xsd_type.h"
41 
42 namespace kmlxsd {
43 
44 typedef std::map<string, string> XsdAliasMap;
45 typedef std::map<string, XsdElementPtr> XsdElementMap;
46 typedef std::vector<XsdElementPtr> XsdElementVector;
47 typedef std::map<string, XsdTypePtr> XsdTypeMap;
48 typedef std::vector<XsdTypePtr> XsdTypeVector;
49 
50 // This class holds the state of a processed XSD file.  Overall usage:
51 //   // Process: fetch and parse.
52 //   const string xsd_data = fetch_the_xsd_file();
53 //   string errors;
54 //   XsdFile* xsd_file = XsdFile::CreateFromParse(xsd_data, &errors);
55 //   // Access XSD file info.
56 //   xsd_file.GetElementNames(...);
57 //   xsd_file.IsComplex(...);
58 //   GetChildElementNames(...);
59 class XsdFile {
60  public:
61   static XsdFile* CreateFromParse(const string& xsd_data,
62                                   string* errors);
63 
XsdFile()64   XsdFile() {}  // Use static CreateFromParse().
65 
66   // Set <xs:schema> info.  The attributes are those of the <schema> element
67   // in the XSD file.
set_schema(const XsdSchemaPtr & xsd_schema)68   void set_schema(const XsdSchemaPtr& xsd_schema) {
69     xsd_schema_ = xsd_schema;
70   }
71 
72   // Add global <xs:element> info.  A "global" <xs:element> is a child of
73   // <xs::schema>.
add_element(const XsdElementPtr & xsd_element)74   void add_element(const XsdElementPtr& xsd_element) {
75     element_map_[xsd_element->get_name()] = xsd_element;
76   }
77 
78   // Add a <xs:complexType> or <xs:simpleType>.
add_type(const XsdTypePtr & xsd_type)79   void add_type(const XsdTypePtr& xsd_type) {
80     type_map_[xsd_type->get_name()] = xsd_type;
81   }
82 
get_target_namespace()83   const string& get_target_namespace() const {
84     return xsd_schema_->get_target_namespace();
85   }
get_target_namespace_prefix()86   const string& get_target_namespace_prefix() const {
87     return xsd_schema_->get_target_namespace_prefix();
88   }
89 
90   // Create an alias.  For example, "AbstractFeatureGroup" == "Feature".
set_alias(const string & real_name,const string & alias_name)91   void set_alias(const string& real_name,
92                  const string& alias_name) {
93     alias_map_[real_name] = alias_name;
94   }
95 
96   // Returns the alias for this name or NULL if this name has no alias.  For
97   // example, if set_alias("AbstractGeometryGroup", "Geometry") was used then
98   // get_alias("AbstractGeometryGroup") returns "Geometry".
get_alias(const string & real_name)99   const string get_alias(const string& real_name) const {
100     XsdAliasMap::const_iterator iter = alias_map_.find(real_name);
101     return iter == alias_map_.end() ? "" : iter->second;
102   }
103 
104   // Return all <xs:element> children of <xs:schema>.  Order is not preserved
105   // w.r.t. to the XSD file.
106   void GetAllElements(XsdElementVector* elements) const;
107 
108   // Return all <xs:complexType> and <xs:simpleType> children of <xs:schema>.
109   //  Order is not preserved w.r.t. to the XSD file.
110   void GetAllTypes(XsdTypeVector* type) const;
111 
112   // Return the names of the immediate child elements of the given complex
113   // element.  Each <xs:element ref="..."> is resolved.
114   void FindChildElements(const XsdComplexTypePtr& complex_element,
115                          XsdElementVector* elements) const;
116   void GetChildElements(const string& complex_element_name,
117                         XsdElementVector* elements) const;
118 
119 
120   // This looks up the given element by name.
121   const XsdElementPtr FindElement(const string& element_name) const;
122 
123   // Return the XsdType for the given element.  If there is no type for this
124   // element in the target namespace NULL is returned.
125   const XsdTypePtr FindElementType(const XsdElementPtr& element) const;
126 
127   // This looks up the given type by name.
128   const XsdTypePtr FindType(const string& type_name) const;
129 
130   // Return the global <xs:element> for the given <xs:element ref="..."/>.
131   // For example, element ref of "kml:name" returns the XsdElement describing
132   // the <xs:element name="name".../> child of <xs:schema/>.
133   const XsdElementPtr ResolveRef(const string& element_ref) const;
134 
135   // Return the XsdComplexType of the complex_type's extension base.  NULL is
136   // returned if the complex_type has no extension base or if the extension
137   // base is not found within this XsdFile's target namespace.
138   XsdComplexTypePtr GetBaseType(const XsdComplexTypePtr& complex_type) const;
139 
140   // Return the inheritance hierarchy of a given <xs:complexType>.  The first
141   // item in the vector is this type's extension base, the next that type's
142   // extension base and so on until a type with no extension base is reached.
143   bool GetTypeHierarchy(const XsdComplexTypePtr& complex_type,
144                         std::vector<XsdComplexTypePtr>* type_hier) const;
145 
146   // This appends all abstract elements to the given vector.
147   void GetAbstractElements(XsdElementVector* elements) const;
148 
149   // This appends all concrete complex elements to the given vector.
150   void GetComplexElements(XsdElementVector* elements) const;
151 
152   // This appends all concrete simple elements to the given vector.
153   void GetSimpleElements(XsdElementVector* elements) const;
154 
155   // This sorts the elements in this XSD file into 3 ranges in this order and
156   // then alphabetical order within each group:  1) abstract elements,
157   // 2) complex elements, 3) simple elements.  Offset 0 is reserved/invalid.
158   void GenerateElementIdVector(XsdElementVector* elements,
159                                size_t* begin_complex,
160                                size_t *begin_simple) const;
161 
162   // If find_type is a base type of complex_type return true, else false.
163   bool SearchTypeHierarchy(const XsdComplexTypePtr& complex_type,
164                            const XsdComplexTypePtr& find_type) const;
165 
166   // Return all elements derived from the given complex type.
167   void GetElementsOfType(const XsdComplexTypePtr& complex_type,
168                          XsdElementVector* elements) const;
169 
170   // Return all elements derived from the given complex type name.
171   void GetElementsOfTypeByName(const string& type_name,
172                                XsdElementVector* elements) const;
173 
174  private:
175   XsdSchemaPtr xsd_schema_;
176   XsdElementMap element_map_;
177   XsdTypeMap type_map_;
178   XsdAliasMap alias_map_;
179 };
180 
181 }  // end namespace kmlxsd
182 
183 #endif // KML_XSD_XSD_FILE_H__
184