diff options
Diffstat (limited to 'xsd/cxx/tree/tree-source.cxx')
-rw-r--r-- | xsd/cxx/tree/tree-source.cxx | 3912 |
1 files changed, 3912 insertions, 0 deletions
diff --git a/xsd/cxx/tree/tree-source.cxx b/xsd/cxx/tree/tree-source.cxx new file mode 100644 index 0000000..89419af --- /dev/null +++ b/xsd/cxx/tree/tree-source.cxx @@ -0,0 +1,3912 @@ +// file : xsd/cxx/tree/tree-source.cxx +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <map> +#include <list> + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +#include <xsd/cxx/tree/tree-source.hxx> +#include <xsd/cxx/tree/default-value.hxx> + +using namespace std; + +namespace CXX +{ + namespace Tree + { + namespace + { + struct List: Traversal::List, Context + { + List (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& l) + { + String name (ename (l)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (l, name) && !name) + return; + + os << "// " << name << endl + << "//" << endl + << endl; + + if (!options.suppress_parsing ()) + { + SemanticGraph::Type& item_type (l.argumented ().type ()); + String base (L"::xsd::cxx::tree::list< " + + item_type_name (item_type) + L", " + char_type); + + if (item_type.is_a<SemanticGraph::Fundamental::Double> ()) + base += L", ::xsd::cxx::tree::schema_type::double_"; + else if (item_type.is_a<SemanticGraph::Fundamental::Decimal> ()) + base += L", ::xsd::cxx::tree::schema_type::decimal"; + + base += L" >"; + + // c-tor (xercesc::DOMElement) + // + os << name << "::" << endl + << name << " (const " << xerces_ns << "::DOMElement& e," << endl + << flags_type << " f," << endl + << container << "* c)" << endl + << ": " << any_simple_type << " (e, f, c)," << endl + << " " << base << " (e, f, this)" + << "{" + << "}"; + + // c-tor (xercesc::DOMAttr) + // + os << name << "::" << endl + << name << " (const " << xerces_ns << "::DOMAttr& a," << endl + << flags_type << " f," << endl + << container << "* c)" << endl + << ": " << any_simple_type << " (a, f, c)," << endl + << " " << base << " (a, f, this)" + << "{" + << "}"; + + // c-tor (string const&, xercesc::DOMElement) + // + os << name << "::" << endl + << name << " (const " << string_type << "& s," << endl + << "const " << xerces_ns << "::DOMElement* e," << endl + << flags_type << " f," << endl + << container << "* c)" << endl + << ": " << any_simple_type << " (s, e, f, c)," << endl + << " " << base << " (s, e, f, this)" + << "{" + << "}"; + } + + // _clone + // + os << name << "* " << name << "::" << endl + << "_clone (" << flags_type << " f," << endl + << container << "* c) const" + << "{" + << "return new class " << name << " (*this, f, c);" + << "}"; + + // d-tor + // + os << name << "::" << endl + << "~" << name << " ()" + << "{" + << "}"; + + // Register with type factory map. + // + if (polymorphic && polymorphic_p (l)) + { + // Note that we are using the original type name. + // + String const& name (ename (l)); + + // If this type is anonymous but substitutes, then it will + // be registered as part of the substitution registration. + // + if (!anonymous_p (l) && !options.suppress_parsing ()) + { + os << "static" << endl + << "const ::xsd::cxx::tree::type_factory_initializer< " << + poly_plate << ", " << char_type << ", " << name << " >" << endl + << "_xsd_" << name << "_type_factory_init (" << endl + << strlit (l.name ()) << "," << endl + << strlit (xml_ns_name (l)) << ");" + << endl; + } + + if ((!anonymous_p (l) || anonymous_substitutes_p (l)) && + options.generate_comparison ()) + { + os << "static" << endl + << "const ::xsd::cxx::tree::comparison_initializer< " << + poly_plate << ", " << char_type << ", " << name << " >" << endl + << "_xsd_" << name << "_comparison_init;" + << endl; + } + } + } + + private: + String + item_type_name (SemanticGraph::Type& t) + { + std::wostringstream o; + + MemberTypeName type (*this, o); + type.dispatch (t); + + return o.str (); + } + }; + + + struct Union: Traversal::Union, Context + { + Union (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& u) + { + String name (ename (u)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (u, name) && !name) + return; + + String const& base (xs_string_type); + + os << "// " << name << endl + << "//" << endl + << endl; + + if (!options.suppress_parsing ()) + { + // c-tor (xercesc::DOMElement) + // + os << name << "::" << endl + << name << " (const " << xerces_ns << "::DOMElement& e," << endl + << flags_type << " f," << endl + << container << "* c)" << endl + << ": " << base << " (e, f, c)" + << "{" + << "}"; + + // c-tor (xercesc::DOMAttr) + // + os << name << "::" << endl + << name << " (const " << xerces_ns << "::DOMAttr& a," << endl + << flags_type << " f," << endl + << container << "* c)" << endl + << ": " << base << " (a, f, c)" + << "{" + << "}"; + + // c-tor (string const&, xercesc::DOMElement) + // + os << name << "::" << endl + << name << " (const " << string_type << "& s," << endl + << "const " << xerces_ns << "::DOMElement* e," << endl + << flags_type << " f," << endl + << container << "* c)" << endl + << ": " << base << " (s, e, f, c)" + << "{" + << "}"; + } + + // _clone + // + os << name << "* " << name << "::" << endl + << "_clone (" << flags_type << " f," << endl + << container << "* c) const" + << "{" + << "return new class " << name << " (*this, f, c);" + << "}"; + + // Register with type factory map. + // + if (polymorphic && polymorphic_p (u)) + { + // Note that we are using the original type name. + // + String const& name (ename (u)); + + // If this type is anonymous but substitutes, then it will + // be registered as part of the substitution registration. + // + if (!anonymous_p (u) && !options.suppress_parsing ()) + { + os << "static" << endl + << "const ::xsd::cxx::tree::type_factory_initializer< " << + poly_plate << ", " << char_type << ", " << name << " >" << endl + << "_xsd_" << name << "_type_factory_init (" << endl + << strlit (u.name ()) << "," << endl + << strlit (xml_ns_name (u)) << ");" + << endl; + } + + if ((!anonymous_p (u) || anonymous_substitutes_p (u)) && + options.generate_comparison ()) + { + os << "static" << endl + << "const ::xsd::cxx::tree::comparison_initializer< " << + poly_plate << ", " << char_type << ", " << name << " >" << endl + << "_xsd_" << name << "_comparison_init;" + << endl; + } + } + } + }; + + + // Enumeration mapping. + // + + struct EnumeratorLiteral: Traversal::Enumerator, Context + { + EnumeratorLiteral (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& e) + { + os << strlit (e.name ()); + } + }; + + + // + // + struct LiteralInfo + { + LiteralInfo (String const& value, String const& name) + : value_ (value), name_ (name) + { + } + + String value_; + String name_; + }; + + bool + operator< (LiteralInfo const& x, LiteralInfo const& y) + { + return x.value_ < y.value_; + } + + typedef list<LiteralInfo> LiteralInfoList; + + + // Populate LiteralInfoList + // + struct EnumeratorLiteralInfo: Traversal::Enumerator, Context + + { + EnumeratorLiteralInfo (Context& c, LiteralInfoList& list) + : Context (c), list_ (list) + { + } + + virtual void + traverse (Type& e) + { + list_.push_back (LiteralInfo (e.name (), ename (e))); + } + + private: + LiteralInfoList& list_; + }; + + + struct Enumeration: Traversal::Enumeration, Context + { + Enumeration (Context& c) + : Context (c), enumerator_literal_ (c) + { + names_enumerator_literal_ >> enumerator_literal_; + } + + virtual void + traverse (Type& e) + { + String name (ename (e)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (e, name) && !name) + return; + + bool string_based (false); + { + IsStringBasedType t (string_based); + t.dispatch (e); + } + + SemanticGraph::Enumeration* be (0); + bool enum_based (false); + if (string_based) + { + IsEnumBasedType t (be); + t.dispatch (e); + + enum_based = (be != 0); + } + + String value; + if (string_based) + value = evalue (e); + + size_t enum_count (0); + + for (Type::NamesIterator i (e.names_begin ()), end (e.names_end ()); + i != end; ++i) + ++enum_count; + + String base; // base type name + { + std::wostringstream o; + + BaseTypeName base_type (*this, o); + Traversal::Inherits inherits_type (base_type); + + inherits (e, inherits_type); + base = o.str (); + } + + os << "// " << name << endl + << "//" << endl + << endl; + + if (!options.suppress_parsing ()) + { + // c-tor (xercesc::DOMElement) + // + os << name << "::" << endl + << name << " (const " << xerces_ns << "::DOMElement& e," << endl + << flags_type << " f," << endl + << container << "* c)" << endl + << ": " << base << " (e, f, c)" + << "{"; + + if (string_based) + os << "_xsd_" << name << "_convert ();"; + + os << "}"; + + + // c-tor (xercesc::DOMAttr) + // + os << name << "::" << endl + << name << " (const " << xerces_ns << "::DOMAttr& a," << endl + << flags_type << " f," << endl + << container << "* c)" << endl + << ": " << base << " (a, f, c)" + << "{"; + + if (string_based) + { + os << "_xsd_" << name << "_convert ();"; + } + + os << "}"; + + + // c-tor (string const&, xercesc::DOMElement) + // + os << name << "::" << endl + << name << " (const " << string_type << "& s," << endl + << "const " << xerces_ns << "::DOMElement* e," << endl + << flags_type << " f," << endl + << container << "* c)" << endl + << ": " << base << " (s, e, f, c)" + << "{"; + + if (string_based) + { + os << "_xsd_" << name << "_convert ();"; + } + + os << "}"; + } + + // _clone + // + os << name << "* " << name << "::" << endl + << "_clone (" << flags_type << " f," << endl + << container << "* c) const" + << "{" + << "return new class " << name << " (*this, f, c);" + << "}"; + + // convert + // + // @@ TODO: expected list + // + if (string_based) + { + String i_name (L"_xsd_" + name + L"_indexes_"); + + os << name << "::" << value << " " << + name << "::" << endl + << "_xsd_" << name << "_convert () const" + << "{" + << "::xsd::cxx::tree::enum_comparator< " << char_type << + " > c (_xsd_" << name << "_literals_);" + << "const " << value << "* i (::std::lower_bound (" << endl + << i_name << "," << endl + << i_name << " + " << enum_count << "," << endl + << "*this," << endl + << "c));" + << endl + << "if (i == " << i_name << " + " << enum_count << " || " << + "_xsd_" << name << "_literals_[*i] != *this)" + << "{" + << "throw ::xsd::cxx::tree::unexpected_enumerator < " << + char_type << " > (*this);" + << "}" + << "return *i;" + << "}"; + } + + // literals and indexes + // + if (string_based) + { + if (enum_based) + { + os << "const " << char_type << "* const* " << name << "::" << endl + << "_xsd_" << name << "_literals_ = " << + fq_name (*be) << "::_xsd_" << ename (*be) << "_literals_;" + << endl; + } + else + { + os << "const " << char_type << "* const " << name << "::" << endl + << "_xsd_" << name << "_literals_[" << enum_count << "] =" + << "{"; + + names<Enumeration> ( + e, names_enumerator_literal_, 0, 0, 0, &Enumeration::comma); + + os << "};"; + } + + + LiteralInfoList l; + { + EnumeratorLiteralInfo enumerator (*this, l); + Traversal::Names names_enumerator (enumerator); + names (e, names_enumerator); + } + + l.sort (); + + os << "const " << name << "::" << value << " " << + name << "::" << endl + << "_xsd_" << name << "_indexes_[" << enum_count << "] =" + << "{"; + + String fq_name (ns_scope + L"::" + name); + + for (LiteralInfoList::iterator + b (l.begin ()), i (b), end (l.end ()); i != end; ++i) + { + if (i != b) + os << "," << endl; + + os << fq_name << "::" << i->name_; + } + + os << "};"; + } + + // Register with type factory map. + // + if (polymorphic && polymorphic_p (e)) + { + // Note that we are using the original type name. + // + String const& name (ename (e)); + + // If this type is anonymous but substitutes, then it will + // be registered as part of the substitution registration. + // + if (!anonymous_p (e) && !options.suppress_parsing ()) + { + os << "static" << endl + << "const ::xsd::cxx::tree::type_factory_initializer< " << + poly_plate << ", " << char_type << ", " << name << " >" << endl + << "_xsd_" << name << "_type_factory_init (" << endl + << strlit (e.name ()) << "," << endl + << strlit (xml_ns_name (e)) << ");" + << endl; + } + + if ((!anonymous_p (e) || anonymous_substitutes_p (e)) && + options.generate_comparison ()) + { + os << "static" << endl + << "const ::xsd::cxx::tree::comparison_initializer< " << + poly_plate << ", " << char_type << ", " << name << " >" << endl + << "_xsd_" << name << "_comparison_init;" + << endl; + } + } + } + + virtual void + comma (Type&) + { + os << "," << endl; + } + + private: + Traversal::Names names_enumerator_literal_; + EnumeratorLiteral enumerator_literal_; + + }; + + // + // + struct Member: Traversal::Member, Context + { + Member (Context& c, String const& scope) + : Context (c), scope_ (scope), init_value_ (c) + { + } + + virtual void + traverse (Type& m) + { + if (skip (m)) + return; + + // default_value + // + if (m.default_p ()) + { + SemanticGraph::Type& t (m.type ()); + bool simple (true); + + if (m.is_a<SemanticGraph::Element> ()) + { + IsSimpleType test (simple); + test.dispatch (t); + } + + if (simple) + { + bool lit (false); + { + IsLiteralValue test (lit); + test.dispatch (t); + } + + if (!lit) + { + InitKind::Kind kind (InitKind::simple); + { + InitKind test (kind); + test.dispatch (t); + } + + String const& member (edefault_value_member (m)); + + String init_name; + + switch (kind) + { + case InitKind::data: + { + init_name = escape (L"_xsd_" + scope_ + member + L"data"); + init_value_.data (init_name); + init_value_.dispatch (t, m.value ()); + break; + } + case InitKind::function: + { + init_name = escape (L"_xsd_" + scope_ + member + L"init"); + + os << "static " << scope_ << "::" << etype (m) << endl + << init_name << " ()" + << "{" + << scope_ << "::" << etype (m) << " r;" + << endl; + + init_value_.dispatch (t, m.value ()); + + os << "return r;" + << "};"; + break; + } + case InitKind::simple: + break; + } + + os << "const " << scope_ << "::" << etype (m) << " " << + scope_ << "::" << member << " (" << endl; + + switch (kind) + { + case InitKind::data: + { + // Second dispatch. + // + init_value_.dispatch (t, m.value ()); + break; + } + case InitKind::function: + { + os << init_name << " ()"; + break; + } + case InitKind::simple: + { + init_value_.dispatch (t, m.value ()); + break; + } + } + + os << ");" + << endl; + } + } + } + } + + private: + String scope_; + InitValue init_value_; + }; + + + struct Element: Traversal::Element, Context + { + Element (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& e) + { + if (skip (e)) + return; + + SemanticGraph::Complex& c ( + dynamic_cast<SemanticGraph::Complex&> (e.scope ())); + + String const& member (emember (e)); + + String tr (etraits (e)); // traits type name + String type (etype (e)); + + SemanticGraph::Type& t (e.type ()); + + bool fund (false); + { + IsFundamentalType traverser (fund); + traverser.dispatch (t); + } + + // Check if we need to handle xsi:type and substitution groups. + // If this element's type is anonymous then we don't need to do + // anything. Note that if the type is anonymous then it can't be + // derived from which makes it impossible to substitute or + // dynamically-type with xsi:type. + // + bool poly (polymorphic && polymorphic_p (t) && !anonymous_p (t)); + + os << "// " << comment (e.name ()) << endl + << "//" << endl; + + if (poly) + { + os << "{" + << auto_ptr << "< ::xsd::cxx::tree::type > tmp (" << endl + << "::xsd::cxx::tree::type_factory_map_instance< " << + poly_plate << ", " << char_type << " > ().create (" << endl + << strlit (e.name ()) << "," << endl + << (e.qualified_p () + ? strlit (e.namespace_ ().name ()) + : L + String ("\"\"")) << "," << endl; + + SemanticGraph::Complex* tc; + if ((tc = dynamic_cast<SemanticGraph::Complex*> (&t)) != 0 && + tc->abstract_p ()) + os << "0,"; + else + os << "&::xsd::cxx::tree::factory_impl< " << type << " >,"; + + os << endl + << (e.global_p () ? "true" : "false") << ", " << + (e.qualified_p () ? "true" : "false") << ", " << + "i, n, f, this));" + << endl + << "if (tmp.get () != 0)" + << "{"; + } + else + { + if (e.qualified_p () && e.namespace_ ().name ()) + { + os << "if (n.name () == " << strlit (e.name ()) << " && " << + "n.namespace_ () == " << strlit (e.namespace_ ().name ()) << ")" + << "{"; + } + else + { + os << "if (n.name () == " << strlit (e.name ()) << " && " << + "n.namespace_ ().empty ())" + << "{"; + } + + if (!fund) + { + os << auto_ptr << "< " << type << " > r (" << endl + << tr << "::create (i, f"; + + if (t.is_a<SemanticGraph::AnyType> () && + options.generate_any_type ()) + os << " | " << flags_type << "::extract_content"; + + os << ", this));" + << endl; + } + } + + + // Checks. Disabled at the moment since they make it impossible to + // parse valid instances where the same element is used in both + // base and derived types. See the cxx/tree/name-clash/inheritance + // test for details. + // + // + if (max (e) != 1) + { + // sequence + // + } + else if (min (e) == 0) + { + // optional + // + os << "if (!this->" << member << ")" + << "{"; + } + else + { + // one + // + os << "if (!" << member << ".present ())" + << "{"; + } + + + if (poly || !fund) + { + if (poly) + { + // Cast to static type. + // + os << auto_ptr << "< " << type << " > r (" << endl + << "dynamic_cast< " << type << "* > (tmp.get ()));" + << endl + << "if (r.get ())" << endl + << "tmp.release ();" + << "else" << endl + << "throw ::xsd::cxx::tree::not_derived< " << char_type << + " > ();" + << endl; + } + + char const* r (std >= cxx_version::cxx11 ? "::std::move (r)" : "r"); + + if (max (e) != 1) + { + // sequence + // + os << "this->" << member << ".push_back (" << r << ");"; + } + else if (min (e) == 0) + { + // optional + // + os << "this->" << member << ".set (" << r << ");"; + } + else + { + // one + // + os << "this->" << member << ".set (" << r << ");"; + } + } + else + { + if (max (e) != 1) + { + // sequence + // + os << "this->" << member << ".push_back (" << tr << + "::create (i, f, this));"; + } + else if (min (e) == 0) + { + // optional + // + os << "this->" << member << ".set (" << tr << + "::create (i, f, this));"; + } + else + { + // one + // + os << "this->" << member << ".set (" << tr << + "::create (i, f, this));"; + } + } + + // Capture order. + // + if (ordered_p (c)) + { + SemanticGraph::Context& ctx (c.context ()); + + String const& t (ctx.get<String> ("order-type")); + String const& m (ctx.get<String> ("order-member")); + + os << "this->" << m << ".push_back (" << endl + << t << " (" << + e.context ().get<String> ("ordered-id-name"); + + // sequence + // + if (max (e) != 1) + os << ", " << "this->" << member << ".size () - 1"; + + os << "));"; + } + + os << "continue;"; + + // End of check block. + // + if (max (e) != 1) + { + // sequence + // + } + else if (min (e) == 0) + { + // optional + // + os << "}"; + } + else + { + // one + // + os << "}"; + } + + os << "}"; // if block + + if (poly) + os << "}"; + } + }; + + struct ElementTest: Traversal::Element, Context + { + ElementTest (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& e) + { + if (skip (e)) + return; + + if (max (e) == 1 && min (e) == 1) + { + // one + // + os << "if (!" << emember (e) << ".present ())" + << "{" + << "throw ::xsd::cxx::tree::expected_element< " << + char_type << " > (" << endl + << strlit (e.name ()) << "," << endl + << (e.qualified_p () + ? strlit (e.namespace_ ().name ()) + : L + String ("\"\"")) << ");" + << "}"; + } + } + }; + + struct Any: Traversal::Any, Context + { + Any (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& a) + { + String const& member (emember (a)); + + SemanticGraph::Complex& c ( + dynamic_cast<SemanticGraph::Complex&> (a.scope ())); + + String const& ns (a.definition_namespace ().name ()); + String const& dom_doc (edom_document (c)); + + os << "// " << ename (a) << endl + << "//" << endl + << "if ("; + + for (SemanticGraph::Any::NamespaceIterator i (a.namespace_begin ()), + e (a.namespace_end ()); i != e;) + { + if (*i == L"##any") + { + os << "true"; + } + else if (*i == L"##other") + { + if (ns) + { + // Note that here I assume that ##other does not include + // unqualified names in a schema with target namespace. + // This is not what the spec says but that seems to be + // the consensus. + // + os << "(!n.namespace_ ().empty () && " << + "n.namespace_ () != " << strlit (ns) << ")"; + } + else + os << "!n.namespace_ ().empty ()"; + } + else if (*i == L"##local") + { + os << "n.namespace_ ().empty ()"; + } + else if (*i == L"##targetNamespace") + { + os << "n.namespace_ () == " << strlit (ns); + } + else + { + os << "n.namespace_ () == " << strlit (*i); + } + + if (++i != e) + os << " ||" << endl; + } + + os << ")" + << "{"; + + + // Checks. + // + // + if (max (a) != 1) + { + // sequence + // + } + else if (min (a) == 0) + { + // optional + // + os << "if (!this->" << member << ")" + << "{"; + } + else + { + // one + // + os << "if (!" << member << ".present ())" + << "{"; + } + + os << xerces_ns << "::DOMElement* r (" << endl + << "static_cast< " << xerces_ns << "::DOMElement* > (" << endl + << "this->" << dom_doc << " ().importNode (" << endl + << "const_cast< " << xerces_ns << "::DOMElement* > (&i), true)));"; + + if (max (a) != 1) + { + // sequence + // + os << "this->" << member << ".push_back (r);"; + } + else if (min (a) == 0) + { + // optional + // + os << "this->" << member << ".set (r);"; + } + else + { + // one + // + os << "this->" << member << ".set (r);"; + } + + // Capture order. + // + if (ordered_p (c)) + { + SemanticGraph::Context& ctx (c.context ()); + + String const& t (ctx.get<String> ("order-type")); + String const& m (ctx.get<String> ("order-member")); + + os << "this->" << m << ".push_back (" << endl + << t << " (" << + a.context ().get<String> ("ordered-id-name") << ", "; + + if (max (a) != 1) + // sequence + // + os << "this->" << member << ".size () - 1"; + else + // optional & one + // + os << "0"; + + os << "));"; + } + + os << "continue;"; + + // End of check block. + // + if (max (a) != 1) + { + // sequence + // + } + else if (min (a) == 0) + { + // optional + // + os << "}"; + } + else + { + // one + // + os << "}"; + } + + os << "}"; // if block + } + }; + + struct AnyTest: Traversal::Any, Context + { + AnyTest (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& a) + { + if (max (a) == 1 && min (a) == 1) + { + // one + // + os << "if (!" << emember (a) << ".present ())" + << "{" + << "throw ::xsd::cxx::tree::expected_element< " << + char_type << " > (" << endl + << L << "\"*\"," << endl + << strlit (*a.namespace_begin ()) << ");" + << "}"; + } + } + }; + + struct Attribute: Traversal::Attribute, Context + { + Attribute (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& a) + { + String const& member (emember (a)); + + String const& tr (etraits (a)); // traits type name + + if (a.qualified_p () && a.namespace_ ().name ()) + { + os << "if (n.name () == " << strlit (a.name ()) << " && " << + "n.namespace_ () == " << strlit (a.namespace_ ().name ()) << ")" + << "{"; + } + else + { + os << "if (n.name () == " << strlit (a.name ()) << " && " << + "n.namespace_ ().empty ())" + << "{"; + } + + os << "this->" << member << ".set (" << tr << + "::create (i, f, this));"; + + os << "continue;" + << "}"; + + } + }; + + struct AnyAttribute: Traversal::AnyAttribute, Context + { + AnyAttribute (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& a) + { + String const& member (emember (a)); + + String const& ns (a.definition_namespace ().name ()); + String const& dom_doc ( + edom_document ( + dynamic_cast<SemanticGraph::Complex&> (a.scope ()))); + + os << "// " << ename (a) << endl + << "//" << endl + << "if ("; + + // Note that we need to filter out namespaces for xmlns and + // xsi. + // + for (SemanticGraph::Any::NamespaceIterator i (a.namespace_begin ()), + e (a.namespace_end ()); i != e;) + { + if (*i == L"##any") + { + os << "(n.namespace_ () != " << + "::xsd::cxx::xml::bits::xmlns_namespace< " << char_type << + " > () &&" << endl + << "n.namespace_ () != " << + "::xsd::cxx::xml::bits::xsi_namespace< " << char_type << + " > ())"; + } + else if (*i == L"##other") + { + if (ns) + { + // Note that here I assume that ##other does not include + // unqualified names in a schema with target namespace. + // This is not what the spec says but that seems to be + // the consensus. + // + os << "(!n.namespace_ ().empty () &&" << endl + << "n.namespace_ () != " << strlit (ns) << " &&" <<endl + << "n.namespace_ () != " << + "::xsd::cxx::xml::bits::xmlns_namespace< " << char_type << + " > () &&" << endl + << "n.namespace_ () != " << + "::xsd::cxx::xml::bits::xsi_namespace< " << char_type << + " > ())"; + } + else + os << "(!n.namespace_ ().empty () &&" << endl + << "n.namespace_ () != " << + "::xsd::cxx::xml::bits::xmlns_namespace< " << char_type << + " > () &&" << endl + << "n.namespace_ () != " << + "::xsd::cxx::xml::bits::xsi_namespace< " << char_type << + " > ())"; + } + else if (*i == L"##local") + { + os << "n.namespace_ ().empty ()"; + } + else if (*i == L"##targetNamespace") + { + os << "n.namespace_ () == " << strlit (ns); + } + else + { + os << "n.namespace_ () == " << strlit (*i); + } + + if (++i != e) + os << " ||" << endl; + } + + os << ")" + << "{" + << xerces_ns << "::DOMAttr* r (" << endl + << "static_cast< " << xerces_ns << "::DOMAttr* > (" << endl + << "this->" << dom_doc << " ().importNode (" << endl + << "const_cast< " << xerces_ns << "::DOMAttr* > (&i), true)));" + << "this->" << member << " .insert (r);" + << "continue;" + << "}"; + } + }; + + + struct AttributeTest: Traversal::Attribute, Context + { + AttributeTest (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& a) + { + String const& member (emember (a)); + + if (!a.optional_p () || a.default_p ()) + { + os << "if (!" << member << ".present ())" + << "{"; + + if (a.default_p ()) + { + os << "this->" << member << ".set (" << + edefault_value (a) << " ());"; + } + else + os << "throw ::xsd::cxx::tree::expected_attribute< " << + char_type << " > (" << endl + << strlit (a.name ()) << "," << endl + << (a.qualified_p () + ? strlit (a.namespace_ ().name ()) + : L + String ("\"\"")) << ");"; + + os << "}"; + } + } + }; + + + // + // + struct CtorBase: Traversal::Complex, + Traversal::Enumeration, + Traversal::Type, + Context + { + // If base_arg is empty then no base argument is generated. + // + CtorBase (Context& c, CtorArgType at, String const& base_arg) + : Context (c), args_ (c, at, base_arg) + { + } + + virtual void + traverse (SemanticGraph::Type&) + { + if (args_.base_arg_) + os << args_.base_arg_; + } + + virtual void + traverse (SemanticGraph::Enumeration&) + { + if (args_.base_arg_) + os << args_.base_arg_; + } + + void + traverse (SemanticGraph::Complex& c) + { + args_.traverse (c); + } + + private: + // No need to traverse AnyAttribute since it is always mapped + // to a sequence. + // + struct Args: Traversal::Complex, + Traversal::Enumeration, + Traversal::Type, + Traversal::Any, + Traversal::Element, + Traversal::Attribute, + Context + { + Args (Context& c, CtorArgType at, String const& base_arg) + : Context (c), + arg_type_ (at), base_arg_ (base_arg), first_ (true) + { + *this >> inherits_ >> *this; + *this >> names_ >> *this; + } + + virtual void + traverse (SemanticGraph::Type&) + { + if (base_arg_) + os << comma () << base_arg_; + } + + virtual void + traverse (SemanticGraph::Enumeration&) + { + if (base_arg_) + os << comma () << base_arg_; + } + + virtual void + traverse (SemanticGraph::Any& a) + { + if (!options.generate_wildcard ()) + return; + + if (min (a) == 1 && max (a) == 1) + { + // one + // + os << comma () << ename (a); + } + } + + virtual void + traverse (SemanticGraph::Element& e) + { + if (!skip (e) && min (e) == 1 && max (e) == 1) + { + // one + // + bool move (false); + + if (std >= cxx_version::cxx11) + { + switch (arg_type_) + { + case CtorArgType::complex_auto_ptr: + { + bool simple (true); + IsSimpleType t (simple); + t.dispatch (e.type ()); + move = !simple; + break; + } + case CtorArgType::poly_auto_ptr: + { + move = polymorphic && polymorphic_p (e.type ()); + break; + } + case CtorArgType::type: + break; + } + } + + os << comma () << (move ? "std::move (" : "") << ename (e) << + (move ? ")" : ""); + } + } + + virtual void + traverse (SemanticGraph::Attribute& a) + { + // Note that we are not including attributes with default + // or required fixed values here. + // + if (min (a) == 1 && !a.fixed_p ()) + { + // one + // + os << comma () << ename (a); + } + } + + using Complex::traverse; + + private: + String + comma () + { + bool tmp (first_); + first_ = false; + return tmp ? "" : ",\n"; + } + + public: + CtorArgType arg_type_; + String base_arg_; + + private: + bool first_; + + Traversal::Inherits inherits_; + Traversal::Names names_; + }; + + Args args_; + }; + + + struct CtorMember: Traversal::Element, + Traversal::Attribute, + Context + { + CtorMember (Context& c, CtorArgType at) + : Context (c), arg_type_ (at) + { + } + + virtual void + traverse (SemanticGraph::Element& e) + { + if (skip (e)) + return; + + String const& member (emember (e)); + + if (max (e) != 1) + { + // sequence + // + os << "," << endl + << " " << member << " (this)"; + } + else if (min (e) == 0) + { + // optional + // + os << "," << endl + << " " << member << " (this)"; + } + else + { + // one + // + bool move (false); + + if (std >= cxx_version::cxx11) + { + switch (arg_type_) + { + case CtorArgType::complex_auto_ptr: + { + bool simple (true); + IsSimpleType t (simple); + t.dispatch (e.type ()); + move = !simple; + break; + } + case CtorArgType::poly_auto_ptr: + { + move = polymorphic && polymorphic_p (e.type ()); + break; + } + case CtorArgType::type: + break; + } + } + + os << "," << endl + << " " << member << " (" << (move ? "std::move (" : "") << + ename (e) << (move ? ")" : "") << ", this)"; + } + } + + virtual void + traverse (SemanticGraph::Attribute& a) + { + String const& member (emember (a)); + + bool def (a.default_p ()); + + if (min (a) == 0 && !def) + { + // optional + // + os << "," << endl + << " " << member << " (this)"; + } + else + { + // one + // + + if (def) + { + // This is an attribute with default or fixed value. We are + // going to initialize it to its default value. + // + os << "," << endl + << " " << member << " (" << + edefault_value (a) << " (), this)"; + } + else + { + os << "," << endl + << " " << member << " (" << ename (a) << ", this)"; + } + } + } + + private: + CtorArgType arg_type_; + }; + + struct CtorAny: Traversal::Any, + Traversal::AnyAttribute, + Context + { + CtorAny (Context& c) + : Context (c) + { + } + + virtual void + traverse (SemanticGraph::Any& a) + { + String const& member (emember (a)); + String const& dom_doc ( + edom_document ( + dynamic_cast<SemanticGraph::Complex&> (a.scope ()))); + + if (max (a) != 1) + { + // sequence + // + os << "," << endl + << " " << member << " (this->" << dom_doc << " ())"; + } + else if (min (a) == 0) + { + // optional + // + os << "," << endl + << " " << member << " (this->" << dom_doc << " ())"; + } + else + { + // one + // + os << "," << endl + << " " << member << " (" << ename (a) << ", this->" << + dom_doc << " ())"; + } + } + + virtual void + traverse (SemanticGraph::AnyAttribute& a) + { + String const& dom_doc ( + edom_document ( + dynamic_cast<SemanticGraph::Complex&> (a.scope ()))); + + os << "," << endl + << " " << emember (a) << " (this->" << dom_doc << " ())"; + } + }; + + + struct CopyMember: Traversal::Member, Context + { + CopyMember (Context& c, String const& arg_name_) + : Context (c), arg_name (arg_name_) + { + } + + virtual void + traverse (SemanticGraph::Member& m) + { + if (skip (m)) + return; + + String const& member (emember (m)); + + os << "," << endl + << " " << member << " (" << + arg_name << "." << member << ", f, this)"; + } + + private: + String arg_name; + }; + + struct CopyAny: Traversal::Any, + Traversal::AnyAttribute, + Context + { + CopyAny (Context& c, String const& arg_name_) + : Context (c), arg_name (arg_name_) + { + } + + virtual void + traverse (SemanticGraph::Any& a) + { + String const& member (emember (a)); + String const& dom_doc ( + edom_document ( + dynamic_cast<SemanticGraph::Complex&> (a.scope ()))); + + os << "," << endl + << " " << member << " (" << + arg_name << "." << member << ", this->" << dom_doc << " ())"; + } + + virtual void + traverse (SemanticGraph::AnyAttribute& a) + { + String const& member (emember (a)); + String const& dom_doc ( + edom_document ( + dynamic_cast<SemanticGraph::Complex&> (a.scope ()))); + + os << "," << endl + << " " << member << " (" << + arg_name << "." << member << ", this->" << dom_doc << " ())"; + } + + private: + String arg_name; + }; + + struct AssignMember: Traversal::Member, Context + { + AssignMember (Context& c) + : Context (c) + { + } + + virtual void + traverse (SemanticGraph::Member& m) + { + if (skip (m)) + return; + + String const& member (emember (m)); + os << "this->" << member << " = x." << member << ";"; + } + }; + + struct AssignAny: Traversal::Any, + Traversal::AnyAttribute, + Context + { + AssignAny (Context& c) + : Context (c) + { + } + + virtual void + traverse (SemanticGraph::Any& a) + { + String const& member (emember (a)); + os << "this->" << member << " = x." << member << ";"; + } + + virtual void + traverse (SemanticGraph::AnyAttribute& a) + { + String const& member (emember (a)); + os << "this->" << member << " = x." << member << ";"; + } + }; + + + // Element parsing c-tor initializers. + // + struct ElementCtorMember: Traversal::Member, Context + { + ElementCtorMember (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& m) + { + if (skip (m)) + return; + + String const& member (emember (m)); + + os << "," << endl + << " " << member << " (this)"; + } + }; + + struct ElementCtorAny: Traversal::Any, + Traversal::AnyAttribute, + Context + { + ElementCtorAny (Context& c) + : Context (c) + { + } + + virtual void + traverse (SemanticGraph::Any& a) + { + String const& member (emember (a)); + String const& dom_doc ( + edom_document ( + dynamic_cast<SemanticGraph::Complex&> (a.scope ()))); + + os << "," << endl + << " " << member << " (this->" << dom_doc << " ())"; + } + + virtual void + traverse (SemanticGraph::AnyAttribute& a) + { + String const& member (emember (a)); + String const& dom_doc ( + edom_document ( + dynamic_cast<SemanticGraph::Complex&> (a.scope ()))); + + os << "," << endl + << " " << member << " (this->" << dom_doc << " ())"; + } + }; + + + // Default c-tor member initializer. + // + struct DefaultCtorMemberInit: Traversal::Element, + Traversal::Attribute, + Context + { + DefaultCtorMemberInit (Context& c) + : Context (c) + { + } + + virtual void + traverse (SemanticGraph::Element& e) + { + if (skip (e)) + return; + + String const& member (emember (e)); + + os << "," << endl + << " " << member << " (this)"; + } + + virtual void + traverse (SemanticGraph::Attribute& a) + { + String const& member (emember (a)); + + if (a.default_p ()) + { + // This is an attribute with default or fixed value. We are + // going to initialize it to its default value. + // + os << "," << endl + << " " << member << " (" << + edefault_value (a) << " (), this)"; + } + else + os << "," << endl + << " " << member << " (this)"; + } + }; + + struct DefaultCtorAnyInit: Traversal::Any, + Traversal::AnyAttribute, + Context + { + DefaultCtorAnyInit (Context& c) + : Context (c) + { + } + + virtual void + traverse (SemanticGraph::Any& a) + { + String const& member (emember (a)); + String const& dom_doc ( + edom_document ( + dynamic_cast<SemanticGraph::Complex&> (a.scope ()))); + + os << "," << endl + << " " << member << " (this->" << dom_doc << " ())"; + } + + virtual void + traverse (SemanticGraph::AnyAttribute& a) + { + String const& member (emember (a)); + String const& dom_doc ( + edom_document ( + dynamic_cast<SemanticGraph::Complex&> (a.scope ()))); + + os << "," << endl + << " " << member << " (this->" << dom_doc << " ())"; + } + }; + + // Test whether the base has comparison operators. + // + struct HasComparisonOperator: Traversal::Fundamental::Type, + Traversal::List, + Traversal::Union, + Traversal::Complex, + Traversal::Enumeration, + Traversal::Member, + Traversal::Any, + Traversal::AnyAttribute, + Context + { + // generate should initially be false. + // + HasComparisonOperator (Context& c, bool& generate) + : Context (c), generate_ (generate) + { + *this >> inherits_ >> *this; + *this >> names_ >> *this; + } + + virtual void + traverse (SemanticGraph::Fundamental::Type&) + { + // All built-in types are comparable. + generate_ = true; + } + + virtual void + traverse (SemanticGraph::List&) + { + generate_ = true; + } + + virtual void + traverse (SemanticGraph::Union&) + { + generate_ = true; + } + + virtual void + traverse (SemanticGraph::Enumeration& e) + { + Traversal::Enumeration::inherits (e); + } + + virtual void + traverse (SemanticGraph::Complex& c) + { + Complex::names (c); + + if (!generate_) + Complex::inherits (c); + } + + virtual void + traverse (SemanticGraph::Member& m) + { + if (!skip (m)) + generate_ = true; + } + + virtual void + traverse (SemanticGraph::Any&) + { + if (options.generate_wildcard ()) + generate_ = true; + } + + virtual void + traverse (SemanticGraph::AnyAttribute&) + { + if (options.generate_wildcard ()) + generate_ = true; + } + + private: + bool& generate_; + + Traversal::Inherits inherits_; + Traversal::Names names_; + }; + + // + // + struct MemberComparison: Traversal::Element, + Traversal::Attribute, + Context + { + MemberComparison (Context& c) + : Context (c) + { + } + + virtual void + traverse (SemanticGraph::Element& e) + { + if (skip (e)) + return; + + String const& aname (eaname (e)); + + // Check if we need to handle xsi:type and substitution groups. + // If this element's type is anonymous then we don't need to do + // anything. Note that if the type is anonymous then it can't be + // derived from which makes it impossible to substitute or + // dynamically-type with xsi:type. + // + SemanticGraph::Type& t (e.type ()); + bool poly (polymorphic && polymorphic_p (t) && !anonymous_p (t)); + + if (!poly) + { + os << "if (!(x." << aname << " () == y." << aname << " ()))" << endl + << "return false;" + << endl; + } + else + { + os << "{" + << "::xsd::cxx::tree::comparison_map< " << char_type + << " >& cm (" << endl + << "::xsd::cxx::tree::comparison_map_instance< " << + poly_plate << ", " << char_type << " > ());" + << endl; + + if (max (e) != 1) + { + // sequence + // + String const& scope (ename (e.scope ())); + + os << scope << "::" << econtainer (e) << + " a (x." << aname << " ()), b (y." << aname << " ());" + << endl; + + os << "if (a.size () != b.size ())" << endl + << "return false;" + << endl; + + os << "for (" << scope << "::" << econst_iterator (e) << endl + << "ai (a.begin ()), bi (b.begin ()), " << + "ae (a.end ()), be (b.end ());" << endl + << "ai != ae; ++ai, ++bi)" + << "{" + << "if (!cm.compare (*ai, *bi))" << endl + << "return false;" + << "}"; + } + else if (min (e) == 0) + { + // optional + // + String const& scope (ename (e.scope ())); + + os << scope << "::" << econtainer (e) << + " a (x." << aname << " ()), b (y." << aname << " ());" + << endl; + + os << "if (!a || !b)" + << "{" + << "if (a.present () != b.present ())" << endl + << "return false;" + << "}" + << "else" + << "{" + << "if (!cm.compare (*a, *b))" << endl + << "return false;" + << "}"; + } + else + { + // one + // + os << "if (!cm.compare (x." << aname << " (), y." << + aname << " ()))" << endl + << "return false;"; + } + + os << "}"; + } + } + + virtual void + traverse (SemanticGraph::Attribute& a) + { + String const& aname (eaname (a)); + + os << "if (!(x." << aname << " () == y." << aname << " ()))" << endl + << "return false;" + << endl; + } + }; + + struct AnyComparison: Traversal::Any, + Traversal::AnyAttribute, + Context + { + AnyComparison (Context& c) + : Context (c) + { + } + + virtual void + traverse (SemanticGraph::Any& a) + { + String const& aname (eaname (a)); + + if (max (a) == 1 && min (a) == 1) + os << "if (!x." << aname << " ().isEqualNode (&y." << + aname << " ()))"; + else + os << "if (!(x." << aname << " () == y." << aname << " ()))"; + + os << endl + << "return false;" + << endl; + } + + virtual void + traverse (SemanticGraph::AnyAttribute& a) + { + String const& aname (eaname (a)); + + os << "if (!(x." << aname << " () == y." << aname << " ()))" << endl + << "return false;" + << endl; + } + }; + + // Check whether a type has a parse() function (i.e., has any + // members, recursively). + // + struct HasParseFunction: Traversal::Complex, + Traversal::Element, + Traversal::Any, + Traversal::Attribute, + Traversal::AnyAttribute, + Context + { + HasParseFunction (Context& c, bool& has_el, bool& has_at) + : Context (c), has_el_ (has_el), has_at_ (has_at) + { + *this >> names_ >> *this; + *this >> inherits_ >> *this; + } + + virtual void + traverse (SemanticGraph::Complex& c) + { + if (mixed_p (c) && !c.context ().count ("mixed-in-base")) + has_el_ = true; + + names (c); + + if (!(has_el_ && has_at_)) + inherits (c); + } + + virtual void + traverse (SemanticGraph::Element&) + { + has_el_ = true; + } + + virtual void + traverse (SemanticGraph::Any&) + { + has_el_ = true; + } + + virtual void + traverse (SemanticGraph::Attribute&) + { + has_at_ = true; + } + + virtual void + traverse (SemanticGraph::AnyAttribute&) + { + if (options.generate_wildcard ()) + has_at_ = true; + } + + private: + bool& has_el_; + bool& has_at_; + + Traversal::Names names_; + Traversal::Inherits inherits_; + }; + + // + // + struct FacetArray: Traversal::Complex, Context + { + FacetArray (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& c) + { + Facets f; + FacetCollector col (f); + col.traverse (c); + + for (Facets::const_iterator i (f.begin ()); i != f.end (); ++i) + { + if (i->first == L"fractionDigits") + os << "{::xsd::cxx::tree::facet::fraction_digits, " << + i->second << "UL}," << endl; + else if (i->first == L"totalDigits") + os << "{::xsd::cxx::tree::facet::total_digits, " << + i->second << "UL}," << endl; + } + } + + private: + typedef map<String, String> Facets; + + struct FacetCollector: Traversal::Complex + { + FacetCollector (Facets& facets) + : facets_ (facets) + { + *this >> inherits_ >> *this; + } + + virtual void + traverse (Type& c) + { + if (c.inherits_p ()) + { + // First collect our base so that we can override its + // facets. + // + inherits (c); + + using SemanticGraph::Restricts; + + if (Restricts* r = dynamic_cast<Restricts*> (&c.inherits ())) + { + if (!r->facet_empty ()) + { + Restricts::FacetIterator i (r->facet_find ("totalDigits")); + + if (i != r->facet_end ()) + facets_[i->first] = i->second; + + i = r->facet_find ("fractionDigits"); + + if (i != r->facet_end ()) + facets_[i->first] = i->second; + } + } + } + } + + private: + Traversal::Inherits inherits_; + Facets& facets_; + }; + }; + + // + // + struct Complex: Traversal::Complex, Context + { + Complex (Context& c) + : Context (c), + member_name_ (c), + any_ (c), + element_ (c), + any_test_ (c), + element_test_ (c), + attribute_ (c), + attribute_test_ (c), + any_attribute_ (c), + default_ctor_any_init_ (c), + default_ctor_member_init_ (c), + ctor_any_ (c), + ctor_member_ (c, CtorArgType::type), + element_ctor_any_ (c), + element_ctor_member_ (c), + assign_any_ (c), + assign_member_ (c), + comparison_any_ (c), + comparison_member_ (c), + facet_array_ (c) + { + bool gen_wildcard (options.generate_wildcard ()); + + inherits_member_ >> member_name_; + + names_element_ >> element_; + if (gen_wildcard) + names_element_ >> any_; + + names_element_test_ >> element_test_; + if (gen_wildcard) + names_element_test_ >> any_test_; + + names_attribute_ >> attribute_; + names_attribute_test_ >> attribute_test_; + names_any_attribute_ >> any_attribute_; + + default_ctor_init_names_ >> default_ctor_member_init_; + if (gen_wildcard) + default_ctor_init_names_ >> default_ctor_any_init_; + + ctor_names_ >> ctor_member_; + if (gen_wildcard) + ctor_names_ >> ctor_any_; + + element_ctor_names_ >> element_ctor_member_; + if (gen_wildcard) + element_ctor_names_ >> element_ctor_any_; + + assign_names_ >> assign_member_; + if (gen_wildcard) + assign_names_ >> assign_any_; + + comparison_names_ >> comparison_member_; + if (gen_wildcard) + comparison_names_ >> comparison_any_; + } + + + virtual void + traverse (Type& c) + { + bool gen_wildcard (options.generate_wildcard ()); + + String name (ename (c)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + bool renamed (renamed_type (c, name)); + if (renamed && !name) + return; + + SemanticGraph::Context& ctx (c.context ()); + + bool mixed (mixed_p (c) && !ctx.count ("mixed-in-base")); + bool ordered (ordered_p (c) && !ctx.count ("order-in-base")); + + bool string_based (false); + { + IsStringBasedType t (string_based); + t.dispatch (c); + } + + SemanticGraph::Enumeration* enum_base (0); + { + IsEnumBasedType t (enum_base); + t.dispatch (c); + } + + bool facets (false); + String base; // base type name + if (c.inherits_p ()) + { + // Get base name. + // + std::wostringstream o; + + BaseTypeName base_type (*this, o); + Traversal::Inherits inherits_type (base_type); + + // Cannot use inherits_none here because need the + // result in a string. + // + inherits (c, inherits_type); + + base = o.str (); + + // See if we have any facets that we need to handle. + // + using SemanticGraph::Restricts; + using SemanticGraph::Fundamental::Decimal; + + if (Restricts* r = dynamic_cast<Restricts*> (&c.inherits ())) + { + if (!r->facet_empty () && + (r->facet_find ("fractionDigits") != r->facet_end () || + r->facet_find ("totalDigits") != r->facet_end ()) && + ultimate_base (c).is_a<Decimal> ()) + facets = true; + } + } + else + base = any_type; + + os << "// " << name << endl + << "//" << endl + << endl; + + // + // + { + Member member (*this, name); + Traversal::Names names_member (member); + names (c, names_member); + } + + // facets + // + if (facets) + { + os << "static const ::xsd::cxx::tree::facet _xsd_" << name << + "_facet_table[] = " + << "{"; + + facet_array_.traverse (c); + + os << "{::xsd::cxx::tree::facet::none, 0UL}" + << "};"; + } + + // c-tors + // + bool generate_no_base_ctor (false); + { + GenerateWithoutBaseCtor t (generate_no_base_ctor); + t.traverse (c); + } + + bool has_complex_non_op_args (false); + bool has_poly_non_op_args (false); + bool complex_poly_args_clash (true); + { + HasComplexPolyNonOptArgs t (*this, true, + has_complex_non_op_args, + has_poly_non_op_args, + complex_poly_args_clash); + t.traverse (c); + } + + // default c-tor + // + if (options.generate_default_ctor ()) + { + bool generate (false); + { + GenerateDefaultCtor t (*this, generate, generate_no_base_ctor); + t.traverse (c); + } + + if (generate) + { + os << name << "::" << endl + << name << " ()" << endl + << ": " << base << " ()"; + + if (edom_document_member_p (c)) + { + os << "," << endl + << " " << edom_document_member (c) << " (" << + "::xsd::cxx::xml::dom::create_document< " << char_type << + " > ())"; + } + + if (mixed) + { + os << "," << endl + << " " << ctx.get<String> ("mixed-member") << " (this)"; + } + + names (c, default_ctor_init_names_); + + os << "{"; + if (facets) + os << "this->_facet_table (_xsd_" << name << "_facet_table);"; + os << "}"; + } + } + + // c-tor (base, all-non-optional-members) + // + if (options.generate_from_base_ctor ()) + { + bool generate (false); + { + GenerateFromBaseCtor t (*this, generate); + t.traverse (c); + } + + if (generate) + { + bool has_complex_non_op_args (false); + bool has_poly_non_op_args (false); + bool complex_poly_args_clash (true); + { + HasComplexPolyNonOptArgs t (*this, false, + has_complex_non_op_args, + has_poly_non_op_args, + complex_poly_args_clash); + t.traverse (c); + } + + String base_arg ( + L"_xsd_" + ename (c.inherits ().base ()) + L"_base"); + + os << name << "::" << endl + << name << " (const "; + inherits (c, inherits_member_); + os << "& " << base_arg; + { + FromBaseCtorArg args (*this, CtorArgType::type, true); + Traversal::Names args_names (args); + names (c, args_names); + } + os << ")" << endl + << ": " << base << " (" << base_arg << ")"; + + if (edom_document_member_p (c)) + { + os << "," << endl + << " " << edom_document_member (c) << " (" << + "::xsd::cxx::xml::dom::create_document< " << char_type << + " > ())"; + } + + if (mixed) + { + os << "," << endl + << " " << ctx.get<String> ("mixed-member") << " (this)"; + } + + names (c, ctor_names_); + + os << "{"; + if (facets) + os << "this->_facet_table (_xsd_" << name << "_facet_table);"; + os << "}"; + + // If we have any complex arguments in the previous c-tor + // then also generate the auto_ptr version. + // + if (has_complex_non_op_args) + { + CtorArgType const at (CtorArgType::complex_auto_ptr); + + os << name << "::" << endl + << name << " (const "; + inherits (c, inherits_member_); + os << "& " << base_arg; + { + FromBaseCtorArg args (*this, at, true); + Traversal::Names args_names (args); + names (c, args_names); + } + os << ")" << endl + << ": " << base << " (" << base_arg << ")"; + + if (edom_document_member_p (c)) + { + os << "," << endl + << " " << edom_document_member (c) << " (" << + "::xsd::cxx::xml::dom::create_document< " << char_type << + " > ())"; + } + + if (mixed) + { + os << "," << endl + << " " << ctx.get<String> ("mixed-member") << " (this)"; + } + + { + CtorMember t (*this, at); + Traversal::Names n (t); + + if (gen_wildcard) + n >> ctor_any_; + + names (c, n); + } + + os << "{"; + if (facets) + os << "this->_facet_table (_xsd_" << name << "_facet_table);"; + os << "}"; + } + + // If we are generating polymorphic code then we also need to + // provide auto_ptr version for every polymorphic type. + // + if (polymorphic && + has_poly_non_op_args && !complex_poly_args_clash) + { + CtorArgType const at (CtorArgType::poly_auto_ptr); + + os << name << "::" << endl + << name << " (const "; + inherits (c, inherits_member_); + os << "& " << base_arg; + { + FromBaseCtorArg args (*this, at, true); + Traversal::Names args_names (args); + names (c, args_names); + } + os << ")" << endl + << ": " << base << " (" << base_arg << ")"; + + if (edom_document_member_p (c)) + { + os << "," << endl + << " " << edom_document_member (c) << " (" << + "::xsd::cxx::xml::dom::create_document< " << char_type << + " > ())"; + } + + if (mixed) + { + os << "," << endl + << " " << ctx.get<String> ("mixed-member") << " (this)"; + } + + { + CtorMember t (*this, at); + Traversal::Names n (t); + + if (gen_wildcard) + n >> ctor_any_; + + names (c, n); + } + + os << "{"; + if (facets) + os << "this->_facet_table (_xsd_" << name << "_facet_table);"; + os << "}"; + } + } + } + + // c-tor (all-non-optional-members) + // + if (generate_no_base_ctor) + { + CtorArgType const at (CtorArgType::type); + + os << name << "::" << endl + << name << " ("; + { + CtorArgsWithoutBase ctor_args (*this, at, true, true); + ctor_args.dispatch (c); + } + os << ")" << endl + << ": " << base << " ("; + { + CtorBase base (*this, at, ""); + Traversal::Inherits inherits_base (base); + + inherits (c, inherits_base); + } + os << ")"; + + if (edom_document_member_p (c)) + { + os << "," << endl + << " " << edom_document_member (c) << " (" << + "::xsd::cxx::xml::dom::create_document< " << char_type << + " > ())"; + } + + if (mixed) + { + os << "," << endl + << " " << ctx.get<String> ("mixed-member") << " (this)"; + } + + names (c, ctor_names_); + + os << "{"; + if (facets) + os << "this->_facet_table (_xsd_" << name << "_facet_table);"; + os << "}"; + + // If we have any complex arguments in the previous c-tor + // then also generate the auto_ptr version. One case where + // this c-tor will be generated is restriction of anyType. + // + if (has_complex_non_op_args) + { + CtorArgType const at (CtorArgType::complex_auto_ptr); + + os << name << "::" << endl + << name << " ("; + { + CtorArgsWithoutBase ctor_args (*this, at, true, true); + ctor_args.dispatch (c); + } + os << ")" << endl + << ": " << base << " ("; + { + CtorBase base (*this, at, ""); + Traversal::Inherits inherits_base (base); + + inherits (c, inherits_base); + } + os << ")"; + + if (edom_document_member_p (c)) + { + os << "," << endl + << " " << edom_document_member (c) << " (" << + "::xsd::cxx::xml::dom::create_document< " << char_type << + " > ())"; + } + + if (mixed) + { + os << "," << endl + << " " << ctx.get<String> ("mixed-member") << " (this)"; + } + + { + CtorMember t (*this, at); + Traversal::Names n (t); + + if (gen_wildcard) + n >> ctor_any_; + + names (c, n); + } + + os << "{"; + if (facets) + os << "this->_facet_table (_xsd_" << name << "_facet_table);"; + os << "}"; + } + + // If we are generating polymorphic code then we also need to + // provide auto_ptr version for every polymorphic type. + // + if (polymorphic && + has_poly_non_op_args && !complex_poly_args_clash) + { + CtorArgType const at (CtorArgType::poly_auto_ptr); + + os << name << "::" << endl + << name << " ("; + { + CtorArgsWithoutBase ctor_args (*this, at, true, true); + ctor_args.dispatch (c); + } + os << ")" << endl + << ": " << base << " ("; + { + CtorBase base (*this, at, ""); + Traversal::Inherits inherits_base (base); + + inherits (c, inherits_base); + } + os << ")"; + + if (edom_document_member_p (c)) + { + os << "," << endl + << " " << edom_document_member (c) << " (" << + "::xsd::cxx::xml::dom::create_document< " << char_type << + " > ())"; + } + + if (mixed) + { + os << "," << endl + << " " << ctx.get<String> ("mixed-member") << " (this)"; + } + + { + CtorMember t (*this, at); + Traversal::Names n (t); + + if (gen_wildcard) + n >> ctor_any_; + + names (c, n); + } + + os << "{"; + if (facets) + os << "this->_facet_table (_xsd_" << name << "_facet_table);"; + os << "}"; + } + } + + if (string_based) + { + // We might not have the value type if this enum is customized. + // + if (enum_base != 0 && enum_base->context ().count ("value")) + { + // c-tor (enum-value, all-non-optional-members) + // + CtorArgType const at (CtorArgType::type); + String base_arg (L"_xsd_" + ename (*enum_base) + L"_base"); + + os << name << "::" << endl + << name << " (" << fq_name (*enum_base) << "::" << + evalue (*enum_base) << " " << base_arg; + + { + CtorArgsWithoutBase ctor_args (*this, at, true, false); + ctor_args.dispatch (c); + } + + os << ")" << endl + << ": " << base << " ("; + + { + CtorBase base (*this, at, base_arg); + Traversal::Inherits inherits_base (base); + + inherits (c, inherits_base); + } + + os << ")"; + + if (edom_document_member_p (c)) + { + os << "," << endl + << " " << edom_document_member (c) << " (" << + "::xsd::cxx::xml::dom::create_document< " << char_type << + " > ())"; + } + + // Cannot be mixed. + + names (c, ctor_names_); + + os << "{"; + if (facets) + os << "this->_facet_table (_xsd_" << name << "_facet_table);"; + os << "}"; + } + + CtorArgType const at (CtorArgType::type); + String base_arg (L"_xsd_" + ename (ultimate_base (c)) + L"_base"); + + // c-tor (const char*, all-non-optional-members) + // + os << name << "::" << endl + << name << " (const " << char_type << "* " << base_arg; + + { + CtorArgsWithoutBase ctor_args (*this, at, true, false); + ctor_args.dispatch (c); + } + + os << ")" << endl + << ": " << base << " ("; + + { + CtorBase base (*this, at, base_arg); + Traversal::Inherits inherits_base (base); + + inherits (c, inherits_base); + } + + os << ")"; + + if (edom_document_member_p (c)) + { + os << "," << endl + << " " << edom_document_member (c) << " (" << + "::xsd::cxx::xml::dom::create_document< " << char_type << + " > ())"; + } + + // Cannot be mixed. + + names (c, ctor_names_); + + os << "{"; + if (facets) + os << "this->_facet_table (_xsd_" << name << "_facet_table);"; + os << "}"; + + + // c-tor (const std::string&, all-non-optional-members) + // + os << name << "::" << endl + << name << " (const " << string_type << "& " << base_arg; + + { + CtorArgsWithoutBase ctor_args (*this, at, true, false); + ctor_args.dispatch (c); + } + + os << ")" << endl + << ": " << base << " ("; + + { + CtorBase base (*this, at, base_arg); + Traversal::Inherits inherits_base (base); + + inherits (c, inherits_base); + } + + os << ")"; + + if (edom_document_member_p (c)) + { + os << "," << endl + << " " << edom_document_member (c) << " (" << + "::xsd::cxx::xml::dom::create_document< " << char_type << + " > ())"; + } + + // Cannot be mixed. + + names (c, ctor_names_); + + os << "{"; + if (facets) + os << "this->_facet_table (_xsd_" << name << "_facet_table);"; + os << "}"; + } + + // c-tor (ultimate-base, all-non-optional-members) + // + { + CtorArgType const at (CtorArgType::type); + + os << name << "::" << endl + << name << " ("; + + String base_arg; + + { + CtorArgs ctor_args (*this, at, base_arg); + ctor_args.dispatch (c); + } + + os << ")" << endl + << ": " << base << " ("; + + { + CtorBase base (*this, at, base_arg); + Traversal::Inherits inherits_base (base); + + inherits (c, inherits_base); + } + + os << ")"; + + if (edom_document_member_p (c)) + { + os << "," << endl + << " " << edom_document_member (c) << " (" << + "::xsd::cxx::xml::dom::create_document< " << char_type << + " > ())"; + } + + if (mixed) + { + os << "," << endl + << " " << ctx.get<String> ("mixed-member") << " (this)"; + } + + names (c, ctor_names_); + + os << "{"; + if (facets) + os << "this->_facet_table (_xsd_" << name << "_facet_table);"; + os << "}"; + } + + // If we have any complex arguments in the previous c-tor + // then also generate the auto_ptr version. + // + if (has_complex_non_op_args) + { + CtorArgType const at (CtorArgType::complex_auto_ptr); + String base_arg; + + os << name << "::" << endl + << name << " ("; + + { + CtorArgs ctor_args (*this, at, base_arg); + ctor_args.dispatch (c); + } + + os << ")" << endl + << ": " << base << " ("; + + { + CtorBase base (*this, at, base_arg); + Traversal::Inherits inherits_base (base); + + inherits (c, inherits_base); + } + + os << ")"; + + if (edom_document_member_p (c)) + { + os << "," << endl + << " " << edom_document_member (c) << " (" << + "::xsd::cxx::xml::dom::create_document< " << char_type << + " > ())"; + } + + if (mixed) + { + os << "," << endl + << " " << ctx.get<String> ("mixed-member") << " (this)"; + } + + { + CtorMember t (*this, at); + Traversal::Names n (t); + + if (gen_wildcard) + n >> ctor_any_; + + names (c, n); + } + + os << "{"; + if (facets) + os << "this->_facet_table (_xsd_" << name << "_facet_table);"; + os << "}"; + } + + // If we are generating polymorphic code then we also need to + // provide auto_ptr version for every polymorphic type. + // + if (polymorphic && + has_poly_non_op_args && !complex_poly_args_clash) + { + CtorArgType const at (CtorArgType::poly_auto_ptr); + String base_arg; + + os << name << "::" << endl + << name << " ("; + + { + CtorArgs ctor_args (*this, at, base_arg); + ctor_args.dispatch (c); + } + + os << ")" << endl + << ": " << base << " ("; + + { + CtorBase base (*this, at, base_arg); + Traversal::Inherits inherits_base (base); + + inherits (c, inherits_base); + } + + os << ")"; + + if (edom_document_member_p (c)) + { + os << "," << endl + << " " << edom_document_member (c) << " (" << + "::xsd::cxx::xml::dom::create_document< " << char_type << + " > ())"; + } + + if (mixed) + { + os << "," << endl + << " " << ctx.get<String> ("mixed-member") << " (this)"; + } + + { + CtorMember t (*this, at); + Traversal::Names n (t); + + if (gen_wildcard) + n >> ctor_any_; + + names (c, n); + } + + os << "{"; + if (facets) + os << "this->_facet_table (_xsd_" << name << "_facet_table);"; + os << "}"; + } + + + // copy c-tor + // + + os << name << "::" << endl + << name << " (const " << name << "& x," << endl + << flags_type << " f," << endl + << container << "* c)" << endl + << ": " << base << " (x, f, c)"; + + if (edom_document_member_p (c)) + { + os << "," << endl + << " " << edom_document_member (c) << " (" << + "::xsd::cxx::xml::dom::create_document< " << char_type << + " > ())"; + } + + if (mixed) + { + String const& m (ctx.get<String> ("mixed-member")); + os << "," << endl + << " " << m << " (x." << m << ", f, this)"; + } + + if (ordered) + { + String const& m (ctx.get<String> ("order-member")); + os << "," << endl + << " " << m << " (x." << m << ")"; + } + + { + CopyAny copy_any (*this, "x"); + CopyMember copy_member (*this, "x"); + Traversal::Names names; + + names >> copy_member; + + if (gen_wildcard) + names >> copy_any; + + Complex::names (c, names); + } + + os << "{"; + if (facets) + os << "this->_facet_table (_xsd_" << name << "_facet_table);"; + os << "}"; + + // + // + bool he (has<Traversal::Element> (c)); + bool hae (has<Traversal::Any> (c)); + + bool ha (has<Traversal::Attribute> (c)); + bool haa (has<Traversal::AnyAttribute> (c)); + + // + // + if (!options.suppress_parsing ()) + { + // c-tor (xercesc::DOMElement) + // + os << name << "::" << endl + << name << " (const " << xerces_ns << "::DOMElement& e," << endl + << flags_type << " f," << endl + << container << "* c)" << endl + << ": " << base << " (e, f"; + + if (he || ha || hae || (haa && gen_wildcard) || mixed) + os << " | " << flags_type << "::base"; + + os << ", c)"; + + if (edom_document_member_p (c)) + { + os << "," << endl + << " " << edom_document_member (c) << " (" << + "::xsd::cxx::xml::dom::create_document< " << char_type << + " > ())"; + } + + if (mixed) + { + os << "," << endl + << " " << ctx.get<String> ("mixed-member") << " (this)"; + } + + names (c, element_ctor_names_); + + os << "{"; + + if (facets) + os << "this->_facet_table (_xsd_" << name << "_facet_table);" + << endl; + + bool base_has_el (false), base_has_at (false); + + // We are only interested in this information if we are + // generating our own parse(). + // + if (he || ha || hae || (haa && gen_wildcard) || mixed) + { + if (c.inherits_p ()) + { + HasParseFunction test (*this, base_has_el, base_has_at); + test.dispatch (c.inherits ().base ()); + } + } + + //@@ Throw if p is not exhausted at the end. + // + if (he || ha || hae || (haa && gen_wildcard) || mixed) + os << "if ((f & " << flags_type << "::base) == 0)" + << "{" + << parser_type << " p (e, " << + (he || hae || base_has_el || mixed_p (c) ? "true, " : "false, ") << + (mixed_p (c) ? "true, " : "false, ") << + (ha || (haa && gen_wildcard) || base_has_at ? "true" : "false") + << ");" + << "this->" << unclash (name, "parse") << " (p, f);" + << "}"; + + os << "}"; + + bool simple (true); + { + IsSimpleType t (simple); + t.dispatch (c); + } + + if (simple) + { + // c-tor (xercesc::DOMAttr) + // + os << name << "::" << endl + << name << " (const " << xerces_ns << "::DOMAttr& a," << endl + << flags_type << " f," << endl + << container << "* c)" << endl + << ": " << base << " (a, f, c)" + << "{"; + + if (facets) + os << "this->_facet_table (_xsd_" << name << "_facet_table);"; + + os << "}"; + + // c-tor (string const&, xercesc::DOMElement) + // + os << name << "::" << endl + << name << " (const " << string_type << "& s," << endl + << "const " << xerces_ns << "::DOMElement* e," << endl + << flags_type << " f," << endl + << container << "* c)" << endl + << ": " << base << " (s, e, f, c)" + << "{"; + + if (facets) + os << "this->_facet_table (_xsd_" << name << "_facet_table);"; + + os << "}"; + } + + if (he || ha || hae || (haa && gen_wildcard) || mixed) + { + os << "void " << name << "::" << endl + << unclash (name, "parse") << " (" << + parser_type << "& p," << endl + << flags_type << + (he || ha || base_has_el || base_has_at ? " f" : "") << ")" + << "{"; + + // Allow the base to parse its part. + // + if (base_has_el || base_has_at) + os << "this->" << base << "::parse (p, f);" + << endl; + + if (he || hae || mixed_p (c)) + { + bool m (mixed_p (c)); + + os << "for (; p.more_content (); p.next_content (" << + (m ? "true" : "false") << "))" + << "{"; + + if (m) + { + String const& ma (ctx.get<String> ("mixed-aname")); + String const& mi (ctx.get<String> ("mixed-ordered-id-name")); + String const& oa (ctx.get<String> ("order-aname")); + String const& ot (ctx.get<String> ("order-type")); + + os << "if (p.cur_is_text ())" + << "{" + << "const " << xerces_ns << "::DOMText& t (" << + "p.cur_text ());" + << "this->" << ma << " ().push_back (" << endl + << "::xsd::cxx::xml::transcode< " << char_type << " > (" << + "t.getData (), t.getLength ()));" + << "this->" << oa << " ().push_back (" << endl + << ot << " (" << mi << "," << endl + << "this->" << ma << " ().size () - 1));" + << "continue;" + << "}"; + } + + if (he || hae) + { + os << "const " << xerces_ns << "::DOMElement& i (" << + "p.cur_element ());" + << "const " << qname_type << " n (" << endl + << "::xsd::cxx::xml::dom::name< " << char_type << " > (i));" + << endl; + + names (c, names_element_); + } + + os << "break;" + << "}"; + + // Make sure all non-optional elements are set. + // + names (c, names_element_test_); + } + + if (ha || (haa && gen_wildcard)) + { + if (base_has_at) + os << "p.reset_attributes ();" + << endl; + + os << "while (p.more_attributes ())" + << "{" + << "const " << xerces_ns << "::DOMAttr& i (" << + "p.next_attribute ());" + << "const " << qname_type << " n (" << endl + << "::xsd::cxx::xml::dom::name< " << char_type << " > (i));" + << endl; + + names (c, names_attribute_); + + // Generate anyAttribute code after all the attributes. + // + if (gen_wildcard) + names (c, names_any_attribute_); + + + // os << "{" // else block + // @@ + // This doesn't play well with inheritance because we + // don't expect base's attributes. Also there are other + // "special" attributes such as xmlns, etc. + // + // << "throw ::xsd::cxx::tree::unexpected_attribute ... " + // << "}"; + + os << "}"; // while loop + + // Make sure all non-optional attributes are set. + // + names (c, names_attribute_test_); + } + + os << "}"; + } + } + + // _clone + // + if (!(c.abstract_p () || + (renamed && polymorphic && polymorphic_p (c)))) + os << name << "* " << name << "::" << endl + << "_clone (" << flags_type << " f," << endl + << container << "* c) const" + << "{" + << "return new class " << name << " (*this, f, c);" + << "}"; + + // operator= + // + if (!options.suppress_assignment () && + (he || ha || (gen_wildcard && (hae || haa)))) + { + os << name << "& " << name << "::" << endl + << "operator= (const " << name << "& x)" + << "{" + << "if (this != &x)" + << "{" + << "static_cast< " << base << "& > (*this) = x;"; + + // Note that here we don't assign the DOMDocument that is + // used to hold wildcard fragments. Each document has its + // own copy. + + // Mixed text content. + // + if (mixed) + { + String const& m (ctx.get<String> ("mixed-member")); + os << "this->" << m << " = x." << m << ";"; + } + + // Order container. + // + if (ordered) + { + String const& m (ctx.get<String> ("order-member")); + os << "this->" << m << " = x." << m << ";"; + } + + names (c, assign_names_); + + os << "}" + << "return *this;" + << "}"; + } + + // d-tor + // + os << name << "::" << endl + << "~" << name << " ()" + << "{" + << "}"; + + // Register with type factory map. + // + if (polymorphic && polymorphic_p (c) && !c.abstract_p ()) + { + // Note that we are using the original type name. + // + String const& name (ename (c)); + + // If this type is anonymous but substitutes, then it will + // be registered as part of the substitution registration. + // + if (!anonymous_p (c) && !options.suppress_parsing ()) + { + os << "static" << endl + << "const ::xsd::cxx::tree::type_factory_initializer< " << + poly_plate << ", " << char_type << ", " << name << " >" << endl + << "_xsd_" << name << "_type_factory_init (" << endl + << strlit (c.name ()) << "," << endl + << strlit (xml_ns_name (c)) << ");" + << endl; + } + + if ((!anonymous_p (c) || anonymous_substitutes_p (c)) && + options.generate_comparison ()) + { + os << "static" << endl + << "const ::xsd::cxx::tree::comparison_initializer< " << + poly_plate << ", " << char_type << ", " << name << " >" << endl + << "_xsd_" << name << "_comparison_init;" + << endl; + } + } + + // Comparison operators. + // + if (options.generate_comparison () && + (he || ha || mixed || ordered || !c.inherits_p () || + ((hae || haa) && gen_wildcard))) + { + bool base_comp (false); + + if (c.inherits_p ()) + { + HasComparisonOperator test (*this, base_comp); + test.dispatch (c.inherits ().base ()); + } + + bool has_body (he || ha || ordered || mixed || base_comp || + ((hae || haa) && gen_wildcard)); + + os << "bool" << endl + << "operator== (const " << name << "&" << + (has_body ? " x" : "") << ", " << + "const " << name << "&" << (has_body ? " y" : "") << ")" + << "{"; + + if (base_comp) + os << "if (!(static_cast< const " << base << "& > (x) ==" << endl + << "static_cast< const " << base << "& > (y)))" << endl + << "return false;" + << endl; + + { + Complex::names (c, comparison_names_); + } + + if (mixed) + { + String const& an (ctx.get<String> ("mixed-aname")); + os << "if (!(x." << an << " () == y." << an << " ()))" << endl + << "return false;" + << endl; + } + + if (ordered) + { + String const& an (ctx.get<String> ("order-aname")); + os << "if (!(x." << an << " () == y." << an << " ()))" << endl + << "return false;" + << endl; + } + + os << "return true;" + << "}"; + + os << "bool" << endl + << "operator!= (const " << name << "& x, " << + "const " << name << "& y)" + << "{" + << "return !(x == y);" + << "}"; + } + } + + private: + Traversal::Inherits inherits_member_; + MemberTypeName member_name_; + + Traversal::Names names_element_; + Traversal::Names names_element_test_; + + Traversal::Names names_attribute_; + Traversal::Names names_any_attribute_; + Traversal::Names names_attribute_test_; + + Any any_; + Element element_; + + AnyTest any_test_; + ElementTest element_test_; + + Attribute attribute_; + AttributeTest attribute_test_; + + AnyAttribute any_attribute_; + + DefaultCtorAnyInit default_ctor_any_init_; + DefaultCtorMemberInit default_ctor_member_init_; + Traversal::Names default_ctor_init_names_; + + CtorAny ctor_any_; + CtorMember ctor_member_; + Traversal::Names ctor_names_; + + ElementCtorAny element_ctor_any_; + ElementCtorMember element_ctor_member_; + Traversal::Names element_ctor_names_; + + AssignAny assign_any_; + AssignMember assign_member_; + Traversal::Names assign_names_; + + AnyComparison comparison_any_; + MemberComparison comparison_member_; + Traversal::Names comparison_names_; + + FacetArray facet_array_; + }; + + + // Generate element types and substitution group map entries. + // + struct GlobalElement: Traversal::Element, + GlobalElementBase, + Context + { + GlobalElement (Context& c) + : GlobalElementBase (c), + Context (c), + element_type_ (c.options.generate_element_type ()), + element_map_ (c.options.generate_element_map ()), + type_name_ (c) + { + belongs_ >> type_name_; + } + + virtual void + traverse (Type& e) + { + SemanticGraph::Type& t (e.type ()); + + // Check if this element is abstract. + // + bool abst; + { + SemanticGraph::Complex* tc; + abst = (tc = dynamic_cast<SemanticGraph::Complex*> (&t)) != 0 && + tc->abstract_p (); + } + + if (!abst && element_type_ && doc_root_p (e)) + { + bool fund (false); + { + IsFundamentalType test (fund); + test.dispatch (t); + } + + bool simple (true); + if (!fund) + { + IsSimpleType test (simple); + test.dispatch (t); + } + + String const& name (ename (e)); + String const& type (etype (e)); + String const& member (emember (e)); + + os << "// " << name << endl + << "//" << endl + << endl; + + // Virtual accessors. + // + os << "const " << any_type << "* " << name << "::" << endl + << "_value () const" + << "{"; + + if (fund) + os << "return 0;"; + else + os << "return &this->" << member << ".get ();"; + + os << "}"; + + os << any_type << "* " << name << "::" << endl + << "_value ()" + << "{"; + + if (fund) + os << "return 0;"; + else + os << "return &this->" << member << ".get ();"; + + os << "}"; + + // default c-tor + // + if (options.generate_default_ctor ()) + { + os << name << "::" << endl + << name << " ()" << endl + << ": " << member << " (0)" + << "{" + << "}"; + } + + // c-tor (value) + // + os << name << "::" << endl + << name << " (const " << type << "& x)" << endl + << ": " << member << " (x, 0)" + << "{" + << "}"; + + + // c-tor (auto_ptr<value>) + // + if (!simple || (polymorphic && polymorphic_p (t))) + { + os << name << "::" << endl + << name << " (" << auto_ptr << "< " << type << " > p)" << endl + << ": " << member << " (" << + (std >= cxx_version::cxx11 ? "::std::move (p)" : "p") << ", 0)" + << "{" + << "}"; + } + + // c-tor (xercesc::DOMElement) + // + SemanticGraph::Context& ec (e.context ()); + String const& name_member (ec.get<String> ("element-name-member")); + String const& ns_member (ec.get<String> ("element-ns-member")); + + bool parsing (!options.suppress_parsing ()); + if (parsing) + { + String const& tr (etraits (e)); + + os << name << "::" << endl + << name << " (const " << xerces_ns << "::DOMElement& e, " << + flags_type << " f)" << endl + << ": " << member << " (0)" + << "{" + << "const " << qname_type << " n (" << endl + << "::xsd::cxx::xml::dom::name< " << char_type << " > (e));" + << endl + << "if (n.name () == " << name_member << " && " << + "n.namespace_ () == " << ns_member << ")" << endl + << "this->" << member << ".set (" << tr << + "::create (e, f, 0));" + << "else" << endl + << "throw ::xsd::cxx::tree::unexpected_element < " << + char_type << " > (" << endl + << "n.name (), n.namespace_ ()," << endl + << name_member << ", " << ns_member << ");" + << "}"; + } + + // copy c-tor + // + os << name << "::" << endl + << name << " (const " << name << "& x, " << + flags_type << " f)" << endl + << ": " << element_type << " ()," << endl + << " " << member << " (x." << member << ", f, 0)" + << "{" + << "}"; + + // _clone + // + os << name << "* " << name << "::" << endl + << "_clone (" << flags_type << " f) const" + << "{" + << "return new class " << name << " (*this, f);" + << "}"; + + // Element name and namespace accessors. + // + String const& aname (ec.get<String> ("element-name")); + String const& ans (ec.get<String> ("element-ns")); + + os << "const " << string_type << "& " << name << "::" << endl + << aname << " ()" + << "{" + << "return " << name_member << ";" + << "}"; + + os << "const " << string_type << "& " << name << "::" << endl + << ans << " ()" + << "{" + << "return " << ns_member << ";" + << "}"; + + os << "const " << string_type << "& " << name << "::" << endl + << "_name () const" + << "{" + << "return " << name_member << ";" + << "}"; + + os << "const " << string_type << "& " << name << "::" << endl + << "_namespace () const" + << "{" + << "return " << ns_member << ";" + << "}"; + + os << "const " << string_type << " " << name << "::" << endl + << name_member << " (" << strlit (e.name ()) << ");" + << endl + << "const " << string_type << " " << name << "::" << endl + << ns_member << " (" << strlit (e.namespace_ ().name ()) << ");" + << endl; + + // d-tor + // + os << name << "::" << endl + << "~" << name << " ()" + << "{" + << "}"; + + // Element map registration. + // + if (element_map_ && parsing) + { + os << "static " << endl + << "const ::xsd::cxx::tree::parser_init< " << name << ", " << + char_type << ", " << any_type << " >" << endl + << "_xsd_" << name << "_parser_init (" << + name << "::" << aname << " (), " << + name << "::" << ans << " ());" + << endl; + } + } + + // Note that we cannot just omit this element if it's abstract + // because it may serve as a "link" between the root of the + // substitution group and a non-abstract element that uses this + // element as its root (see element_factory_map::find_substitution() + // for details). + // + if (polymorphic && e.substitutes_p () && !options.suppress_parsing ()) + { + String const& name (ename (e)); + Type& r (e.substitutes ().root ()); + + os << "static" << endl + << "const ::xsd::cxx::tree::element_factory_initializer< " << + poly_plate << ", " << char_type << " >" << endl + << "_xsd_" << name << "_element_factory_init (" << endl + << strlit (r.name ()) << "," << endl + << strlit (r.namespace_ ().name ()) << "," << endl + << strlit (e.name ()) << "," << endl + << strlit (e.namespace_ ().name ()) << "," << endl; + + if (abst) + os << "0"; + else + { + os << "&::xsd::cxx::tree::factory_impl< "; + belongs (e, belongs_); + os << " >"; + } + + os << ");" + << endl + << endl; + } + } + + private: + bool element_type_; + bool element_map_; + Traversal::Belongs belongs_; + MemberTypeName type_name_; + }; + } + + void + generate_tree_source (Context& ctx, size_t first, size_t last) + { + if (ctx.options.generate_wildcard ()) + { + ctx.os << "#include <xsd/cxx/xml/dom/wildcard-source.hxx>" << endl + << endl; + } + + if (!ctx.options.suppress_parsing ()) + ctx.os << "#include <xsd/cxx/xml/dom/parsing-source.hxx>" << endl + << endl; + + if (ctx.polymorphic) + { + bool parsing (!ctx.options.suppress_parsing ()); + bool comparison (ctx.options.generate_comparison ()); + + if (parsing) + ctx.os << "#include <xsd/cxx/tree/type-factory-map.hxx>" << endl + << endl; + + if (comparison) + ctx.os << "#include <xsd/cxx/tree/comparison-map.hxx>" << endl + << endl; + + if (parsing || comparison) + { + bool import_maps (ctx.options.import_maps ()); + bool export_maps (ctx.options.export_maps ()); + + if (import_maps || export_maps) + { + ctx.os << "#ifndef XSD_NO_EXPORT" << endl + << endl + << "namespace xsd" + << "{" + << "namespace cxx" + << "{" + << "namespace tree" + << "{" + << "#ifdef _MSC_VER" << endl; + + if (parsing && export_maps) + ctx.os << "template struct __declspec (dllexport) " << + "type_factory_plate< " << ctx.poly_plate << ", " << + ctx.char_type << " >;"; + + if (parsing && import_maps) + ctx.os << "template struct __declspec (dllimport) " << + "type_factory_plate< " << ctx.poly_plate << ", " << + ctx.char_type << " >;"; + + if (comparison && export_maps) + ctx.os << "template struct __declspec (dllexport) " << + "comparison_plate< " << ctx.poly_plate << ", " << + ctx.char_type << " >;"; + + if (comparison && import_maps) + ctx.os << "template struct __declspec (dllimport) " << + "comparison_plate< " << ctx.poly_plate << ", " << + ctx.char_type << " >;"; + + ctx.os << "#elif defined(__GNUC__) && __GNUC__ >= 4" << endl; + + if (parsing) + ctx.os << "template struct __attribute__ ((visibility(\"default\"))) " << + "type_factory_plate< " << ctx.poly_plate << ", " << + ctx.char_type << " >;"; + + if (comparison) + ctx.os << "template struct __attribute__ ((visibility(\"default\"))) " << + "comparison_plate< " << ctx.poly_plate << ", " << + ctx.char_type << " >;"; + + ctx.os << "#elif defined(XSD_MAP_VISIBILITY)" << endl; + + if (parsing) + ctx.os << "template struct XSD_MAP_VISIBILITY " << + "type_factory_plate< " << ctx.poly_plate << ", " << + ctx.char_type << " >;"; + + if (comparison) + ctx.os << "template struct XSD_MAP_VISIBILITY " << + "comparison_plate< " << ctx.poly_plate << ", " << + ctx.char_type << " >;"; + + ctx.os << "#endif" << endl + << "}" // tree + << "}" // cxx + << "}" // xsd + << "#endif // XSD_NO_EXPORT" << endl + << endl; + } + + ctx.os << "namespace _xsd" + << "{"; + + if (parsing) + ctx.os << "static" << endl + << "const ::xsd::cxx::tree::type_factory_plate< " << + ctx.poly_plate << ", " << ctx.char_type << " >" << endl + << "type_factory_plate_init;" + << endl; + + if (comparison) + ctx.os << "static" << endl + << "const ::xsd::cxx::tree::comparison_plate< " << + ctx.poly_plate << ", " << ctx.char_type << " >" << endl + << "comparison_plate_init;" + << endl; + + ctx.os << "}"; + } + } + + Traversal::Schema schema; + Sources sources; + Traversal::Names names_ns, names; + Namespace ns (ctx, first, last); + + List list (ctx); + Union union_ (ctx); + Complex complex (ctx); + Enumeration enumeration (ctx); + GlobalElement element (ctx); + + schema >> sources >> schema; + schema >> names_ns >> ns >> names; + + names >> list; + names >> union_; + names >> complex; + names >> enumeration; + names >> element; + + schema.dispatch (ctx.schema_root); + } + } +} |