// file : xsd/cxx/tree/elements.hxx // author : Boris Kolpackov // copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC // license : GNU GPL v2 + exceptions; see accompanying LICENSE file /** * @file * * @brief Contains C++ class definitions for XML Schema anyType and * anySimpleType types as well as supporting code. * * This is an internal header and is included by the generated code. You * normally should not include it directly. * */ #ifndef XSD_CXX_TREE_ELEMENTS_HXX #define XSD_CXX_TREE_ELEMENTS_HXX #include #include #include // std::auto_ptr #include #include #include #include #include #include #include #include #include // xml::properties #include // dom::auto_ptr #include #include #include namespace xsd { namespace cxx { /** * @brief C++/Tree mapping runtime namespace. * * This is an internal namespace and normally should not be referenced * directly. Instead you should use the aliases for types in this * namespaces that are created in the generated code. * */ namespace tree { /** * @brief Parsing and %serialization %flags. * * Flags are used to modify the default behavior of %parsing and * %serialization functions as well as %parsing constructors. * * @nosubgrouping */ class flags { public: /** * @name Flag constants */ //@{ /** * @brief Keep DOM association in the resulting tree. */ static const unsigned long keep_dom = 0x00000100UL; /** * @brief Assume ownership of the DOM document. * * This flag only makes sense together with the @c keep_dom * flag in the call to the %parsing function with the * @c dom::auto_ptr argument. * */ static const unsigned long own_dom = 0x00000200UL; /** * @brief Turn off XML Schema validation in the underlying XML * parser. */ static const unsigned long dont_validate = 0x00000400UL; /** * @brief Do not initialize the Xerces-C++ runtime. */ static const unsigned long dont_initialize = 0x00000001UL; /** * @brief Do not write XML declaration during %serialization. */ static const unsigned long no_xml_declaration = 0x00010000UL; /** * @brief Do not add extra spaces or new lines that make the * resulting XML easier to read. */ static const unsigned long dont_pretty_print = 0x00020000UL; //@cond // The following flags are for internal use. // static const unsigned long base = 0x01000000UL; //@endcond // Notes on flag blocks: // // 0x000000FF - common (applicable to both parsing and serialization) // 0x0000FF00 - parsing (values aligned with XML parsing) // 0x00FF0000 - serialization (values aligned with XML serialization) // 0xFF000000 - internal //@} public: /** * @brief Initialize an instance with an integer value. * * @param x A %flags value as an integer. */ flags (unsigned long x = 0) : x_ (x) { } /** * @brief Convert an instance to an integer value. * * @return An integer %flags value. */ operator unsigned long () const { return x_; } /** * @brief Combine two %flags. * * @return A %flags object that is a combination of the arguments. */ friend flags operator| (const flags& a, const flags& b) { return flags (a.x_ | b.x_); } /** * @brief Combine two %flags. * * @return A %flags object that is a combination of the arguments. */ friend flags operator| (const flags& a, unsigned long b) { return flags (a.x_ | b); } /** * @brief Combine two %flags. * * @return A %flags object that is a combination of the arguments. */ friend flags operator| (unsigned long a, const flags& b) { return flags (a | b.x_); } private: unsigned long x_; }; // Parsing properties. Refer to xsd/cxx/xml/elements.hxx for XML- // related properties. // template class properties: public xml::properties { }; //@cond // DOM user data keys. // template struct user_data_keys_template { // Back pointers to tree nodes. // static const XMLCh node[21]; }; typedef user_data_keys_template<0> user_data_keys; // HP aCC3 complains about unresolved symbols without an explicit // instantiation. // #if defined(__HP_aCC) && __HP_aCC <= 39999 template struct user_data_keys_template<0>; #endif // // struct identity { virtual ~identity () { } identity () { } virtual bool before (const identity&) const = 0; virtual void throw_duplicate_id () const = 0; private: identity (const identity&); identity& operator= (const identity&); }; //@endcond // anyType. VC++ has a name injection bug that makes it impossible // to have a member with the same name as a base type. To address // that we will have to choose some unique name for the definition // and typedef it to 'type'. // class _type; /** * @brief Class corresponding to the XML Schema anyType built-in type. * */ typedef _type type; /** * @brief Container type. * */ typedef _type container; /** * @brief Class corresponding to the XML Schema anyType built-in type. * * This class is a base for every generated and built-in type in the * C++/Tree mapping. * * @nosubgrouping */ class _type { public: virtual ~_type () { // Everything should have been unregistered by now. // assert (map_.get () == 0 || map_->size () == 0); } public: /** * @name Constructors */ //@{ /** * @brief Default constructor. */ _type () : container_ (0) { } public: /** * @brief Copy constructor. * * @param x An instance to make a copy of. * @param f Flags to create the copy with. * @param c A pointer to the object that will contain the copy. * * For polymorphic object models use the @c _clone function instead. */ _type (const type& x, flags f = 0, container* c = 0); /** * @brief Copy the instance polymorphically. * * @param f Flags to create the copy with. * @param c A pointer to the object that will contain the copy. * @return A pointer to the dynamically allocated copy. * * This function ensures that the dynamic type of the instance * is used for copying and should be used for polymorphic object * models instead of the copy constructor. */ virtual type* _clone (flags f = 0, container* c = 0) const { return new type (*this, f, c); } public: /** * @brief Create an instance from a data representation * stream. * * @param s A stream to extract the data from. * @param f Flags to create the new instance with. * @param c A pointer to the object that will contain the new * instance. */ template _type (istream& s, flags f = 0, container* c = 0); /** * @brief Create an instance from a DOM element. * * @param e A DOM element to extract the data from. * @param f Flags to create the new instance with. * @param c A pointer to the object that will contain the new * instance. */ _type (const xercesc::DOMElement& e, flags f = 0, container* c = 0); /** * @brief Create an instance from a DOM Attribute. * * @param a A DOM attribute to extract the data from. * @param f Flags to create the new instance with. * @param c A pointer to the object that will contain the new * instance. */ _type (const xercesc::DOMAttr& a, flags f = 0, container* c = 0); /** * @brief Create an instance from a %string fragment. * * @param s A %string fragment to extract the data from. * @param e A pointer to DOM element containing the %string fragment. * @param f Flags to create the new instance with. * @param c A pointer to the object that will contain the new * instance. */ template _type (const std::basic_string& s, const xercesc::DOMElement* e, flags f = 0, container* c = 0); //@} public: /** * @brief Copy assignment operator. * * @param x An instance to assign. * @return A reference to the instance. */ type& operator= (const type& x) { while (&x == 0) /* unused */; return *this; } // Container API. // public: /** * @brief Get a constant pointer to container, an object model * node that contains this instance. * * @return A constant pointer to container, or 0 if this instance * is not contained. */ const container* _container () const { return container_; } /** * @brief Get a pointer to container, an object model node that * contains this instance. * * @return A pointer to container, or 0 if this instance is not * contained. */ container* _container () { return container_; } /** * @brief Set this instance's new container, an object model node * that contains this instance. * * @param c A pointer to container. */ virtual void _container (container* c) { container* dr (0); if (c != 0) { dr = c->_root (); if (dr == 0) dr = c; } std::auto_ptr& m (dr ? dr->map_ : map_); if (container_ == 0) { if (c != 0 && map_.get () != 0) { // Transfer our IDs to the new root. // if (m.get () != 0) { m->insert (map_->begin (), map_->end ()); std::auto_ptr tmp (0); map_ = tmp; } else m = map_; } } else { container* sr (_root ()); if (sr->map_.get () != 0) { // Transfer IDs that belong to this subtree. // for (map::iterator i (sr->map_->begin ()), e (sr->map_->end ()); i != e;) { type* x (i->second); for (; x != this && x != sr; x = x->_container ()) ; if (x != sr) { // Part of our subtree. // if (m.get () == 0) { std::auto_ptr tmp (new map); m = tmp; } m->insert (*i); sr->map_->erase (i++); } else ++i; } } } container_ = c; } /** * @brief Get a constant pointer to object model's root node. * * @return A constant pointer to root node, or 0 if this instance * is not contained. */ const container* _root () const { const container* r (container_); for (const container* c (r); c != 0; c = c->container_) r = c; return r; } /** * @brief Get a pointer to object model's root node. * * @return A pointer to root node, or 0 if this instance is not * contained. */ container* _root () { container* r (container_); for (container* c (r); c != 0; c = c->container_) r = c; return r; } // DOM association. // public: /** * @brief Get a constant pointer to a DOM node associated with * this object model node. * * @return A constant pointer to DOM node, or 0 if none associated. */ const xercesc::DOMNode* _node () const { return dom_info_.get () ? dom_info_->node() : 0; } /** * @brief Get a pointer to a DOM node associated with this object * model node. * * @return A pointer to DOM node, or 0 if none associated. */ xercesc::DOMNode* _node () { return dom_info_.get () ? dom_info_->node () : 0; } /** * @brief Exception indicating that a DOM node cannot be associated * with an object model node. */ class bad_dom_node_type: public std::exception //@@ Inherit exception. { public: /** * @brief Get %exception description. * * @return A C %string describing the %exception. */ virtual const char* what () const throw () { return "DOM node is not an attribute node or element node"; } }; /** * @brief Manually set a DOM node associated with this object * model node. * * The DOM node should be a child of the parent's DOM node. If * this object model node is a root of the tree, then it will * assume the ownership of the whole DOM document to which this * DOM node belongs. * * @param n A pointer to DOM node (should be either an element or * an attribute). */ void _node (xercesc::DOMNode* n) { switch (n->getNodeType ()) { case xercesc::DOMNode::ELEMENT_NODE: { if (container_ != 0) { // @@ Should be a throw. // assert (_root ()->_node () != 0); assert (_root ()->_node ()->getOwnerDocument () == n->getOwnerDocument ()); } std::auto_ptr r ( dom_info_factory::create ( *static_cast (n), *this, container_ == 0)); dom_info_ = r; break; } case xercesc::DOMNode::ATTRIBUTE_NODE: { //@@ Should be a throw. // assert (container_ != 0); assert (_root ()->_node () != 0); assert (_root ()->_node ()->getOwnerDocument () == n->getOwnerDocument ()); std::auto_ptr r ( dom_info_factory::create ( *static_cast (n), *this)); dom_info_ = r; break; } default: { throw bad_dom_node_type (); } } } public: //@cond void _register_id (const identity& id, type* t) { // We should be the root. // assert (container_ == 0); if (map_.get () == 0) { std::auto_ptr tmp (new map); map_ = tmp; } if (!map_->insert ( std::pair (&id, t)).second) { id.throw_duplicate_id (); } } //@@ Does not inherit from exception. // struct not_registered: std::exception { virtual const char* what () const throw () { return "attempt to unregister non-existent id"; } }; void _unregister_id (const identity& id) { // We should be the root. // assert (container_ == 0); if (map_.get () == 0 || map_->erase (&id) == 0) throw not_registered (); } type* _lookup_id (const identity& id) const { if (map_.get ()) { map::const_iterator it (map_->find (&id)); if (it != map_->end ()) return it->second; } return 0; } //@endcond private: //@cond struct dom_info { virtual ~dom_info () { } dom_info () { } virtual std::auto_ptr clone (type& tree_node, container*) const = 0; virtual xercesc::DOMNode* node () = 0; private: dom_info (const dom_info&); dom_info& operator= (const dom_info&); }; struct dom_element_info: public dom_info { dom_element_info (xercesc::DOMElement& e, type& n, bool root) : doc_ (0), e_ (e) { e_.setUserData (user_data_keys::node, &n, 0); if (root) { // The caller should have associated a dom::auto_ptr object // that owns this document with the document node using the // xml_schema::dom::tree_node_key key. // xml::dom::auto_ptr* pd ( reinterpret_cast*> ( e.getOwnerDocument ()->getUserData (user_data_keys::node))); assert (pd != 0); assert (pd->get () == e.getOwnerDocument ()); doc_ = *pd; // Transfer ownership. } } virtual std::auto_ptr clone (type& tree_node, container* c) const { using std::auto_ptr; // Check if we are a document root. // if (c == 0) { // We preserver DOM associations only in complete // copies from root. // if (doc_.get () == 0) return auto_ptr (0); return auto_ptr ( new dom_element_info (*doc_, tree_node)); } // Check if our container does not have DOM association (e.g., // because it wasn't a complete copy of the tree). // using xercesc::DOMNode; DOMNode* cn (c->_node ()); if (cn == 0) return auto_ptr (0); // Now we are going to find the corresponding element in // the new tree. // { using xercesc::DOMElement; DOMNode& pn (*e_.getParentNode ()); assert (pn.getNodeType () == DOMNode::ELEMENT_NODE); DOMNode* sn (pn.getFirstChild ()); // Source. DOMNode* dn (cn->getFirstChild ()); // Destination. // We should have at least one child. // assert (sn != 0); // Move in parallel until we get to the needed node. // for (; sn != 0 && !e_.isSameNode (sn);) { sn = sn->getNextSibling (); dn = dn->getNextSibling (); } // e_ should be on the list. // assert (sn != 0); assert (dn->getNodeType () == DOMNode::ELEMENT_NODE); return auto_ptr ( new dom_element_info (static_cast (*dn), tree_node, false)); } } virtual xercesc::DOMNode* node () { return &e_; } private: dom_element_info (const xercesc::DOMDocument& d, type& n) : doc_ (static_cast ( d.cloneNode (true))), e_ (*doc_->getDocumentElement ()) { e_.setUserData (user_data_keys::node, &n, 0); } private: xml::dom::auto_ptr doc_; xercesc::DOMElement& e_; }; struct dom_attribute_info: public dom_info { dom_attribute_info (xercesc::DOMAttr& a, type& n) : a_ (a) { a_.setUserData (user_data_keys::node, &n, 0); } virtual std::auto_ptr clone (type& tree_node, container* c) const { using std::auto_ptr; // Check if we are a document root. // if (c == 0) { // We preserver DOM associations only in complete // copies from root. // return auto_ptr (0); } // Check if our container does not have DOM association (e.g., // because it wasn't a complete copy of the tree). // using xercesc::DOMNode; DOMNode* cn (c->_node ()); if (cn == 0) return auto_ptr (0); // We are going to find the corresponding attribute in // the new tree. // using xercesc::DOMAttr; using xercesc::DOMElement; using xercesc::DOMNamedNodeMap; DOMElement& p (*a_.getOwnerElement ()); DOMNamedNodeMap& nl (*p.getAttributes ()); XMLSize_t size (nl.getLength ()), i (0); // We should have at least one child. // assert (size != 0); for ( ;i < size && !a_.isSameNode (nl.item (i)); ++i)/*noop*/; // a_ should be in the list. // assert (i < size); DOMNode& n (*cn->getAttributes ()->item (i)); assert (n.getNodeType () == DOMNode::ATTRIBUTE_NODE); return auto_ptr ( new dom_attribute_info (static_cast (n), tree_node)); } virtual xercesc::DOMNode* node () { return &a_; } private: xercesc::DOMAttr& a_; }; // For Sun C++ 5.6. // struct dom_info_factory; friend struct _type::dom_info_factory; struct dom_info_factory { static std::auto_ptr create (const xercesc::DOMElement& e, type& n, bool root) { return std::auto_ptr ( new dom_element_info ( const_cast (e), n, root)); } static std::auto_ptr create (const xercesc::DOMAttr& a, type& n) { return std::auto_ptr ( new dom_attribute_info ( const_cast (a), n)); } }; //@endcond std::auto_ptr dom_info_; // ID/IDREF map. // private: //@cond struct identity_comparator { bool operator () (const identity* x, const identity* y) const { return x->before (*y); } }; //@endcond typedef std::map map; std::auto_ptr map_; private: container* container_; }; inline _type:: _type (const type& x, flags, container* c) : container_ (c) { if (x.dom_info_.get ()) { std::auto_ptr r (x.dom_info_->clone (*this, c)); dom_info_ = r; } } /** * @brief Class corresponding to the XML Schema anySimpleType built-in * type. * * @nosubgrouping */ template class simple_type: public B { public: /** * @name Constructors */ //@{ /** * @brief Default constructor. */ simple_type () { } public: /** * @brief Copy constructor. * * @param x An instance to make a copy of. * @param f Flags to create the copy with. * @param c A pointer to the object that will contain the copy. * * For polymorphic object models use the @c _clone function instead. */ simple_type (const simple_type& x, flags f = 0, container* c = 0); /** * @brief Copy the instance polymorphically. * * @param f Flags to create the copy with. * @param c A pointer to the object that will contain the copy. * @return A pointer to the dynamically allocated copy. * * This function ensures that the dynamic type of the instance * is used for copying and should be used for polymorphic object * models instead of the copy constructor. */ virtual simple_type* _clone (flags f = 0, container* c = 0) const; public: /** * @brief Create an instance from a data representation * stream. * * @param s A stream to extract the data from. * @param f Flags to create the new instance with. * @param c A pointer to the object that will contain the new * instance. */ template simple_type (istream& s, flags f = 0, container* c = 0); /** * @brief Create an instance from a DOM element. * * @param e A DOM element to extract the data from. * @param f Flags to create the new instance with. * @param c A pointer to the object that will contain the new * instance. */ simple_type (const xercesc::DOMElement& e, flags f = 0, container* c = 0); /** * @brief Create an instance from a DOM Attribute. * * @param a A DOM attribute to extract the data from. * @param f Flags to create the new instance with. * @param c A pointer to the object that will contain the new * instance. */ simple_type (const xercesc::DOMAttr& a, flags f = 0, container* c = 0); /** * @brief Create an instance from a %string fragment. * * @param s A %string fragment to extract the data from. * @param e A pointer to DOM element containing the %string fragment. * @param f Flags to create the new instance with. * @param c A pointer to the object that will contain the new * instance. */ template simple_type (const std::basic_string& s, const xercesc::DOMElement* e, flags f = 0, container* c = 0); //@} }; /** * @brief Base class for element types. * * This class is a base for every generated element type. * * @nosubgrouping */ template class element_type { public: virtual ~element_type () { } /** * @brief Copy the instance polymorphically. * * @param f Flags to create the copy with. * @return A pointer to the dynamically allocated copy. * * This function ensures that the dynamic type of the instance * is used for copying and should be used for polymorphic object * models instead of the copy constructor. */ virtual element_type* _clone (flags f = 0) const = 0; /** * @brief Return the element name. * * @return A read-only string reference containing the element * name. */ virtual const std::basic_string& _name () const = 0; /** * @brief Return the element namespace. * * @return A read-only string reference containing the element * namespace. Empty string is returned if the element is * unqualified. */ virtual const std::basic_string& _namespace () const = 0; /** * @brief Return the element value. * * @return A pointer to the element value or 0 if the element * is of a fundamental type. */ virtual T* _value () = 0; /** * @brief Return the element value. * * @return A read-only pointer to the element value or 0 if the * element is of a fundamental type. */ virtual const T* _value () const = 0; }; //@cond // Extra schema type id to disambiguate certain cases where // different XML Schema types (e.g., double and decimal) are // mapped to the same fundamental C++ type (e.g., double). // struct schema_type { enum value { other, double_, decimal }; }; //@endcond //@cond template struct traits { typedef T type; static std::auto_ptr create (const xercesc::DOMElement& e, flags f, container* c) { return std::auto_ptr (new T (e, f, c)); } static std::auto_ptr create (const xercesc::DOMAttr& a, flags f, container* c) { return std::auto_ptr (new T (a, f, c)); } static std::auto_ptr create (const std::basic_string& s, const xercesc::DOMElement* e, flags f, container* c) { return std::auto_ptr (new T (s, e, f, c)); } }; //@endcond /** * @brief Class template that emulates inheritance from a * fundamental C++ type. * * @nosubgrouping */ template class fundamental_base: public B { public: /** * @name Constructors */ //@{ /** * @brief Default constructor. */ fundamental_base () : facet_table_ (0), x_ () { } /** * @brief Initialize an instance with an underlying type value. * * @param x An underlying type value. */ fundamental_base (T x) : facet_table_ (0), x_ (x) { } public: /** * @brief Copy constructor. * * @param x An instance to make a copy of. * @param f Flags to create the copy with. * @param c A pointer to the object that will contain the copy. * * For polymorphic object models use the @c _clone function instead. */ fundamental_base (const fundamental_base& x, flags f = 0, container* c = 0) : B (x, f, c), facet_table_ (0), x_ (x.x_) { } /** * @brief Copy the instance polymorphically. * * @param f Flags to create the copy with. * @param c A pointer to the object that will contain the copy. * @return A pointer to the dynamically allocated copy. * * This function ensures that the dynamic type of the instance * is used for copying and should be used for polymorphic object * models instead of the copy constructor. */ virtual fundamental_base* _clone (flags f = 0, container* c = 0) const; public: /** * @brief Create an instance from a data representation * stream. * * @param s A stream to extract the data from. * @param f Flags to create the new instance with. * @param c A pointer to the object that will contain the new * instance. */ template fundamental_base (istream& s, flags f = 0, container* c = 0); /** * @brief Create an instance from a DOM element. * * @param e A DOM element to extract the data from. * @param f Flags to create the new instance with. * @param c A pointer to the object that will contain the new * instance. */ fundamental_base (const xercesc::DOMElement& e, flags f = 0, container* c = 0); /** * @brief Create an instance from a DOM Attribute. * * @param a A DOM attribute to extract the data from. * @param f Flags to create the new instance with. * @param c A pointer to the object that will contain the new * instance. */ fundamental_base (const xercesc::DOMAttr& a, flags f = 0, container* c = 0); /** * @brief Create an instance from a %string fragment. * * @param s A %string fragment to extract the data from. * @param e A pointer to DOM element containing the %string fragment. * @param f Flags to create the new instance with. * @param c A pointer to the object that will contain the new * instance. */ fundamental_base (const std::basic_string& s, const xercesc::DOMElement* e, flags f = 0, container* c = 0); //@} public: /** * @brief Assign an underlying type value to the instance. * * @param x An underlying type value. * @return A reference to the instance. */ fundamental_base& operator= (const T& x) { if (&x_ != &x) x_ = x; return *this; } public: /** * @brief Implicitly convert the instance to constant reference to * the underlying type. * * @return A constant reference to the underlying type. */ operator const T& () const { return x_; } /** * @brief Implicitly convert the instance to reference to the * underlying type. * * @return A reference to the underlying type. */ operator T& () { return x_; } // The following extra conversion operators causes problems on // some compilers (notably VC 7.1 and 9.0) and are disabled by // default. // #ifdef XSD_TREE_EXTRA_FUND_CONV /** * @brief Implicitly convert the instance to another type (const * version). * * @return A value converted to the target type. */ template operator T2 () const { return x_; } /** * @brief Implicitly convert the instance to another type. * * @return A value converted to the target type. */ template operator T2 () { return x_; } #endif // XSD_TREE_EXTRA_FUND_CONV public: /** * @brief Get the facet table associated with this type. * * @return A pointer to read-only facet table or 0. */ const facet* _facet_table () const { return facet_table_; } protected: /** * @brief Set the facet table associated with this type. * * @param ft A pointer to read-only facet table. */ void _facet_table (const facet* ft) { facet_table_ = ft; } private: const facet* facet_table_; T x_; }; // While thse operators are not normally necessary, they // help resolve ambiguities between implicit conversion and // construction. // /** * @brief %fundamental_base comparison operator. * * @return True if the underlying values are equal, false otherwise. */ template inline bool operator== (const fundamental_base& x, const fundamental_base& y) { T x_ (x); T y_ (y); return x_ == y_; } /** * @brief %fundamental_base comparison operator. * * @return True if the underlying values are not equal, false otherwise. */ template inline bool operator!= (const fundamental_base& x, const fundamental_base& y) { T x_ (x); T y_ (y); return x_ != y_; } //@cond // Comparator for enum tables. // template struct enum_comparator { enum_comparator (const C* const* table) : table_ (table) { } bool operator() (std::size_t i, const std::basic_string& s) const { return table_[i] < s; } bool operator() (const std::basic_string& s, std::size_t i) const { return s < table_[i]; } bool operator() (std::size_t i, std::size_t j) const { return std::basic_string (table_[i]) < table_[j]; } private: const C* const* table_; }; //@endcond } } } #include #endif // XSD_CXX_TREE_ELEMENTS_HXX