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

Generated on Sun Dec 19 22:58:57 2004 for akaxiso2 by doxygen1.2.18