diff options
Diffstat (limited to 'examples/cxx/serializer/polyroot')
-rw-r--r-- | examples/cxx/serializer/polyroot/README | 46 | ||||
-rw-r--r-- | examples/cxx/serializer/polyroot/driver.cxx | 142 | ||||
-rw-r--r-- | examples/cxx/serializer/polyroot/makefile | 73 | ||||
-rw-r--r-- | examples/cxx/serializer/polyroot/supermen-simpl-mixin.cxx | 35 | ||||
-rw-r--r-- | examples/cxx/serializer/polyroot/supermen-simpl-mixin.hxx | 35 | ||||
-rw-r--r-- | examples/cxx/serializer/polyroot/supermen-simpl-tiein.cxx | 59 | ||||
-rw-r--r-- | examples/cxx/serializer/polyroot/supermen-simpl-tiein.hxx | 53 | ||||
-rw-r--r-- | examples/cxx/serializer/polyroot/supermen.hxx | 129 | ||||
-rw-r--r-- | examples/cxx/serializer/polyroot/supermen.map | 9 | ||||
-rw-r--r-- | examples/cxx/serializer/polyroot/supermen.xsd | 41 |
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> |