00001
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 }
00520
00521 #endif