#include "construct.h"
#include "membertype.h"
#include "member_cache.h"

using namespace aka2;


void aka2::element_construct(const node &nd) {
  switch (nd.get_schematype()) {
  case sequence_id:
    sequence_construct(nd.ptr(), static_cast<const sequence_op&>(nd.op()));
    break; 
  case all_id:
    all_construct(nd.ptr(), static_cast<const all_op&>(nd.op()));
    break;
  case simplecontent_id: 
    simplecontent_construct(nd.ptr(), static_cast<const simplecontent_op&>(nd.op()));
    break;
  case ptrmember_id:
    ptrmember_construct(nd.ptr(), static_cast<const ptrmember_op&>(nd.op()));
    break;
  case simpletype_id:
  case choice_id:
  case array_id:
  default:
    ;
  }
}


void aka2::member_construct(void *e, const named_member &mtype) {
  schematype_id id = mtype.get_schematype();
  if (id == simpletype_id)
    mtype.set_member_to_default(e);
  else {
    member_cache cache(e, mtype.op(), mtype.getter());
    cache.prepare(false);
    element_construct(cache.get_node());
    cache.flush();
  }
}

void aka2::attributes_construct(void *e, const attribute_types *attrtypes) {
  if (attrtypes == 0)
    return;
  
  for (attribute_types::const_iterator it = attrtypes->begin();
       it != attrtypes->end(); ++it) {
    member_construct(e, *it);
  }
}

void aka2::sequence_construct(void *e, const sequence_op &sop) {
  attributes_construct(e, sop.get_attribute_types());
  const member_types &mtypes = sop.get_member_types();
  for (member_types::const_iterator it = mtypes.begin(); it != mtypes.end(); ++it) {
    member_construct(e, *it);
  }
}


void aka2::all_construct(void *e, const all_op &aop) {

  attributes_construct(e, aop.get_attribute_types());
  const member_map &mmap = aop.get_member_map();
  for (member_map::const_iterator it = mmap.begin(); it != mmap.end(); ++it)
    member_construct(e, it->second);
}


void aka2::simplecontent_construct(void *e, const simplecontent_op &sop) {
  attributes_construct(e, sop.get_attribute_types());
  const member_type &mtype = sop.get_valuetype();
  mtype.set_member_to_default(e);
}


void aka2::ptrmember_construct(void *e, const ptrmember_op &pop) {
  pop.set_null(e);
}

