/*
 *  Implementation of COSS Relationship Service for MICO
 *  Copyright (C) 1998 Karel Gardas with the assistance of Kay Roemer
 *                                                       & Arno Puder
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Library General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Library General Public License for more details.
 *
 *  You should have received a copy of the GNU Library General Public
 *  License along with this library; if not, write to the Free
 *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *  Send comments and/or bug reports to:
 *                 mico@informatik.uni-frankfurt.de
 *  or to my private e-mail:
 *                 gardask@alpha.inf.upol.cz
 */


#include <iostream.h>
#include <fstream.h>
#include <mico/CosRelationships.h>
#include <mico/Relationship_impl.h>

//#define DEBUG 1


Relationship_impl::Relationship_impl ()
  : IdentifiableObject_impl ()
{
#if DEBUG
  cout << "  <Relationship_impl> Relationship_impl ()\n";
#endif
  
  // n_roles = new CosRelationships::NamedRoles;
  //n_roles->length (0);
  n_roles.length (0);
  
#if DEBUG
  cout << "  <Relationship_impl> Relationship_impl () done.\n";
#endif
 
}


Relationship_impl::Relationship_impl (CORBA::Object_ptr obj)
  : IdentifiableObject_impl (), 
    CosRelationships::Relationship_skel (obj)
{
  CORBA::ORB_ptr orb = _orb();
  char s[1000];

#if DEBUG
  cout << "  <Relationship_impl> Relationship_impl (CORBA::Object_ptr obj)\n";
  cout << "  <Relationship_impl> restoring id " << obj->_ident() << endl;
#endif
  ifstream in (obj->_ident());
  assert (in);

#if DEBUG
  cout << "  <Relationship_impl> restoring rand_id: ";
#endif
  
  in >> random_id;
#if DEBUG
  cout << constant_random_id () << "\n";
#endif
 
  CORBA::String_var tmp_string;
  CORBA::Object_var tmp_obj;
  CORBA::Long how_many;
  CosRelationships::NamedRole nr;

  in >> how_many;
  n_roles.length (how_many);

#if DEBUG
  cout << "  <Relationship_impl> restoring n_roles of "<< n_roles.length ()
       << " members\n";
#endif

  for (int i=0; i<how_many; i++) {
    in >> s;
#if DEBUG
    cout << "  <Relationship_impl> name: " << s << "\n";
#endif
    nr.name = CORBA::string_dup (s);
    in >> s;
#if DEBUG
    cout << "  <Relationship_impl> ior: " << s << "\n";
#endif
    tmp_obj = orb->string_to_object (s);
    CosRelationships::Role_ptr tmp_role 
      = CosRelationships::Role::_narrow (tmp_obj);
#if DEBUG
    if (CORBA::is_nil (tmp_role)) {
      cout << "  <Relationship_impl> Role is NIL!!!\n";
    }
#endif
    nr.aRole = CosRelationships::Role::_duplicate (tmp_role);
    n_roles[i] = nr;
  }
#if DEBUG
  cout << "  <Relationship_impl> done.\n";
#endif
}

Relationship_impl::Relationship_impl (CosRelationships::NamedRoles nr)
  : IdentifiableObject_impl ()
{
#if DEBUG
  cout << "  <Relationship_impl>" 
       << " Relationship_impl (CosRelationships::NamedRoles nr)\n";
#endif
  n_roles = nr;
#if DEBUG
  cout << "  <Relationship_impl> Relationship_impl (...) done\n";
#endif

}


CORBA::Boolean
Relationship_impl::_save_object ()
{

  CORBA::ORB_ptr orb = _orb();
  CORBA::String_var tmp_string;
  CosRelationships::NamedRole nr;

#if DEBUG
  cout << "  <Relationship_impl> saving id " << _ident() << endl;
#endif

  ofstream out (_ident());
  assert (out);

#if DEBUG
  cout << "  <Relationship_impl> writing rand_id: " << constant_random_id () 
       << "\n";
#endif

  out << constant_random_id () << "\n";


#if DEBUG
  cout << "  <Relationship_impl> writing n_roles of "<< n_roles.length ()
       << " members" << flush;
#endif

  out << n_roles.length () << "\n";
  for (CORBA::ULong i=0; i<n_roles.length (); i++) {

#if DEBUG
    cout << "." << flush;
#endif

    nr = n_roles[i];
    out << nr.name.in() << "\n";
    tmp_string = orb->object_to_string (nr.aRole);
    out << tmp_string.in() << "\n";
  }

#if DEBUG
  cout << "done.\n";
#endif

  out.close ();
  
  return TRUE;
}

 
CosRelationships::NamedRoles* 
Relationship_impl::named_roles ()
{

#if DEBUG
  cout << "  <Relationship_impl> named_roles ()\n";
#endif

  CosRelationships::NamedRoles* tmp_nrs = new CosRelationships::NamedRoles;
  tmp_nrs->length (n_roles.length ());
  for (CORBA::ULong i=0; i<n_roles.length (); i++) {
    //  (*tmp_nrs)[i] = n_roles[i];
    (*tmp_nrs)[i].name = n_roles[i].name;
    (*tmp_nrs)[i].aRole = n_roles[i].aRole;
  }

  return tmp_nrs;
}


void 
Relationship_impl::destroy ()
{
#if DEBUG
  cout << "  <Relationship_impl> destroy ()\n";
#endif
  CosRelationships::RelationshipHandle rh;
  rh.constant_random_id = random_id;
  rh.the_relationship = CosRelationships::Relationship::_duplicate (this);
  for (CORBA::ULong i=0; i<n_roles.length (); i++) {
#ifdef HAVE_EXCEPTIONS
    try {
#endif
      n_roles[i].aRole->unlink (rh);
#ifdef HAVE_EXCEPTIONS
    }
    catch (CosRelationships::Role::UnknownRelationship_var &ex) {
#if DEBUG
      cout << "  <Relationship_impl> exception when unlink role!\n";
#endif
    }
#endif
  }

  CORBA::BOA_var boa = _boa ();
  CORBA::ORB_var orb = _orb ();
  boa->deactivate_obj (this);
  orb->shutdown (TRUE);
 }
