//
// valuetype_init_cs.cpp,v 1.10 2004/06/08 14:12:16 parsons Exp
//

// ============================================================================
//
// = LIBRARY
//    TAO IDL
//
// = FILENAME
//    valuetype_init_cs.cpp
//
// = DESCRIPTION
//    Visitor generating code for Valuetypes factory in the client header
//    (see IDL to C++ mapping)
//
// = AUTHOR
//   Boris Kolpackov <bosk@ipmce.ru>
//
//
// ============================================================================

ACE_RCSID (be_visitor_valuetype,
           valuetype_init_cs,
           "valuetype_init_cs.cpp,v 1.10 2004/06/08 14:12:16 parsons Exp")

be_visitor_valuetype_init_cs::be_visitor_valuetype_init_cs (
    be_visitor_context *ctx
  )
  : be_visitor_valuetype_init (ctx)
{
}

be_visitor_valuetype_init_cs::~be_visitor_valuetype_init_cs (void)
{
}

int
be_visitor_valuetype_init_cs::visit_valuetype (be_valuetype *node)
{
  if (node->is_abstract ())
    {
      return 0;
    }

  // There are three possible situations.
  // (1) If there is no initializers but at least one operation.
  //     In this case we don't need to bother about factory.
  //
  // (2) There are no (operations or initializers) (i.e. only state
  //     members) then we need a concrete type-specific factory
  //     class whose create_for_unmarshal creates OBV_ class.
  //
  // (3) There is at least one operation and at least one initializer.
  //     In this case we need to generate abstract factory class.

  be_valuetype::FactoryStyle factory_style =
    node->determine_factory_style ();

  if (factory_style == be_valuetype::FS_NO_FACTORY)
    {
      return 0;
    }

  TAO_OutStream *os = this->ctx_->stream ();

  char fname [NAMEBUFSIZE];  // to hold the full and
  char lname [NAMEBUFSIZE];  // local _out names

  ACE_OS::memset (fname,
                  '\0',
                  NAMEBUFSIZE);
  ACE_OS::sprintf (fname,
                   "%s_init",
                   node->full_name ());

  ACE_OS::memset (lname,
                  '\0',
                  NAMEBUFSIZE);
  ACE_OS::sprintf (lname,
                   "%s_init",
                   node->local_name ());

  *os << be_nl << be_nl << "// TAO_IDL - Generated from" << be_nl
      << "// " << __FILE__ << ":" << __LINE__;

  // ctor
  *os << be_nl << be_nl
      << fname << "::" << lname << " (void)" << be_nl
      << "{" << be_nl << "}";

  // dtor
  *os << be_nl << be_nl
      << fname << "::~" << lname << " (void)" << be_nl
      << "{" << be_nl << "}";

  // The _downcast method.
  *os << be_nl << be_nl
      << node->name () << "_init *" << be_nl << node->name ()
      << "_init::_downcast (CORBA::ValueFactoryBase *v)" << be_nl
      << "{" << be_idt_nl
      << "if (v == 0)" << be_idt_nl
      << "{" << be_idt_nl
      << "return 0;" << be_uidt_nl
      << "}" << be_uidt_nl << be_nl
      << "return dynamic_cast< ::" << node->name () << "_init * > (v);" << be_uidt_nl
      << "}";

  // tao_repository_id
  *os << be_nl << be_nl
      << "const char* " << be_nl
      << fname << "::tao_repository_id (void)" << be_nl
      << "{" << be_idt_nl
      <<   "return ::" << node->full_name ()
      <<                "::_tao_obv_static_repository_id ();"
      << be_uidt_nl << "}";


  if (factory_style == be_valuetype::FS_CONCRETE_FACTORY)
    {
      // generate create_for_unmarshal()
      *os << be_nl << be_nl
          << "CORBA::ValueBase *" << be_nl
          << fname << "::create_for_unmarshal" << " "
          << "(ACE_ENV_SINGLE_ARG_DECL)" << be_nl
          << "{" << be_idt_nl
          << "CORBA::ValueBase *ret_val = 0;" << be_nl
          << "ACE_NEW_THROW_EX (" << be_idt << be_idt_nl
          << "ret_val," << be_nl
          << "OBV_" << node->full_name () << "," << be_nl
          << "CORBA::NO_MEMORY ()" << be_uidt_nl
          << ");" << be_uidt_nl
          << "return ret_val;"
          << be_uidt_nl << "}";

        if (node->supports_abstract ())
          {
            *os << be_nl << be_nl
                << "CORBA::AbstractBase_ptr" << be_nl
                << fname << "::create_for_unmarshal_abstract (ACE_ENV_SINGLE_ARG_DECL)" << be_nl
                << "{" << be_idt_nl
                << "CORBA::AbstractBase *ret_val = 0;" << be_nl
                << "ACE_NEW_THROW_EX (" << be_idt << be_idt_nl
                << "ret_val," << be_nl
                << "OBV_" << node->full_name () << "," << be_nl
                << "CORBA::NO_MEMORY ()" << be_uidt_nl
                << ");" << be_uidt_nl
                << "return ret_val;"
                << be_uidt_nl << "}";
          }
    }

  return 0;
}

int
be_visitor_valuetype_init_cs::visit_factory (be_factory *)
{
  return 0;
}
