aboutsummaryrefslogtreecommitdiff
path: root/examples/cxx/serializer/polyroot
diff options
context:
space:
mode:
Diffstat (limited to 'examples/cxx/serializer/polyroot')
-rw-r--r--examples/cxx/serializer/polyroot/README46
-rw-r--r--examples/cxx/serializer/polyroot/driver.cxx142
-rw-r--r--examples/cxx/serializer/polyroot/makefile73
-rw-r--r--examples/cxx/serializer/polyroot/supermen-simpl-mixin.cxx35
-rw-r--r--examples/cxx/serializer/polyroot/supermen-simpl-mixin.hxx35
-rw-r--r--examples/cxx/serializer/polyroot/supermen-simpl-tiein.cxx59
-rw-r--r--examples/cxx/serializer/polyroot/supermen-simpl-tiein.hxx53
-rw-r--r--examples/cxx/serializer/polyroot/supermen.hxx129
-rw-r--r--examples/cxx/serializer/polyroot/supermen.map9
-rw-r--r--examples/cxx/serializer/polyroot/supermen.xsd41
10 files changed, 622 insertions, 0 deletions
diff --git a/examples/cxx/serializer/polyroot/README b/examples/cxx/serializer/polyroot/README
new file mode 100644
index 0000000..bd86188
--- /dev/null
+++ b/examples/cxx/serializer/polyroot/README
@@ -0,0 +1,46 @@
+This example shows how to handle the xsi:type attributes and substitution
+groups when they are used on root elements. For general coverage of XML
+Schema polymorphism handling in the Embedded C++/Serializer mapping see
+the polymorphism example.
+
+The example consists of the following files:
+
+supermen.xsd
+ XML Schema which describes supermen instance documents.
+
+supermen.hxx
+ Types that describe the supermen object model in C++. These
+ are hand-written.
+
+supermen.map
+ Type map. It maps XML Schema types defined in supermen.xsd to
+ C++ types defined in supermen.hxx.
+
+supermen-sskel.hxx
+supermen-sskel.cxx
+ Serializer skeletons generated by XSD/e from supermen.xsd and
+ supermen.map.
+
+supermen-simpl-mixin.hxx
+supermen-simpl-mixin.cxx
+
+supermen-simpl-tiein.hxx
+supermen-simpl-tiein.cxx
+ Serializer implementations (using either mixin or tiein parser
+ reuse style) that serialize the custom in-memory object model to
+ XML. These are hand-written implementations of the serializer
+ skeletons defined in supermen-sskel.hxx.
+
+driver.cxx
+ Driver for the example. It first constructs a sample object model
+ using the types from supermen.hxx. It then creates a serializer
+ instance using all the individual serializers found in one of
+ supermen-simpl-*.hxx. Finally, it iterates over the object model
+ and based on the type of the item being serialized, it creates
+ the corresponding document serializer that is then invoked to
+ serialize the object model item to an XML document which is
+ printed to STDOUT.
+
+To run the example simply execute:
+
+$ ./driver
diff --git a/examples/cxx/serializer/polyroot/driver.cxx b/examples/cxx/serializer/polyroot/driver.cxx
new file mode 100644
index 0000000..d404d15
--- /dev/null
+++ b/examples/cxx/serializer/polyroot/driver.cxx
@@ -0,0 +1,142 @@
+// file : examples/cxx/serializer/polyroot/driver.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#include <iostream>
+
+#include "supermen.hxx"
+
+#include "supermen-sskel.hxx" // Get the configuration macros (XSDE_*).
+
+#if defined(XSDE_REUSE_STYLE_MIXIN)
+# include "supermen-simpl-mixin.hxx"
+#elif defined(XSDE_REUSE_STYLE_TIEIN)
+# include "supermen-simpl-tiein.hxx"
+#else
+# error this example requires mixin or tiein serializer reuse support
+#endif
+
+using std::cerr;
+using std::endl;
+
+int
+main ()
+{
+ // Check that the load in substitution and inheritance hashmaps
+ // is not too high.
+ //
+#ifndef NDEBUG
+ float load = (float) xml_schema::serializer_smap_elements ();
+ load /= xml_schema::serializer_smap_buckets ();
+
+ if (load > 0.8)
+ {
+ cerr << "substitution hashmap load is " << load << endl;
+ cerr << "time to increase XSDE_SERIALIZER_SMAP_BUCKETS" << endl;
+ }
+
+ load = (float) xml_schema::serializer_smap_bucket_elements ();
+ load /= xml_schema::serializer_smap_bucket_buckets ();
+
+ if (load > 0.8)
+ {
+ cerr << "substitution inner hashmap load is " << load << endl;
+ cerr << "time to increase XSDE_SERIALIZER_SMAP_BUCKET_BUCKETS" << endl;
+ }
+
+#ifdef XSDE_SERIALIZER_VALIDATION
+ load = (float) xml_schema::serializer_imap_elements ();
+ load /= xml_schema::serializer_imap_buckets ();
+
+ if (load > 0.8)
+ {
+ cerr << "inheritance hashmap load is " << load << endl;
+ cerr << "time to increase XSDE_SERIALIZER_IMAP_BUCKETS" << endl;
+ }
+#endif
+#endif
+
+ try
+ {
+ // Create a sample supermen catalog. To keep things simple the
+ // following code is not exception-safe.
+ //
+ supermen sm;
+
+ sm.push_back (new person ("John Doe"));
+ sm.push_back (new superman ("James 007 Bond", false));
+ sm.push_back (new batman ("Bruce Wayne", 10));
+
+ // Construct the serializer.
+ //
+ xml_schema::string_simpl string_s;
+ xml_schema::boolean_simpl boolean_s;
+ xml_schema::unsigned_int_simpl unsigned_int_s;
+
+ person_simpl person_s;
+ superman_simpl superman_s;
+ batman_simpl batman_s;
+
+ person_s.serializers (string_s);
+ superman_s.serializers (string_s, boolean_s);
+ batman_s.serializers (string_s, boolean_s, unsigned_int_s);
+
+ // Serialize each item in the supermen catalog as a separate XML
+ // document.
+ //
+ for (supermen::const_iterator i = sm.begin (); i != sm.end (); ++i)
+ {
+ person& p = **i;
+ person_sskel* ps = 0;
+
+ switch (p.type ())
+ {
+ case person_type:
+ {
+ ps = &person_s;
+ break;
+ }
+ case superman_type:
+ {
+ ps = &superman_s;
+ break;
+ }
+ case batman_type:
+ {
+ ps = &batman_s;
+ break;
+ }
+ }
+
+ // Create a document serializer for this type. Note that we pass
+ // true as the third argument to indicate polymorphic serialization
+ // as well as the root element's static type as the last argument
+ // which is necessary if the actual root type can differ from its
+ // static type.
+ //
+ xml_schema::document_simpl doc_s (
+ *ps, "person", true, person_sskel::_static_type ());
+
+ doc_s.add_no_namespace_schema ("supermen.xsd");
+
+ ps->pre (p);
+ doc_s.serialize (std::cout);
+ ps->post ();
+
+ std::cout << endl
+ << endl;
+ }
+ }
+ catch (const xml_schema::serializer_exception& e)
+ {
+ cerr << "error: " << e.text () << endl;
+ return 1;
+ }
+ catch (const std::ios_base::failure&)
+ {
+ cerr << "error: write failure" << endl;
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/examples/cxx/serializer/polyroot/makefile b/examples/cxx/serializer/polyroot/makefile
new file mode 100644
index 0000000..9427b4a
--- /dev/null
+++ b/examples/cxx/serializer/polyroot/makefile
@@ -0,0 +1,73 @@
+# file : examples/cxx/serializer/polyroot/makefile
+# author : Boris Kolpackov <boris@codesynthesis.com>
+# copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+# license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../../../../build/bootstrap.make
+
+xsd := supermen.xsd
+cxx := driver.cxx
+
+ifeq ($(xsde_reuse_style),mixin)
+cxx += supermen-simpl-mixin.cxx
+else
+cxx += supermen-simpl-tiein.cxx
+endif
+
+obj := $(addprefix $(out_base)/,$(cxx:.cxx=.o) $(xsd:.xsd=-sskel.o))
+dep := $(obj:.o=.o.d)
+
+xsde.l := $(out_root)/libxsde/xsde/xsde.l
+xsde.l.cpp-options := $(out_root)/libxsde/xsde/xsde.l.cpp-options
+
+driver := $(out_base)/driver
+clean := $(out_base)/.clean
+
+
+# Build.
+#
+$(driver): $(obj) $(xsde.l)
+
+$(obj) $(dep): cpp_options := -I$(out_base) -I$(src_base)
+$(obj) $(dep): $(xsde.l.cpp-options)
+
+skel := $(out_base)/$(xsd:.xsd=-sskel.hxx) \
+ $(out_base)/$(xsd:.xsd=-sskel.ixx) \
+ $(out_base)/$(xsd:.xsd=-sskel.cxx)
+
+$(skel): xsde := $(out_root)/xsde/xsde
+$(skel): xsde_options += --generate-polymorphic \
+--type-map $(src_base)/supermen.map
+
+$(skel): $(out_root)/xsde/xsde $(src_base)/supermen.map
+
+$(call include-dep,$(dep))
+
+# Convenience alias for default target.
+#
+.PHONY: $(out_base)/
+$(out_base)/: $(driver)
+
+
+# Clean.
+#
+.PHONY: $(clean)
+
+$(clean): $(driver).o.clean \
+ $(addsuffix .cxx.clean,$(obj)) \
+ $(addsuffix .cxx.clean,$(dep)) \
+ $(addprefix $(out_base)/,$(xsd:.xsd=-sskel.cxx.xsd.clean))
+
+
+# How to.
+#
+$(call include,$(bld_root)/cxx/o-e.make)
+$(call include,$(bld_root)/cxx/cxx-o.make)
+$(call include,$(bld_root)/cxx/cxx-d.make)
+$(call include,$(scf_root)/xsde/serializer/xsd-cxx.make)
+
+
+# Dependencies.
+#
+$(call import,$(src_root)/xsde/makefile)
+$(call import,$(src_root)/libxsde/xsde/makefile)
diff --git a/examples/cxx/serializer/polyroot/supermen-simpl-mixin.cxx b/examples/cxx/serializer/polyroot/supermen-simpl-mixin.cxx
new file mode 100644
index 0000000..b6ea058
--- /dev/null
+++ b/examples/cxx/serializer/polyroot/supermen-simpl-mixin.cxx
@@ -0,0 +1,35 @@
+// file : examples/cxx/serializer/polyroot/supermen-simpl-mixin.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#include "supermen-simpl-mixin.hxx"
+
+//
+//
+void person_simpl::
+pre (const person& p)
+{
+ person_ = &p;
+}
+
+std::string person_simpl::
+name ()
+{
+ return person_->name ();
+}
+
+//
+//
+bool superman_simpl::
+can_fly ()
+{
+ return static_cast<const superman*> (person_)->can_fly ();
+}
+
+//
+//
+unsigned int batman_simpl::
+wing_span ()
+{
+ return static_cast<const batman*> (person_)->wing_span ();
+}
diff --git a/examples/cxx/serializer/polyroot/supermen-simpl-mixin.hxx b/examples/cxx/serializer/polyroot/supermen-simpl-mixin.hxx
new file mode 100644
index 0000000..9f9f37c
--- /dev/null
+++ b/examples/cxx/serializer/polyroot/supermen-simpl-mixin.hxx
@@ -0,0 +1,35 @@
+// file : examples/cxx/serializer/polyroot/library-simpl-mixin.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#ifndef SUPERMEN_SIMPL_HXX
+#define SUPERMEN_SIMPL_HXX
+
+#include "supermen.hxx"
+#include "supermen-sskel.hxx"
+
+struct person_simpl: virtual person_sskel
+{
+ virtual void
+ pre (const person&);
+
+ virtual std::string
+ name ();
+
+protected:
+ const person* person_;
+};
+
+struct superman_simpl: virtual superman_sskel, person_simpl
+{
+ virtual bool
+ can_fly ();
+};
+
+struct batman_simpl: virtual batman_sskel, superman_simpl
+{
+ virtual unsigned int
+ wing_span ();
+};
+
+#endif // SUPERMEN_SIMPL_HXX
diff --git a/examples/cxx/serializer/polyroot/supermen-simpl-tiein.cxx b/examples/cxx/serializer/polyroot/supermen-simpl-tiein.cxx
new file mode 100644
index 0000000..f72e0f4
--- /dev/null
+++ b/examples/cxx/serializer/polyroot/supermen-simpl-tiein.cxx
@@ -0,0 +1,59 @@
+// file : examples/cxx/serializer/polyroot/supermen-simpl-tiein.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#include "supermen-simpl-tiein.hxx"
+
+//
+//
+void person_simpl::
+pre (const person& p)
+{
+ person_ = &p;
+}
+
+std::string person_simpl::
+name ()
+{
+ return person_->name ();
+}
+
+//
+//
+superman_simpl::
+superman_simpl ()
+ : superman_sskel (&base_impl_)
+{
+}
+
+bool superman_simpl::
+can_fly ()
+{
+ return superman_ ().can_fly ();
+}
+
+const superman& superman_simpl::
+superman_ ()
+{
+ return *static_cast<const superman*> (base_impl_.person_);
+}
+
+//
+//
+batman_simpl::
+batman_simpl ()
+ : batman_sskel (&base_impl_)
+{
+}
+
+unsigned int batman_simpl::
+wing_span ()
+{
+ return batman_ ().wing_span ();
+}
+
+const batman& batman_simpl::
+batman_ ()
+{
+ return static_cast<const batman&> (base_impl_.superman_ ());
+}
diff --git a/examples/cxx/serializer/polyroot/supermen-simpl-tiein.hxx b/examples/cxx/serializer/polyroot/supermen-simpl-tiein.hxx
new file mode 100644
index 0000000..e67e7f4
--- /dev/null
+++ b/examples/cxx/serializer/polyroot/supermen-simpl-tiein.hxx
@@ -0,0 +1,53 @@
+// file : examples/cxx/serializer/polyroot/supermen-simpl-tiein.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#ifndef SUPERMEN_SIMPL_HXX
+#define SUPERMEN_SIMPL_HXX
+
+#include "supermen.hxx"
+#include "supermen-sskel.hxx"
+
+struct person_simpl: person_sskel
+{
+ virtual void
+ pre (const person&);
+
+ virtual std::string
+ name ();
+
+ // Derived serializers need access to this variable.
+ //
+public:
+ const person* person_;
+};
+
+struct superman_simpl: superman_sskel
+{
+ superman_simpl ();
+
+ virtual bool
+ can_fly ();
+
+ const superman&
+ superman_ ();
+
+private:
+ person_simpl base_impl_;
+};
+
+struct batman_simpl: batman_sskel
+{
+ batman_simpl ();
+
+ virtual unsigned int
+ wing_span ();
+
+ const batman&
+ batman_ ();
+
+private:
+ superman_simpl base_impl_;
+};
+
+#endif // SUPERMEN_SIMPL_HXX
diff --git a/examples/cxx/serializer/polyroot/supermen.hxx b/examples/cxx/serializer/polyroot/supermen.hxx
new file mode 100644
index 0000000..7987a0d
--- /dev/null
+++ b/examples/cxx/serializer/polyroot/supermen.hxx
@@ -0,0 +1,129 @@
+// file : examples/cxx/serializer/polyroot/supermen.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#ifndef SUPERMEN_HXX
+#define SUPERMEN_HXX
+
+#include <string>
+#include <vector>
+
+// Custom type id. We could also use standard C++ typeid/type_info
+// if it is available.
+//
+enum type_id
+{
+ person_type,
+ superman_type,
+ batman_type
+};
+
+//
+//
+struct person
+{
+ virtual
+ ~person ()
+ {
+ }
+
+ person (const std::string& name)
+ : name_ (name)
+ {
+ }
+
+ const std::string&
+ name () const
+ {
+ return name_;
+ }
+
+ void
+ name (const std::string& n)
+ {
+ name_ = n;
+ }
+
+ virtual type_id
+ type () const
+ {
+ return person_type;
+ }
+
+private:
+ std::string name_;
+};
+
+//
+//
+struct superman: person
+{
+ superman (const std::string& name, bool can_fly)
+ : person (name), can_fly_ (can_fly)
+ {
+ }
+
+ bool
+ can_fly () const
+ {
+ return can_fly_;
+ }
+
+ void
+ can_fly (bool cf)
+ {
+ can_fly_ = cf;
+ }
+
+ virtual type_id
+ type () const
+ {
+ return superman_type;
+ }
+
+private:
+ bool can_fly_;
+};
+
+struct batman: superman
+{
+ batman (const std::string& name, unsigned int wing_span)
+ : superman (name, true), wing_span_ (wing_span)
+ {
+ }
+
+ unsigned int
+ wing_span () const
+ {
+ return wing_span_;
+ }
+
+ void
+ wing_span (unsigned int ws)
+ {
+ wing_span_ = ws;
+ }
+
+ virtual type_id
+ type () const
+ {
+ return batman_type;
+ }
+
+private:
+ unsigned int wing_span_;
+};
+
+// Poor man's polymorphic sequence which also assumes ownership of the
+// elements.
+//
+struct supermen: std::vector<person*>
+{
+ ~supermen ()
+ {
+ for (iterator i = begin (); i != end (); ++i)
+ delete *i;
+ }
+};
+
+#endif // SUPERMEN_HXX
diff --git a/examples/cxx/serializer/polyroot/supermen.map b/examples/cxx/serializer/polyroot/supermen.map
new file mode 100644
index 0000000..53b1097
--- /dev/null
+++ b/examples/cxx/serializer/polyroot/supermen.map
@@ -0,0 +1,9 @@
+# file : examples/cxx/serializer/polyroot/supermen.map
+# author : Boris Kolpackov <boris@codesynthesis.com>
+# copyright : not copyrighted - public domain
+
+include "supermen.hxx";
+
+person "const ::person&";
+superman "const ::person&";
+batman "const ::person&";
diff --git a/examples/cxx/serializer/polyroot/supermen.xsd b/examples/cxx/serializer/polyroot/supermen.xsd
new file mode 100644
index 0000000..3d1d4a8
--- /dev/null
+++ b/examples/cxx/serializer/polyroot/supermen.xsd
@@ -0,0 +1,41 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/serializer/polyroot/schema.xsd
+author : Boris Kolpackov <boris@codesynthesis.com>
+copyright : not copyrighted - public domain
+
+-->
+
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+
+ <xsd:complexType name="person">
+ <xsd:sequence>
+ <xsd:element name="name" type="xsd:string"/>
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <!-- substitution group root -->
+ <xsd:element name="person" type="person"/>
+
+
+ <xsd:complexType name="superman">
+ <xsd:complexContent>
+ <xsd:extension base="person">
+ <xsd:attribute name="can-fly" type="xsd:boolean" use="required"/>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+
+ <xsd:element name="superman" type="superman" substitutionGroup="person"/>
+
+ <xsd:complexType name="batman">
+ <xsd:complexContent>
+ <xsd:extension base="superman">
+ <xsd:attribute name="wing-span" type="xsd:unsignedInt" use="required"/>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+
+</xsd:schema>