//CUPPA:include=+
//CUPPA:include=-
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/TestAssert.h>

//CUPPA:namespace=+
//CUPPA:namespace=-

#include <akaxiso/akaxiso.h>
#include <akaxiso/content_model.h>

namespace {

  struct any_test {
    std::string member1_;
    aka2::any any_;
    std::string member2_;
  };

  struct any_array_test {
    aka2::any_array array1_;
    std::string value_;
    aka2::any_array array2_;
  };

  typedef std::vector<aka2::item> any_choice;
  typedef std::vector<aka2::item> any_array_choice;


  struct any_choice_leaf : aka2::sequential_choice<any_choice, any_choice_leaf> {
    void model() {
      any();
      item("value", xiso::leaf<std::string>());
    }
  };


  struct any_array_choice_leaf : aka2::sequential_choice<any_array_choice, any_array_choice_leaf> {
    void model() {
      any(0, aka2::unbounded);
      item("value", xiso::leaf<std::string>());
    }
  };

}

namespace xiso {

  template<>
  struct leaf<any_test> : aka2::sequence<any_test> {
    void model() {
      member("member1", &any_test::member1_);
      member(any, &any_test::any_);
      member("member2", &any_test::member2_);
    }
  };


  template<>
  struct leaf<any_array_test> : aka2::sequence<any_array_test> {
    void model() {
      member(any, &any_array_test::array1_, 0, aka2::unbounded);
      member("value", &any_array_test::value_);
      member(any, &any_array_test::array2_, 0, aka2::unbounded);
    }
  };

}


class anyTest : public CppUnit::TestFixture {
  CPPUNIT_TEST_SUITE(anyTest);
//CUPPA:suite=+
  CPPUNIT_TEST(test_serialize);
  CPPUNIT_TEST(test_parse);
  CPPUNIT_TEST(test_serialize_array);
  CPPUNIT_TEST(test_parse_array);
  CPPUNIT_TEST(test_serialize_choice);
  CPPUNIT_TEST(test_parse_choice);
  CPPUNIT_TEST(test_serialize_array_choice);
  CPPUNIT_TEST(test_parse_array_choice);
//CUPPA:suite=-
  CPPUNIT_TEST_SUITE_END();
private:

  // your stuff...

public:

  virtual void setUp() {
    aka2::initialize();
    aka2::doctype("any_test", xiso::leaf<any_test>());
    aka2::doctype("any_array_test", xiso::leaf<any_array_test>());
    aka2::doctype("any_choice", any_choice_leaf()).set_occurrence(0, aka2::unbounded);
    aka2::doctype("any_array_choice", any_array_choice_leaf()).set_occurrence(0, aka2::unbounded);
  }
  virtual void tearDown() { 
    aka2::uninitialize();
  }

  any_test create_root() {
    any_test root;
    root.member1_ = "member1";
    root.member2_ = "member2";

    root.any_.name_ = aka2::qname("any_element");
    root.any_.value_ = "any's value.";

    root.any_.attributes_.push_back(aka2::wc_attribute(aka2::qname("test"), "value"));


    aka2::any child;
    child.name_ = aka2::qname("child_node");
    root.any_.children_.push_back(child);

    return root;
  }

//CUPPA:decl=+
  void test_serialize() {
    any_test root = create_root();
    aka2::xml_serializer ser;
    std::ostringstream ostm;
    ser.serialize(root, "any_test", ostm);
  }

  void test_serialize_array() {
    any_array_test root;
    root.value_ = "value";
    aka2::xml_serializer ser;
    std::ostringstream ostm;
    ser.serialize(root, "any_array_test", ostm);
    //std::cout << ostm.rdbuf()->str() << std::endl;
  }


  void test_serialize_choice() {
    any_choice root;
    any_choice_leaf::moc moc(root);

    moc.push_back(std::string("test"), "value");
    aka2::any an;
    an.name_ = aka2::qname("test");
    moc.push_back(an, "&any");

    aka2::xml_serializer ser;
    std::ostringstream ostm;
    ser.serialize(root, "any_choice", ostm);

    //std::cout << ostm.rdbuf()->str() << std::endl;
  }



  void test_parse_choice() {
    any_choice root;
    any_choice_leaf::moc moc(root);

    moc.push_back(std::string("test"), "value");
    aka2::any an;
    an.name_ = aka2::qname("test");
    moc.push_back(an, "&any");

    aka2::xml_serializer ser;
    std::ostringstream ostm;
    ser.serialize(root, "any_choice", ostm);

    aka2::xml_parser parser;
    aka2::document doc = parser.parse(ostm.rdbuf()->str());

  }


  void test_parse() {
    any_test root = create_root();
    aka2::xml_serializer ser;
    std::ostringstream ostm;
    ser.serialize(root, "any_test", ostm);

    aka2::xml_parser parser;
    aka2::document doc = parser.parse(ostm.rdbuf()->str());
  }


  void test_parse_array() {
    any_array_test root;

    aka2::any an;
    an.name_ = aka2::qname("test1");
    //root.array1_.push_back(an);
    //root.array1_.push_back(an);

    root.value_ = "value";

    an.name_ = aka2::qname("test2");
    root.array2_.push_back(an);
    root.array2_.push_back(an);

    aka2::xml_serializer ser;
    std::ostringstream ostm;
    ser.serialize(root, "any_array_test", ostm);
    //std::cout << ostm.rdbuf()->str() << std::endl;
    aka2::xml_parser parser;
    aka2::document doc = parser.parse(ostm.rdbuf()->str());

    //ser.serialize(doc, std::cout);
  }



  void test_serialize_array_choice() {
    any_array_choice root;
    any_array_choice_leaf::moc moc(root);

    aka2::any_array ar;
    aka2::any an;
    an.name_ = aka2::qname("any_array_item");
    ar.push_back(an);

    moc.push_back(ar, "&any");
    moc.push_back(std::string("test"), "value");

    aka2::xml_serializer ser;
    std::ostringstream ostm;
    ser.serialize(root, "any_array_choice", ostm);

    //std::cout << ostm.rdbuf()->str() << std::endl;
  }


  void test_parse_array_choice() {
    any_array_choice root;
    any_array_choice_leaf::moc moc(root);

    aka2::any_array ar;
    aka2::any an;
    an.name_ = aka2::qname("any_array_item");
    ar.push_back(an);

    moc.push_back(ar, "&any");
    moc.push_back(std::string("test"), "value");

    aka2::xml_serializer ser;
    std::ostringstream ostm;
    ser.serialize(root, "any_array_choice", ostm);

    //std::cout << ostm.rdbuf()->str() << std::endl;

    aka2::xml_parser parser;
    aka2::document doc = parser.parse(ostm.rdbuf()->str());
    //ser.serialize(doc, std::cout);

  }


//CUPPA:decl=-
};

//CUPPA:impl=+
//CUPPA:impl=-

CPPUNIT_TEST_SUITE_REGISTRATION(anyTest);
