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 Element and Field classes.
27 // The Element class is the base class for the KML Object Model.  All
28 // KML complex elements are derived from this class.  As the Element class
29 // members wnd methods indicate an Element always has a given type id, and
30 // a single parent Element.  Element itself holds all unknown XML for a given
31 // KML element including completely unknown XML, misplaced KML,
32 // and unknown attributes.  During parse a simple element is held for
33 // a short time in the Field specialization of Element.
34 
35 #ifndef KML_DOM_ELEMENT_H__
36 #define KML_DOM_ELEMENT_H__
37 
38 #include <vector>
39 #include "boost/scoped_ptr.hpp"
40 #include "kml/dom/kml22.h"
41 #include "kml/dom/kml_ptr.h"
42 #include "kml/dom/visitor_driver.h"
43 #include "kml/base/util.h"
44 #include "kml/base/xml_element.h"
45 
46 namespace kmlbase {
47 class Attributes;
48 }
49 
50 namespace kmldom {
51 
52 class Serializer;
53 class Visitor;
54 class Xsd;
55 
56 // This is a KML-specific implementation of the somewhat abstracted
57 // kmlbase::XmlElement.
58 class Element : public kmlbase::XmlElement {
59  public:
60   virtual ~Element();
Type()61   virtual KmlDomType Type() const { return type_id_; }
IsA(KmlDomType type)62   virtual bool IsA(KmlDomType type) const {
63     return type == type_id_;
64   }
65 
66   // This returns the element of which this is a child (if any).
67   ElementPtr GetParent() const;
68 
69   // This is the concatenation of all character data found parsing this element.
get_char_data()70   const string& get_char_data() const {
71     return char_data_;
72   }
set_char_data(const string & char_data)73   void set_char_data(const string& char_data) {
74     char_data_ = char_data;
75   }
76 
77   // TODO: AddElement() and ParseAttributes() should really be protected.
78 
79   // A derived class implements this to use with parsing.  Element is
80   // either a complex or simple element which the given concrete element
81   // can accept.  If the given element is a valid child the concrete element
82   // takes ownership.  The given element is attached to the concrete parent
83   // if it is a valid complex child.  If the element is a simple element
84   // the character data is converted to the appropropriate simple type
85   // and the passed element is discarded.  If the passed element is not
86   // a valid child of the given concrete element the AddElement method
87   // there should pass this up to its parent for consideration.  A misplaced
88   // element will ultimately be attached to Element itself.
89   virtual void AddElement(const ElementPtr& element);
90 
91   // A derived class implements this to use with parsing.  A given concrete
92   // element examines the passed attributes for any it is aware of and
93   // passes the attributes to its parent class and ultimately to Element
94   // itself to preserve unknown attributes.  The caller takes ownership of
95   // the passed attributes class instance and is expected to erase any items
96   // it parses.
97   virtual void ParseAttributes(kmlbase::Attributes* attributes);
98 
99   // A derived class implements this to use with serialization.  See
100   // class Serializer for more information.
Serialize(Serializer &)101   virtual void Serialize(Serializer& /*serialize*/ ) const {}
102 
103   // A derived class uses this to use with serialization.  The derived
104   // class adds its attributes to the given set and passes attributes
105   // along to the parent and utlimately to Element itself to preserve
106   // unknown attributes.
107   virtual void SerializeAttributes(kmlbase::Attributes* attributes) const;
108 
109   // Each fully unknown element (and its children) is saved in raw XML form.
110   void AddUnknownElement(const string& s);
111 
112   // Called by concrete elements to serialize unknown and/or misplaced
113   // elements discovered at parse time.
114   void SerializeUnknown(Serializer& serializer) const;
115 
116   // Returns the unknown elements.
get_unknown_elements_array_size()117   size_t get_unknown_elements_array_size() const {
118     return unknown_elements_array_.size();
119   }
get_unknown_elements_array_at(size_t i)120   const string& get_unknown_elements_array_at(size_t i) const {
121     return unknown_elements_array_[i];
122   }
123 
124   // Returns the unknown legal (misplaced) elements.
get_misplaced_elements_array_size()125   size_t get_misplaced_elements_array_size() const {
126     return unknown_legal_elements_array_.size();
127   }
get_misplaced_elements_array_at(size_t i)128   const ElementPtr& get_misplaced_elements_array_at(size_t i) const {
129     return unknown_legal_elements_array_[i];
130   }
131 
132   // Add the given set of attributes to the element's unknown attributes.
133   // Element takes ownership of attributes.
134   void AddUnknownAttributes(kmlbase::Attributes* attributes);
135 
136   // This returns a pointer to the Attributes class holding all unknown
137   // attributes for this element found during parse.  This returns NULL if
138   // there are no unparsed attributes.  Ownership of the object is retained
139   // by the Element class.
GetUnknownAttributes()140   const kmlbase::Attributes* GetUnknownAttributes() const {
141     return unknown_attributes_.get();
142   }
143 
144   // This is the set of xmlns:PREFIX=NAMESPACE attributes on the
145   // element if any.  The attribute keys are without the "xmlns:" prefix.
146   // The default namespace is merely an "unknown" attribute
147   // of "xmlns" in the normal "unknown" attributes list.  Use
148   // get_default_xmlns() to access the default namespace for an element.
GetXmlns()149   const kmlbase::Attributes* GetXmlns() const {
150     return xmlns_.get();
151   }
152 
153   // This merges in the given set of prefix/namespace attributes into the
154   // the xml namespaces set for this element.  Each prefix is is _just_ the
155   // namespace prefix.  Each prefix added here appears in the
156   // SerializeAttributeswith a "xmlns:" prepended.
157   void MergeXmlns(const kmlbase::Attributes& xmlns);
158 
159   // Permits polymorphic use of Field methods.
SetBool(bool *)160   virtual bool SetBool(bool* /*val*/) { return false; }
SetDouble(double *)161   virtual bool SetDouble(double* /*val*/) { return false; }
SetInt(int *)162   virtual bool SetInt(int* /*val*/) { return false; }
SetEnum(int *)163   virtual bool SetEnum(int* /*val*/) { return false; }
SetString(string *)164   virtual bool SetString(string* /*val*/) { return false; }
165 
166   // Accepts the visitor for this element (this must be overridden for each
167   // element type).
168   // TODO(dbeaumont): Make pure virtual when all sub-classes implement Accept().
169   virtual void Accept(Visitor* visitor);
170 
171   // This needs to be implemented by subclasses with child elements and must
172   // call its parent's implementation first. The default implementation does
173   // nothing.
AcceptChildren(VisitorDriver *)174   virtual void AcceptChildren(VisitorDriver* /*driver*/) {
175     /* Inlinable for efficiency */
176   }
177 
178  protected:
179   // Element is an abstract base class and is never created directly.
180   Element();
181   Element(KmlDomType type_id);
182 
183   // This sets the given complex child to a field of this element.
184   // The intended usage is to implement the set_child() and clear_child()
185   // methods in a concrete element.
186   template <class T>
SetComplexChild(const T & child,T * field)187   bool SetComplexChild(const T& child, T* field) {
188     if (child == NULL) {
189       // TODO: remove child and children from ID maps...
190       *field = NULL;  // Assign removes reference and possibly deletes Element.
191       return true;
192     } else if (child->SetParent(this)) {
193       *field = child;  // This first releases the reference to previous field.
194       return true;
195     }
196     return false;
197   }
198 
199   // This adds the given complex child to an array in this element.
200   template <class T>
AddComplexChild(const T & child,std::vector<T> * vec)201   bool AddComplexChild(const T& child, std::vector<T>* vec) {
202     // NULL child ignored.
203     if (child && child->SetParent(this)) {
204       vec->push_back(child);
205       return true;
206     }
207     return false;
208   }
209 
210   // Allows subclasses to easily visit repeated fields.
211   template <class T>
AcceptRepeated(std::vector<T> * elements,VisitorDriver * driver)212   static void AcceptRepeated(std::vector<T>* elements, VisitorDriver* driver) {
213     typename std::vector<T>::iterator it;
214     for (it = elements->begin(); it != elements->end(); ++it) {
215       driver->Visit(*it);
216     }
217   }
218 
219   // This is the internal implementation of the various DeleteTAt() methods.
220   template <class T>
DeleteFromArrayAt(std::vector<T> * array,size_t i)221   static T DeleteFromArrayAt(std::vector<T>* array, size_t i) {
222     if (!array || i >= array->size()) {
223       return NULL;
224     }
225     T e = (*array)[i];
226     array->erase(array->begin() + i);
227     // TODO: notify e's XmlFile about the delete (kmlengine::KmlFile, for
228     // example would want to remove e from its internal maps).
229     // TODO: disparent e
230     return e;
231   }
232 
233  private:
234   KmlDomType type_id_;
235   string char_data_;
236   // A vector of strings to contain unknown non-KML elements discovered during
237   // parse.
238   std::vector<string> unknown_elements_array_;
239   // A vector of Element*'s to contain known KML elements found during parse
240   // to be in illegal positions, e.g. <Placemark><Document>.
241   std::vector<ElementPtr> unknown_legal_elements_array_;
242   // Unknown attributes found during parse are copied out and a pointer is
243   // stored. The object is dynamically allocated so every element is not
244   // burdened with an unnecessary Attributes object.
245   boost::scoped_ptr<kmlbase::Attributes> unknown_attributes_;
246   // Any Element may have 0 or more xmlns attributes.
247   boost::scoped_ptr<kmlbase::Attributes> xmlns_;
248   LIBKML_DISALLOW_EVIL_CONSTRUCTORS(Element);
249 };
250 
251 // This class implements common code for use in serializing most elements.
252 // Intended usage is as follows:
253 // ConcreteElement::Serialize(Serializer& serializer) const {
254 //   ElementSerializer element_serializer(Type(), serializer);
255 //   // serialize each child element and/or field
256 //   // ElementSerializer dtor ends serialization properly.
257 // }
258 class ElementSerializer {
259  public:
260   ElementSerializer(const Element& element, Serializer& serializer);
261   ~ElementSerializer();
262 
263  private:
264   const Element& element_;
265   Serializer& serializer_;
266 };
267 
268 // This class template is essentially common code for all elements based
269 // directly on Element.
270 template<int I>
271 class BasicElement : public Element {
272  public:
273   // This static method makes the class useable with ElementCast.
ElementType()274   static KmlDomType ElementType() { return static_cast<KmlDomType>(I); }
Type()275   virtual KmlDomType Type() const { return ElementType(); }
IsA(KmlDomType type)276   virtual bool IsA(KmlDomType type) const { return type == ElementType(); }
277 };
278 
279 // A field is generally short lived and holds the element id and character data
280 // for that field during parse.  When a Field is presented to AddElement() and
281 // is recognized by a parent element that parent typically copies the value of
282 // the Field to a field held within the parent.  However, when a "misplaced"
283 // field is parsed it is held in this form in Element's misplaced elements
284 // list.  Known child fields are serialized by their parents, but a Serialize
285 // method implementation is provided specifically to provide a means to
286 // serialize a Field held in an Element's misplaced elements list.  For
287 // example, <snippet> is a known element and is parsed initially into a Field,
288 // but since no element accepts <snippet> this results in a <snippet> Field in
289 // the parent element's misplaced elements list.
290 class Field : public Element {
291  public:
292   Field(KmlDomType type_id);
293 
294   // Serialize this Field to the given serializer.  See the class comment above
295   // for when this is used.
296   virtual void Serialize(Serializer& serialize) const;
297 
298   // Sets the given bool from the character data.  If no val pointer is
299   // supplied false is returned, else true is returned and the val is set.
300   bool SetBool(bool* val);
301 
302   // Sets the given double from the character data.  If no val pointer is
303   // supplied false is returned, else true is returned and the val is set.
304   bool SetDouble(double *val);
305 
306   // Sets the given int from the character data.  If no val pointer is
307   // supplied false is returned, else true is returned and the val is set.
308   bool SetInt(int* val);
309 
310   // Sets the given enum from the character data.  If no val pointer is
311   // supplied false is returned, else true is returned and the val is set.
312   bool SetEnum(int* enum_val);
313 
314   // Sets the given string from the character data.  If no val pointer is
315   // supplied false is returned, else true is returned and the val is set.
316   bool SetString(string* val);
317 
318  private:
319   const Xsd& xsd_;
320   LIBKML_DISALLOW_EVIL_CONSTRUCTORS(Field);
321 };
322 
323 }  // namespace kmldom
324 
325 #endif  // KML_DOM_ELEMENT_H__
326