Main Page Namespace List Class Hierarchy Compound List File List Namespace Members Compound Members Related Pages

# choice.h

Go to the documentation of this file.

    00001 /* -*- c++ -*- */
    00002 #ifndef AKAXISO2_FRAMEWORK_CHOICE_H__
    00003 #define AKAXISO2_FRAMEWORK_CHOICE_H__
    00004
    00010 #include <akaxiso2/framework/qname.h>
    00011 #include <akaxiso2/framework/item.h>
    00012 #include <akaxiso2/framework/model_check.h>
    00013 #include <akaxiso2/framework/xmltype.h>
    00014 #include <vector>
    00015
    00016 namespace aka2 {
    00017
    00018   template<class C>
    00019   class typed_item_iterator : public item_iterator {
    00020   public:
    00021     typed_item_iterator(const C& container) :
    00022       container_(container), current_(container.begin()) {}
    00023     virtual ~typed_item_iterator(){}
    00024
    00025     const C &container_;
    00026     TYPENAME C::const_iterator current_;
    00027
    00028     virtual bool has_next() const { return current_ != container_.end(); }
    00029     virtual const item *next() {
    00030       const item &v = *current_;
    00031       ++current_;
    00032       return &v;
    00033     }
    00034   };
    00035
    00036
    00037   template<class L>
    00038   class choice_op_dispatcher : public choice_op {
    00039   public:
    00040     virtual schematype_id get_schematype() const { return choice_id; }
    00041     virtual std::string get_typename() const { return L::get_xmltype(); }
    00042     virtual const attribute_types* get_attribute_types() const { return 0; }
    00043     virtual const attribute_type *get_anyattr_type() const { return 0; }
    00044     virtual void construct(void *e) const {  L::construct(e); }
    00045     virtual void copy_construct(void *e, const void *src) const { L::copy_construct(e, src); }
    00046     virtual void destruct(void *e) const { L::destruct(e); }
    00047     virtual size_t class_size() const { return L::class_size(); }
    00048     virtual const occurrence &get_occurrence() const { return L::occ_; }
    00049     virtual bool &get_emptiable() const { return L::emptiable_; }
    00050
    00051     virtual bool equals(const void *lhs, const void *rhs) const {
    00052       return L::equals(lhs, rhs);
    00053     }
    00054
    00055     virtual size_t size(const void *container) const { return L::size(container); }
    00056
    00058     virtual const item_types &get_item_types() const { return L::item_types_; }
    00059
    00060     virtual void push(void *container, item &i) const {
    00061       L::push_function(container, i);
    00062     }
    00063     virtual item_iterator* get_iterator(const void *e) const {
    00064       return L::get_iterator(e);
    00065     }
    00066   };
    00067
    00068
    00069   template<class L>
    00070   struct choice_statics {
    00071     static item_types item_types_;
    00072     static choice_op_dispatcher<L> dispatcher_;
    00073     static occurrence occ_;
    00074     static bool emptiable_;
    00075   };
    00076
    00077   template<class L>
    00078   item_types choice_statics<L>::item_types_;
    00079
    00080   template<class L>
    00081   choice_op_dispatcher<L> choice_statics<L>::dispatcher_;
    00082
    00083   template<class L>
    00084   occurrence choice_statics<L>::occ_;
    00085
    00086   template<class L>
    00087   bool choice_statics<L>::emptiable_ = false;
    00088
    00089
    00101   template<class T, class L>
    00102   class choice : public choice_statics<L>,
    00103                  public xmltype_statics<L> {
    00104   public:
    00105     typedef T value_type;
    00106     virtual ~choice(){}
    00107
    00108     static void initialize() {
    00109       if (!system_type_registry().add(L()))
    00110         return;
    00111       L::item_types_.clear();
    00112       L l; l.model();
    00113       check_emptiable(L::item_types_);
    00114     }
    00115     static void uninitialize() {
    00116       L::item_types_.clear();
    00117     }
    00118
    00119     static typed_item_iterator<T>* get_iterator(const void *container) {
    00120       return new typed_item_iterator<T>(*static_cast<const T*>(container));
    00121     }
    00122
    00123
    00124     static void construct(void *e) {
    00125       new (e) T();
    00126     }
    00127     static void copy_construct(void *e, const void *src) {
    00128       new (e) T(*static_cast<const T*>(src));
    00129     }
    00130     static size_t class_size() { return sizeof(T); }
    00131     static void destruct(void *elm) { static_cast<T*>(elm)->~T(); }
    00132
    00133     static bool equals(const void *lhs, const void *rhs) {
    00134       return choice_equals(lhs, rhs, L::dispatcher_);
    00135     }
    00136
    00137     static size_t size(const void *container) { return static_cast<const T*>(container)->size(); }
    00138
    00139     static void push_function(void *container, aka2::item &i) {
    00140       L().methods.push(*static_cast<T*>(container), i);
    00141     }
    00142
    00149     static void occurrence(int minOccurs, int maxOccurs, bool emptiable = false) {
    00150       L::occ_ = aka2::occurrence(minOccurs, maxOccurs);
    00151       L::emptiable_ = emptiable;
    00152     }
    00153
    00162     template<class IL>
    00163     void item(const std::string &tagname, const IL& il, int minOccurs = 1, int maxOccurs = 1,
    00164               bool emptiable = false) {
    00165       IL::initialize();
    00166       element_op &op = IL::dispatcher_;
    00167       qname qn(tagname);
    00168
    00169       itemtype itype(op, emptiable);
    00170       default_op *defop = IL::create_default_op();
    00171       if (defop != 0)
    00172         itype.set_default_op(defop);
    00173       itype.set_name(qn);
    00174
    00175       schematype_id id = itype.get_schematype();
    00176       if ((id == array_id) || (id == choice_id))
    00177         itype.set_occurrence(aka2::occurrence(minOccurs, maxOccurs));
    00178       else {
    00179         if ((minOccurs != 1) && (maxOccurs != 1)) {
    00180           throw tagged_error("element", tagname, "has wrong occurrence.", __FILE__, __LINE__);
    00181         }
    00182       }
    00183       std::pair<item_types::iterator, bool> res =
    00184         L::item_types_.insert(item_types::value_type(qn, itype));
    00185       if (!res.second) {
    00186         throw tagged_error("element", tagname, "was declared twice.", __FILE__, __LINE__);
    00187       }
    00188     }
    00189
    00197     void any(const std::string &tagname, const std::string &ns_list = "##any") {
    00198       aka2::itemtype itype(aka2::any_op::dispatcher_, false);
    00199       qname qn(tagname);
    00200       itype.set_name(qn);
    00201       itype.set_ns_list(ns_list);
    00202       std::pair<item_types::iterator, bool> res =
    00203         L::item_types_.insert(item_types::value_type(qn, itype));
    00204       if (!res.second)
    00205         throw tagged_error("choice", L::get_xmltype(), "any child element is already declared.",
    00206                            __FILE__, __LINE__);
    00207     }
    00208
    00220     void any(const std::string &tagname, int minOccurs, int maxOccurs,
    00221              const std::string &ns_list = "##any") {
    00222       any(tagname, minOccurs, maxOccurs, false, ns_list);
    00223     }
    00224
    00237     void any(const std::string &tagname, int minOccurs, int maxOccurs, bool emptiable,
    00238              const std::string &ns_list) {
    00239       aka2::itemtype itype(aka2::any_array_op::dispatcher_, emptiable);
    00240       itype.set_name(qname(tagname));
    00241       itype.set_occurrence(minOccurs, maxOccurs);
    00242       itype.set_ns_list(ns_list);
    00243       std::pair<item_types::iterator, bool> res =
    00244         L::item_types_.insert(item_types::value_type(qname(tagname), itype));
    00245       if (!res.second)
    00246         throw tagged_error("choice", L::get_xmltype(), "any child element is already declared.",
    00247                            __FILE__, __LINE__);
    00248     }
    00249
    00250
    00257     template<class IL>
    00258     void fixed_item(const std::string &tagname, const std::string &fixed_value, const IL& il) {
    00259       if (IL::dispatcher_.get_schematype() != simpletype_id)
    00260         throw tagged_error("element", tagname, "fixed value should be simpleType.",
    00261                            __FILE__, __LINE__);
    00262       IL::initialize();
    00263       element_op &op = aka2::fixed<IL>::dispatcher_;
    00264       itemtype itype(op, false);
    00265       itype.set_default_op(IL::create_default_op());
    00266       itype.setup_default_value(fixed_value);
    00267       itype.set_name(qname(tagname));
    00268       std::pair<item_types::iterator, bool> res =
    00269         L::item_types_.insert(item_types::value_type(qname(tagname), itype));
    00270       if (!res.second)
    00271         throw tagged_error("element", tagname, "already declared.", __FILE__, __LINE__);
    00272     }
    00273
    00274
    00284     template<class IL>
    00285     void fixed_array(const std::string &tagname, const std::string &fixed_value, const IL& il,
    00286                      int minOccurs, int maxOccurs, bool emptiable = false) {
    00287       if (IL::dispatcher_.get_schematype() != array_id)
    00288         throw tagged_error("element", tagname, " should be array.", __FILE__, __LINE__);
    00289
    00290       qname qn(tagname);
    00291       aka2::occurrence occ(minOccurs, maxOccurs);
    00292
    00293       IL::initialize();
    00294       element_op &op = IL::dispatcher_;
    00295       itemtype itype(op, emptiable);
    00296
    00297       typedef TYPENAME IL::item_leaf_type item_leaf_type;
    00298       default_op *defop = item_leaf_type::create_default_op();
    00299       assert(defop != 0);
    00300       itype.set_default_op(defop);
    00301       itype.setup_default_value(fixed_value);
    00302       itype.set_name(qn);
    00303       itype.set_occurrence(occ);
    00304
    00305       std::pair<item_types::iterator, bool> res =
    00306         L::item_types_.insert(item_types::value_type(qn, itype));
    00307       if (!res.second)
    00308         throw tagged_error("element", tagname, "already declared.", __FILE__, __LINE__);
    00309     }
    00310
    00311     static default_op* create_default_op() { return 0; }
    00312
    00313     static const item_types::value_type* find_item_type(const qname &name) {
    00314       item_types::const_iterator it = L::item_types_.find(name);
    00315       if (it == L::item_types_.end())
    00316         return 0;
    00317       return &*it;
    00318     }
    00319
    00320     static const item_types::value_type* find_item_type(const element_op &eo) {
    00321       for (item_types::const_iterator it = L::item_types_.begin(); it != L::item_types_.end(); ++it)
    00322         if (&it->second.op() == &eo)
    00323           return &*it;
    00324       return 0;
    00325     }
    00326   };
    00327
    00328
    00334   template<class C, class L>
    00335   struct sequential_choice_binder {
    00336   private:
    00337     C& c_;
    00338   public:
    00339     typedef TYPENAME C::value_type value_type;
    00340     typedef TYPENAME C::iterator iterator;
    00341     typedef TYPENAME C::const_iterator const_iterator;
    00342
    00346     sequential_choice_binder(C &container) : c_(container) {}
    00347
    00348     iterator begin() { return c_.begin(); }
    00349     iterator end() { return c_.end(); }
    00350     const_iterator begin() const { return c_.begin(); }
    00351     const_iterator end() const { return c_.end(); }
    00352
    00359     template<class I>
    00360     void push_back(const I &v, const std::string &tagname) {
    00361       const item_types::value_type *vt = L::find_item_type(qname(tagname));
    00362       if (vt == 0)
    00363         unknown_tagname_error(tagname);
    00364       const itemtype &itype = vt->second;
    00365       void *newv = itype.op().replicate(&v);
    00366       if (itype.get_schematype() == fixed_id)
    00367         itype.set_item_to_default(newv);
    00368       c_.push_back(item(newv, itype));
    00369     }
    00370
    00378     template<class R>
    00379     int find_elements(R &r, const std::string &tagname) const {
    00380       qname qn(tagname);
    00381       const item_types::value_type *itype = L::find_item_type(qn);
    00382       if (itype == 0)
    00383         unknown_tagname_error(tagname);
    00384
    00385       int count = 0;
    00386       for (const_iterator it = c_.begin(); it != c_.end(); ++it) {
    00387         if (it->get_name() == qn) {
    00388           r.push_back(item_cast<TYPENAME R::value_type>(*it));
    00389           ++count;
    00390         }
    00391       }
    00392       return count;
    00393     }
    00394
    00395   };
    00396
    00406   template<class T, class L=xiso::leaf<T> >
    00407   class sequential_choice : public choice<T, L> {
    00408   public:
    00409     virtual ~sequential_choice(){}
    00410
    00414     typedef  sequential_choice_binder<T, L> binder;
    00415
    00419     typedef  sequential_choice_binder<const T, L> const_binder;
    00420     sequential<T> methods;
    00421   };
    00422
    00423
    00429   template<class C, class L>
    00430   struct associative_choice_binder {
    00432     typedef TYPENAME C::value_type value_type;
    00434     typedef TYPENAME C::iterator iterator;
    00436     typedef TYPENAME C::const_iterator const_iterator;
    00441     associative_choice_binder(C &container) : c_(container) {}
    00442
    00447     iterator begin() { return c_.begin(); }
    00448
    00454     iterator end() { return c_.end(); }
    00455
    00460     const_iterator begin() const { return c_.begin(); }
    00461
    00466     const_iterator end() const { return c_.end(); }
    00467
    00475     template<class R>
    00476     int find_elements(R &r, const std::string &tagname) const {
    00477       qname qn(tagname);
    00478       const item_types::value_type *itype = L::find_item_type(qn);
    00479       if (itype == 0)
    00480         unknown_tagname_error(tagname);
    00481
    00482       int count = 0;
    00483       for (TYPENAME C::const_iterator it = c_.begin(); it != c_.end(); ++it) {
    00484         if (it->get_name() == qn) {
    00485           r.push_back(item_cast<TYPENAME R::value_type>(*it));
    00486           ++count;
    00487         }
    00488       }
    00489       return count;
    00490     }
    00491
    00492   private:
    00493     C& c_;
    00494   };
    00495
    00496
    00507   template<class T, class L=xiso::leaf<T> >
    00508   class associative_choice : public choice<T, L> {
    00509   public:
    00510     virtual ~associative_choice(){}
    00511
    00513     typedef  associative_choice_binder<T, L> binder;
    00515     typedef  associative_choice_binder<const T, L> const_binder;
    00516     associative<T> methods;
    00517   };
    00518
    00519 } // namespace aka2
    00520
    00521 #endif