COMPASSi/trunk/code/inc/DataManager/XmlSerialization/xsd/cxx/tree/elements.hxx

1878 lines
51 KiB
C++

// file : xsd/cxx/tree/elements.hxx
// 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 <xsd/cxx/config.hxx> // XSD_AUTO_PTR, XSD_CXX11
#include <map>
#include <string>
#include <memory> // std::auto_ptr/unique_ptr
#include <cstddef> // std::size_t
#include <istream>
#include <sstream>
#include <cassert>
#ifdef XSD_CXX11
# include <utility> // std::move
#endif
#include <xercesc/dom/DOMNode.hpp>
#include <xercesc/dom/DOMAttr.hpp>
#include <xercesc/dom/DOMElement.hpp>
#include <xercesc/dom/DOMDocument.hpp>
#include <xercesc/dom/DOMNamedNodeMap.hpp>
#include <xercesc/util/XercesVersion.hpp>
#include <xsd/cxx/xml/elements.hxx> // xml::properties
#include <xsd/cxx/xml/dom/auto-ptr.hxx> // dom::auto_ptr/unique_ptr
#include <xsd/cxx/xml/dom/wildcard-source.hxx> // dom::create_document()
#include <xsd/cxx/tree/facet.hxx>
#include <xsd/cxx/tree/exceptions.hxx>
#include <xsd/cxx/tree/istream-fwd.hxx>
#include <xsd/cxx/tree/containers-wildcard.hxx>
#if _XERCES_VERSION < 30000
# error Xerces-C++ 2-series is not supported
#endif
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/unique_ptr\<DOMDocument> 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 Extract XML content for anyType or anySimpleType.
* Normally you don't need to specify this flag explicitly.
*/
static const unsigned long extract_content = 0x00000800UL;
/**
* @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 <typename C>
class properties: public xml::properties<C>
{
};
/**
* @brief Content order sequence entry.
*
* @nosubgrouping
*/
struct content_order
{
/**
* @brief Initialize an instance with passed id and index.
*
* @param id Content id.
* @param index Content index in the corresponding sequence.
*/
content_order (std::size_t id, std::size_t index = 0)
: id (id), index (index)
{
}
/**
* @brief Content id.
*/
std::size_t id;
/**
* @brief Content index.
*/
std::size_t index;
};
//@cond
bool
operator== (const content_order&, const content_order&);
bool
operator!= (const content_order&, const content_order&);
bool
operator< (const content_order&, const content_order&);
// DOM user data keys.
//
template <int dummy>
struct user_data_keys_template
{
// Back pointers to tree nodes.
//
static const XMLCh node[21];
};
typedef user_data_keys_template<0> user_data_keys;
//
//
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 ();
/**
* @brief Create an instance from a C string.
*
* @param s A string to initialize the instance with.
*
* Note that this constructor ignores the string and creates an
* empty anyType instance. In particular, it will not convert the
* string into DOM content. The purpose of such a strange constructor
* is to allow statically-initialized default values of anyType type.
*/
template <typename C>
explicit
_type (const C* s);
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 <typename S>
_type (istream<S>& 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 = flags::extract_content,
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 <typename C>
_type (const std::basic_string<C>& 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)
{
if (this != &x)
{
if (x.content_.get () == 0)
content_.reset ();
else
content_ = x.content_->clone ();
// Drop DOM association.
//
dom_info_.reset ();
}
return *this;
}
// anyType content API.
//
public:
//@cond
typedef element_optional dom_content_optional;
//@endcond
/**
* @brief Return a read-only (constant) reference to the anyType
* DOM content.
*
* @return A constant reference to the optional container.
*
* The DOM content is returned as an optional element container,
* the same container as used for optional element wildcards.
*/
const dom_content_optional&
dom_content () const;
/**
* @brief Return a read-write reference to the anyType DOM content.
*
* @return A reference to the optional container.
*
* The DOM content is returned as an optional element container,
* the same container as used for optional element wildcards.
*/
dom_content_optional&
dom_content ();
/**
* @brief Set the anyType DOM content.
*
* @param e A new element to set.
*
* This function makes a copy of its argument and sets it as the
* new DOM content.
*/
void
dom_content (const xercesc::DOMElement& e);
/**
* @brief Set the anyType DOM content.
*
* @param e A new element to use.
*
* This function will use the passed element directly instead
* of making a copy. For this to work the element should belong
* to the DOM document associated with this anyType instance.
*
* @see dom_content_document
*/
void
dom_content (xercesc::DOMElement* e);
/**
* @brief Set the anyType DOM content.
*
* @param d An optional container with the new element to set.
*
* If the element is present in @a d then this function makes a
* copy of this element and sets it as the new wildcard content.
* Otherwise the element container is set the 'not present' state.
*/
void
dom_content (const dom_content_optional& d);
/**
* @brief Return a read-only (constant) reference to the DOM
* document associated with this anyType instance.
*
* @return A constant reference to the DOM document.
*
* The DOM document returned by this function is used to store
* the raw XML content corresponding to the anyType instance.
*/
const xercesc::DOMDocument&
dom_content_document () const;
/**
* @brief Return a read-write reference to the DOM document
* associated with this anyType instance.
*
* @return A reference to the DOM document.
*
* The DOM document returned by this function is used to store
* the raw XML content corresponding to the anyType instance.
*/
xercesc::DOMDocument&
dom_content_document ();
/**
* @brief Check for absence of DOM (anyType) and text (anySimpleType)
* content.
*
* @return True if there is no content and false otherwise.
*
* This is an optimization function that allows us to check for the
* lack of content without actually creating its empty representation
* (that is, empty DOM document for DOM or empty string for text).
*/
bool
null_content () const;
//
//
public:
/**
* @brief Comparison operator. It uses DOM (anyType) or text
* (anySimpleType) content if present. If the content is missing
* then the types are assumed unequal.
*
* @return True if the instances are equal, false otherwise.
*/
friend bool
operator== (const type& x, const type& y)
{
return x.content_.get () != 0 &&
x.content_->compare (y.content_.get ());
}
/**
* @brief Comparison operator. It uses DOM (anyType) or text
* (anySimpleType) content if present. If the content is missing
* then the types are assumed unequal.
*
* @return True if the instances are not equal, false otherwise.
*/
friend bool
operator!= (const type& x, const type& y) {return !(x == y);}
// 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;
}
XSD_AUTO_PTR<map>& 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 ());
map_.reset ();
}
else
{
#ifdef XSD_CXX11
m = std::move (map_);
#else
m = map_;
#endif
}
}
}
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)
m.reset (new map);
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<C>.
{
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)
{
assert (_root ()->_node () != 0);
assert (_root ()->_node ()->getOwnerDocument () ==
n->getOwnerDocument ());
}
dom_info_ =
dom_info_factory::create (
*static_cast<xercesc::DOMElement*> (n),
*this,
container_ == 0);
break;
}
case xercesc::DOMNode::ATTRIBUTE_NODE:
{
assert (container_ != 0);
assert (_root ()->_node () != 0);
assert (_root ()->_node ()->getOwnerDocument () ==
n->getOwnerDocument ());
dom_info_ =
dom_info_factory::create (
*static_cast<xercesc::DOMAttr*> (n),
*this);
break;
}
default:
{
throw bad_dom_node_type ();
}
}
}
public:
//@cond
void
_register_id (const identity& i, type* t)
{
// We should be the root.
//
assert (container_ == 0);
if (map_.get () == 0)
map_.reset (new map);
if (!map_->insert (
std::pair<const identity*, type*> (&i, t)).second)
{
i.throw_duplicate_id ();
}
}
//@@ Does not inherit from exception<C>.
//
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 XSD_AUTO_PTR<dom_info>
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)
: e_ (e)
{
e_.setUserData (user_data_keys::node, &n, 0);
if (root)
{
// The caller should have associated a dom::auto/unique_ptr
// object that owns this document with the document node
// using the xml_schema::dom::tree_node_key key.
//
XSD_DOM_AUTO_PTR<xercesc::DOMDocument>* pd (
reinterpret_cast<XSD_DOM_AUTO_PTR<xercesc::DOMDocument>*> (
e.getOwnerDocument ()->getUserData (user_data_keys::node)));
assert (pd != 0);
assert (pd->get () == e.getOwnerDocument ());
// Transfer ownership.
#ifdef XSD_CXX11
doc_ = std::move (*pd);
#else
doc_ = *pd;
#endif
}
}
virtual XSD_AUTO_PTR<dom_info>
clone (type& tree_node, container* c) const
{
// Check if we are a document root.
//
if (c == 0)
{
// We preserver DOM associations only in complete
// copies from root.
//
return XSD_AUTO_PTR<dom_info> (
doc_.get () == 0
? 0
: 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 XSD_AUTO_PTR<dom_info> ();
// 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 XSD_AUTO_PTR<dom_info> (
new dom_element_info (static_cast<DOMElement&> (*dn),
tree_node,
false));
}
}
virtual xercesc::DOMNode*
node ()
{
return &e_;
}
private:
dom_element_info (const xercesc::DOMDocument& d, type& n)
: doc_ (static_cast<xercesc::DOMDocument*> (
d.cloneNode (true))),
e_ (*doc_->getDocumentElement ())
{
e_.setUserData (user_data_keys::node, &n, 0);
}
private:
XSD_DOM_AUTO_PTR<xercesc::DOMDocument> 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 XSD_AUTO_PTR<dom_info>
clone (type& tree_node, container* c) const
{
// Check if we are a document root.
//
if (c == 0)
{
// We preserver DOM associations only in complete
// copies from root.
//
return XSD_AUTO_PTR<dom_info> ();
}
// 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 XSD_AUTO_PTR<dom_info> ();
// 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 XSD_AUTO_PTR<dom_info> (
new dom_attribute_info (static_cast<DOMAttr&> (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 XSD_AUTO_PTR<dom_info>
create (const xercesc::DOMElement& e, type& n, bool root)
{
return XSD_AUTO_PTR<dom_info> (
new dom_element_info (
const_cast<xercesc::DOMElement&> (e), n, root));
}
static XSD_AUTO_PTR<dom_info>
create (const xercesc::DOMAttr& a, type& n)
{
return XSD_AUTO_PTR<dom_info> (
new dom_attribute_info (
const_cast<xercesc::DOMAttr&> (a), n));
}
};
//@endcond
XSD_AUTO_PTR<dom_info> 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<const identity*, type*, identity_comparator>
map;
XSD_AUTO_PTR<map> map_;
// anyType and anySimpleType content.
//
protected:
//@cond
struct content_type
{
virtual
~content_type () {}
content_type () {}
virtual XSD_AUTO_PTR<content_type>
clone () const = 0;
virtual bool
compare (const content_type*) const = 0;
private:
content_type (const content_type&);
content_type& operator= (const content_type&);
};
struct dom_content_type: content_type
{
dom_content_type ()
: doc (xml::dom::create_document<char> ()), dom (*doc) {}
explicit
dom_content_type (const xercesc::DOMElement& e)
: doc (xml::dom::create_document<char> ()), dom (e, *doc) {}
explicit
dom_content_type (xercesc::DOMElement* e)
: doc (xml::dom::create_document<char> ()), dom (e, *doc) {}
explicit
dom_content_type (const dom_content_optional& d)
: doc (xml::dom::create_document<char> ()), dom (d, *doc) {}
virtual XSD_AUTO_PTR<content_type>
clone () const
{
return XSD_AUTO_PTR<content_type> (new dom_content_type (dom));
}
virtual bool
compare (const content_type* c) const
{
if (const dom_content_type* dc =
dynamic_cast<const dom_content_type*> (c))
return dom == dc->dom;
return false;
}
public:
XSD_DOM_AUTO_PTR<xercesc::DOMDocument> doc;
dom_content_optional dom;
};
mutable XSD_AUTO_PTR<content_type> content_;
//@endcond
private:
container* container_;
};
/**
* @brief Class corresponding to the XML Schema anySimpleType built-in
* type.
*
* @nosubgrouping
*/
template <typename C, typename B>
class simple_type: public B
{
public:
/**
* @name Constructors
*/
//@{
/**
* @brief Default constructor.
*/
simple_type ();
/**
* @brief Create an instance from a C string.
*
* @param s A string to initialize the instance with.
*/
simple_type (const C* s);
/**
* @brief Create an instance from a string.
*
* @param s A string to initialize the instance with.
*/
simple_type (const std::basic_string<C>& s);
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);
#ifdef XSD_CXX11
simple_type&
operator= (const simple_type&) = default;
#endif
/**
* @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 <typename S>
simple_type (istream<S>& s,
flags f = flags::extract_content,
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 = flags::extract_content,
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 = flags::extract_content,
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.
*/
simple_type (const std::basic_string<C>& s,
const xercesc::DOMElement* e,
flags f = flags::extract_content,
container* c = 0);
//@}
// anySimpleType content API.
//
public:
/**
* @brief Return a read-only (constant) reference to the anySimpleType
* text content.
*
* @return A constant reference to the text string.
*/
const std::basic_string<C>&
text_content () const;
/**
* @brief Return a read-write reference to the anySimpleType text
* content.
*
* @return A reference to the text string.
*/
std::basic_string<C>&
text_content ();
/**
* @brief Set the anySimpleType text content.
*
* @param t A new text string to set.
*/
void
text_content (const std::basic_string<C>& t);
protected:
//@cond
typedef typename B::content_type content_type;
struct text_content_type: content_type
{
text_content_type () {}
explicit
text_content_type (const std::basic_string<C>& t): text (t) {}
explicit
text_content_type (const C* t): text (t) {}
virtual XSD_AUTO_PTR<content_type>
clone () const
{
return XSD_AUTO_PTR<content_type> (new text_content_type (text));
}
virtual bool
compare (const content_type* c) const
{
if (const text_content_type* tc =
dynamic_cast<const text_content_type*> (c))
return text == tc->text;
return false;
}
public:
// It would have been more elegant to store text content as DOMText.
// However, that would require Xerces-C++ initialization. Also
// having a separate DOMDocument for each text node seems like
// an overkill.
//
std::basic_string<C> text;
};
//@endcond
};
/**
* @brief Base class for element types.
*
* This class is a base for every generated element type.
*
* @nosubgrouping
*/
template <typename C, typename T>
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<C>&
_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<C>&
_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 <typename T,
typename C,
schema_type::value ST = schema_type::other>
struct traits
{
typedef T type;
static XSD_AUTO_PTR<T>
create (const xercesc::DOMElement& e, flags f, container* c)
{
return XSD_AUTO_PTR<T> (new T (e, f, c));
}
static XSD_AUTO_PTR<T>
create (const xercesc::DOMAttr& a, flags f, container* c)
{
return XSD_AUTO_PTR<T> (new T (a, f, c));
}
static XSD_AUTO_PTR<T>
create (const std::basic_string<C>& s,
const xercesc::DOMElement* e,
flags f,
container* c)
{
return XSD_AUTO_PTR<T> (new T (s, e, f, c));
}
// For now for istream we only go through traits for non-
// fundamental types.
//
template <typename S>
static XSD_AUTO_PTR<T>
create (istream<S>& s, flags f, container* c)
{
return XSD_AUTO_PTR<T> (new T (s, f, c));
}
};
template <typename B,
typename C,
schema_type::value ST>
struct traits<simple_type<C, B>, C, ST>
{
typedef simple_type<C, B> type;
static XSD_AUTO_PTR<type>
create (const xercesc::DOMElement& e, flags f, container* c)
{
return XSD_AUTO_PTR<type> (
new type (e, f | flags::extract_content, c));
}
static XSD_AUTO_PTR<type>
create (const xercesc::DOMAttr& a, flags f, container* c)
{
return XSD_AUTO_PTR<type> (
new type (a, f | flags::extract_content, c));
}
static XSD_AUTO_PTR<type>
create (const std::basic_string<C>& s,
const xercesc::DOMElement* e,
flags f,
container* c)
{
return XSD_AUTO_PTR<type> (
new type (s, e, f | flags::extract_content, c));
}
template <typename S>
static XSD_AUTO_PTR<type>
create (istream<S>& s, flags f, container* c)
{
return XSD_AUTO_PTR<type> (
new type (s, f | flags::extract_content, c));
}
};
//@endcond
/**
* @brief Class template that emulates inheritance from a
* fundamental C++ type.
*
* @nosubgrouping
*/
template <typename T,
typename C,
typename B,
schema_type::value ST = schema_type::other>
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_)
{
}
#ifdef XSD_CXX11
fundamental_base&
operator= (const fundamental_base&) = default;
#endif
/**
* @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 <typename S>
fundamental_base (istream<S>& 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<C>& 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 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 <typename T2>
operator T2 () const
{
return x_;
}
/**
* @brief Implicitly convert the instance to another type.
*
* @return A value converted to the target type.
*/
template <typename T2>
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 <typename T, typename C, typename B, schema_type::value ST>
inline bool
operator== (const fundamental_base<T, C, B, ST>& x,
const fundamental_base<T, C, B, ST>& 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 <typename T, typename C, typename B, schema_type::value ST>
inline bool
operator!= (const fundamental_base<T, C, B, ST>& x,
const fundamental_base<T, C, B, ST>& y)
{
T x_ (x);
T y_ (y);
return x_ != y_;
}
//@cond
// Comparator for enum tables.
//
template <typename C>
struct enum_comparator
{
enum_comparator (const C* const* table)
: table_ (table)
{
}
bool
operator() (std::size_t i, const std::basic_string<C>& s) const
{
return table_[i] < s;
}
bool
operator() (const std::basic_string<C>& s, std::size_t i) const
{
return s < table_[i];
}
// This overload shouldn't be necessary according to the standard
// and removing it doesn't appear to trip any old compilers that
// we still support. But let's keeps preprocessed-out until we
// go C++11-only.
//
#if 0
bool
operator() (std::size_t i, std::size_t j) const
{
return std::basic_string<C> (table_[i]) < table_[j];
}
#endif
private:
const C* const* table_;
};
//@endcond
}
}
}
#include <xsd/cxx/tree/elements.ixx>
#include <xsd/cxx/tree/elements.txx>
#endif // XSD_CXX_TREE_ELEMENTS_HXX