/* -*- c++ -*- */
#ifndef AKAXISO_MEMBERTYPE_H__
#define AKAXISO_MEMBERTYPE_H__

#include <akaxiso/classes/member.h>
#include <akaxiso/classes/traits.h>
#include <akaxiso/classes/shared_ptr.h>
#include <akaxiso/classes/node.h>

#include <assert.h>

namespace aka2 {

  class any_member : public element_props {
  public:
    any_member() : mgetter_(0) {}
    any_member(const member_getter *getter, const element_op &op)
      : element_props(op), mgetter_(getter) {}

    const member_getter &getter() const { return *mgetter_; }
    bool equals(const void *lhs, const void *rhs) const;
    void copy(void *dest, const void *src) const;
    bool empty() const { return mgetter_.get() == 0; }
  protected:
    shared_ptr<const member_getter> mgetter_;
  };

  class named_member : public any_member {
  public:
    named_member() {}
    named_member(const member_getter *getter, const element_op &op) 
      : any_member(getter, op){}

    void set_member_to_default(void *e) const;
  };


  class member_type : public named_member {
  public:
    member_type() {}
    member_type(const member_getter *getter, const element_op &op) 
      : named_member(getter, op){}
    bool is_element() const { return name_.local()[0] != '&'; }
  };


  class attribute_type : public named_member  {
  public:
    attribute_type() : required_(false) {}
    attribute_type(const member_getter *mgetter, const element_op &op) : 
      named_member(mgetter, op), required_(false) {    
      schematype_id id = get_schematype();
      if ((id != simpletype_id) &&
	  (id != fixed_id))
	throw internal_error();
    }

    void set_required(bool val) {
      assert(default_.get() != 0); // Simpletype always have default_op.
      required_ = val;
    }

    void set_value_attr(const std::string &defval) { 
      default_->set_default(defval); 
    }

    bool is_required() const { return required_; }
    bool is_attribute_default(const void *e) const;
  private:
    bool required_;

    // Hide occurence related method.
    occurrence &set_occurrence(const occurrence &occ);
    const occurrence &get_occurrence() const;
  };

  struct member_types : public std::vector<member_type> {};
  struct member_map : public std::map<qname, member_type, qname_less> {};
  struct attribute_types : public std::map<qname, attribute_type, qname_less> {};

  typedef std::map<qname, std::string, qname_less> attribute_values;
}

#endif
