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