// **********************************************************************
//
// Copyright (c) 1999
// Object Oriented Concepts, Inc.
// Billerica, MA, USA
//
// All Rights Reserved
//
// **********************************************************************

#include <OB/CORBA.h>
#include <Types.h>
#include <IntRep_impl.h>
#include <Util.h>

#include <ctype.h>

OB_MAKE_NARROW_IMPL_2(CORBA_Contained_impl, CORBA_Contained_skel,
		      CORBA_IRObject_impl)
OB_MAKE_NARROW_IMPL_2(CORBA_Container_impl, CORBA_Container_skel,
		      CORBA_IRObject_impl)
OB_MAKE_NARROW_IMPL_2(CORBA_Repository_impl, CORBA_Repository_skel,
		      CORBA_Container_impl)
OB_MAKE_NARROW_IMPL_3(CORBA_ModuleDef_impl, CORBA_ModuleDef_skel,
		      CORBA_Container_impl, CORBA_Contained_impl)
OB_MAKE_NARROW_IMPL_2(CORBA_ConstantDef_impl, CORBA_ConstantDef_skel,
		      CORBA_Contained_impl)
OB_MAKE_NARROW_IMPL_3(CORBA_TypedefDef_impl, CORBA_TypedefDef_skel,
		      CORBA_Contained_impl, CORBA_IDLType_impl)
OB_MAKE_NARROW_IMPL_2(CORBA_StructDef_impl, CORBA_StructDef_skel,
		      CORBA_TypedefDef_impl)
OB_MAKE_NARROW_IMPL_2(CORBA_UnionDef_impl, CORBA_UnionDef_skel,
		      CORBA_TypedefDef_impl)
OB_MAKE_NARROW_IMPL_2(CORBA_EnumDef_impl, CORBA_EnumDef_skel,
		      CORBA_TypedefDef_impl)
OB_MAKE_NARROW_IMPL_2(CORBA_AliasDef_impl, CORBA_AliasDef_skel,
		      CORBA_TypedefDef_impl)
OB_MAKE_NARROW_IMPL_2(CORBA_PrimitiveDef_impl, CORBA_PrimitiveDef_skel,
		      CORBA_IDLType_impl)
OB_MAKE_NARROW_IMPL_2(CORBA_StringDef_impl, CORBA_StringDef_skel,
		      CORBA_IDLType_impl)
OB_MAKE_NARROW_IMPL_2(CORBA_SequenceDef_impl, CORBA_SequenceDef_skel,
		      CORBA_IDLType_impl)
OB_MAKE_NARROW_IMPL_2(CORBA_ArrayDef_impl, CORBA_ArrayDef_skel,
		      CORBA_IDLType_impl)
OB_MAKE_NARROW_IMPL_2(CORBA_ExceptionDef_impl, CORBA_ExceptionDef_skel,
		      CORBA_Contained_impl)
OB_MAKE_NARROW_IMPL_2(CORBA_AttributeDef_impl, CORBA_AttributeDef_skel,
		      CORBA_Contained_impl)
OB_MAKE_NARROW_IMPL_2(CORBA_OperationDef_impl, CORBA_OperationDef_skel,
		      CORBA_Contained_impl)
OB_MAKE_NARROW_IMPL_4(CORBA_InterfaceDef_impl, CORBA_InterfaceDef_skel,
		      CORBA_Container_impl, CORBA_Contained_impl,
		      CORBA_IDLType_impl)

// ----------------------------------------------------------------------

CORBA_Contained_impl::CORBA_Contained_impl(CORBA_ORB_ptr orb,
					   CORBA_Container_ptr p)
    : CORBA_IRObject_impl(orb),
      definedIn_(CORBA_Container::_duplicate(p))
{
}

CORBA_Contained_impl::~CORBA_Contained_impl()
{
}

void
CORBA_Contained_impl::releaseInternal()
{
    definedIn_ = CORBA_Container::_nil();
    CORBA_IRObject_impl::releaseInternal();
}

void
CORBA_Contained_impl::destroy()
{
    CORBA_Contained_var self = _this();
    
    CORBA_Container_impl* container =
        CORBA_Container_impl::_narrow_impl(definedIn_);
    assert(container);
    container -> remove(self);

    CORBA_IRObject_impl::destroy();
}

char*
CORBA_Contained_impl::id()
{
    return CORBA_string_dup(id_);
}

void
CORBA_Contained_impl::id(const char* s)
{
    if(id_.in() && strcmp(id_, s) == 0)
	return;

    CORBA_Repository_var rep = containing_repository();
    CORBA_Contained_var con = rep -> lookup_id(s);
    
    if(!CORBA_is_nil(con))
    {
	//
        // ID does already exist
	//
	throw CORBA_INTF_REPOS(OBMinorIdExists, CORBA_COMPLETED_NO);
    }
    
    id_ = s;
}

char*
CORBA_Contained_impl::name()
{
    return CORBA_string_dup(name_);
}

void
CORBA_Contained_impl::name(const char* s)
{
    if(name_.in() && strcmp(name_, s) == 0)
	return;

    //
    // Find out whether name already exists. Using case-insensitive
    // comparison.
    //
    CORBA_ULong i, j;

    // Exclude inherited names
    CORBA_ContainedSeq_var seq = definedIn_ -> contents(CORBA_dk_all, true);

    CORBA_String_var s1 = s;
    for(j = 0 ; j < strlen(s1) ; j++)
	if(isupper(s1[j]))
	    s1[j] = tolower(s1[j]);

    for(i = 0 ; i < seq -> length() ; i++)
    {
	CORBA_String_var s2 = seq[i] -> name();
	for(j = 0 ; j < strlen(s2) ; j++)
	    if(isupper(s2[j]))
		s2[j] = tolower(s2[j]);

	if(strcmp(s1, s2) == 0)
	{
	    //
	    // Name does already exist
	    //
	    throw CORBA_INTF_REPOS(OBMinorNameExists, CORBA_COMPLETED_NO);
	}
    }
    
    name_ = s;
}

char*
CORBA_Contained_impl::version()
{
    return CORBA_string_dup(version_);
}

void
CORBA_Contained_impl::version(const char* s)
{
    version_ = s;
}

CORBA_Container_ptr
CORBA_Contained_impl::defined_in()
{
    return CORBA_Container::_duplicate(definedIn_);
}

char*
CORBA_Contained_impl::absolute_name()
{
    CORBA_Contained_var contained = CORBA_Contained::_narrow(definedIn_);

    if(!CORBA_is_nil(contained))
    {
	CORBA_String_var s = contained -> absolute_name();
	char* result = CORBA_string_alloc(strlen(s) + 2 + strlen(name_));
	strcpy(result, s);
	strcat(result, "::");
	strcat(result, name_);
	return result;
    }
    else
    {
	char* result = CORBA_string_alloc(2 + strlen(name_));
	strcpy(result, "::");
	strcat(result, name_);
	return result;
    }
}

CORBA_Repository_ptr
CORBA_Contained_impl::containing_repository()
{
    CORBA_Repository_var repository = CORBA_Repository::_narrow(definedIn_);
    
    if(CORBA_is_nil(repository))
    {
	CORBA_Contained_var contained = CORBA_Contained::_narrow(definedIn_);
	assert(!CORBA_is_nil(contained));
	
	return contained -> containing_repository();
    }
    else
	return CORBA_Repository::_duplicate(repository);
}

void
CORBA_Contained_impl::move(CORBA_Container_ptr new_container,
			   const char* identifier,
			   const char* new_version)
{
    //
    // Get self-reference
    //
    CORBA_Contained_var self = _this();

    //
    // Remove from old container
    //
    CORBA_Container_impl* oldCont =
	CORBA_Container_impl::_narrow_impl(definedIn_);
    assert(oldCont);
    oldCont -> remove(self);

    //
    // Add to new container
    //
    CORBA_RepositoryId_var oldId = id();
    CORBA_Identifier_var oldName = name();
    CORBA_VersionSpec_var oldVersion = version();
    try
    {
	definedIn_ = CORBA_Container::_duplicate(new_container);
	id(id_); // Set old id again for container id check
	name(identifier);
	version(new_version);
	
	CORBA_Container_impl* newCont =
	    CORBA_Container_impl::_narrow_impl(new_container);
	assert(newCont);
	newCont -> add(self);
    }
    catch(...)
    {
	id(oldId);
	name(oldName);
	version(oldVersion);
	oldCont -> add(self);

	throw;
    }
}

// ----------------------------------------------------------------------

void
CORBA_Container_impl::add(CORBA_Contained_ptr p)
{
    contents_.append(CORBA_Contained::_duplicate(p));
}

void
CORBA_Container_impl::remove(CORBA_Contained_ptr p)
{
    CORBA_Identifier_var n1 = p -> name();
    CORBA_Long i;
    for(i = contents_.length() - 1 ; i >= 0 ; i--)
    {
	CORBA_Identifier_var n2 = contents_[i] -> name();
	if(strcmp(n1, n2) == 0)
	{
	    contents_.remove(i);
	    break;
	}
    }

    assert(i > -1);
}

CORBA_Container_impl::CORBA_Container_impl(CORBA_ORB_ptr orb)
    : CORBA_IRObject_impl(orb)
{
}

CORBA_Container_impl::~CORBA_Container_impl()
{
}

void
CORBA_Container_impl::releaseInternal()
{
    for(CORBA_ULong i = 0 ; i < contents_.length() ; i++)
    {
	CORBA_Contained_impl* p =
	    CORBA_Contained_impl::_narrow_impl(contents_[i]);

	if(p)
	    p -> releaseInternal();
    }
    
    contents_.length(0);
    CORBA_IRObject_impl::releaseInternal();
}

CORBA_Contained_ptr
CORBA_Container_impl::lookup(const char* search_name)
{
    if(strncmp(search_name, "::", 2) == 0) // Absolute name, begining with "::"
    {
	CORBA_Container_var self = _this();
	CORBA_Contained_var contained = CORBA_Contained::_narrow(self);

	//
        // Must be contained, since it cannot
	// be a repository (the repository overwrites lookup())
	//
	assert(!CORBA_is_nil(contained));

	CORBA_Repository_var repository = contained -> containing_repository();
	return repository -> lookup(search_name);
    }
    else // Relative name, not begining with "::"
    {
	const char* s2 = strstr(search_name, "::");
	CORBA_String_var s1;

	if(s2)
	{
	    CORBA_ULong len = s2 - search_name;
	    s1 = CORBA_string_alloc(len);
	    strncpy(s1.inout(), search_name, len);
	    s1[len] = '\0';
	    s2 += 2;
	}
	else
	    s1 = search_name;

	for(CORBA_ULong i = 0 ; i < contents_.length(); i++)
	{
	    CORBA_String_var n = contents_[i] -> name();
	    if(strcmp(n, s1) == 0)
	    {
		if(s2)
		{
		    CORBA_Container_var container =
			CORBA_Container::_narrow(contents_[i]);
		    if(CORBA_is_nil(container))
			return CORBA_Contained::_nil();
		    else
			return container -> lookup(s2);
		}
		else
		    return CORBA_Contained::_duplicate(contents_[i]);
	    }
	}

	return CORBA_Contained::_nil();
    }
}

CORBA_ContainedSeq*
CORBA_Container_impl::contents(CORBA_DefinitionKind limit_type,
			       CORBA_Boolean /*exclude_inherited*/)
{
    CORBA_ContainedSeq* s = new CORBA_ContainedSeq;

    for(CORBA_ULong i = 0 ; i < contents_.length() ; i++)
	if(limit_type == CORBA_dk_all ||
	   limit_type == contents_[i] -> def_kind())
	    s -> append(contents_[i]);
    
    return s;
}

CORBA_ContainedSeq*
CORBA_Container_impl::lookup_name(const char* search_name,
				  CORBA_Long levels_to_search,
				  CORBA_DefinitionKind limit_type,
				  CORBA_Boolean exclude_inherited)
{
    CORBA_ULong i, j, k;

    CORBA_ContainedSeq* s = new CORBA_ContainedSeq;

    if(levels_to_search != 0)
    {
	levels_to_search--;

	for(i = 0 ; i < contents_.length() ; i++)
	{
	    if(limit_type == CORBA_dk_all ||
	       limit_type == contents_[i] -> def_kind())
	    {
		CORBA_Identifier_var name = contents_[i] -> name();
		if(strcmp(search_name, name) == 0)
		    s -> append(contents_[i]);

		if(levels_to_search != 0)
		{
		    CORBA_Container_var cont =
			CORBA_Container::_narrow(contents_[i]);
		    if(!CORBA_is_nil(cont))
		    {
			CORBA_ContainedSeq_var s2 =
			    cont -> lookup_name(search_name,
						levels_to_search,
						limit_type,
						exclude_inherited);
			
			for(j = 0 ; j < s2 -> length() ; j++)
			{
			    CORBA_RepositoryId_var id2 = s2[j] -> id(); 
			    
			    for(k = 0 ; k < s -> length() ; k++)
			    {
				CORBA_RepositoryId_var id = (*s)[k] -> id(); 
				
				if(strcmp(id, id2) == 0)
				    break;
			    }
			    
			    if(k == s -> length())
				s -> append(s2[j]);
			}
		    }
		}
	    }
	}
    }
		
    return s;
}

CORBA_Container::DescriptionSeq*
CORBA_Container_impl::describe_contents(CORBA_DefinitionKind limit_type,
					CORBA_Boolean exclude_inherited,
					CORBA_Long max_returned_objs)
{
    CORBA_ContainedSeq_var cs = contents(limit_type, exclude_inherited);

    CORBA_ULong len = cs -> length();

    if(max_returned_objs >= 0 && len > (CORBA_ULong)max_returned_objs)
	len = (CORBA_ULong)max_returned_objs;

    DescriptionSeq* s = new DescriptionSeq(len);

    for(CORBA_ULong i = 0 ; i < len ; i++)
    {
	if(limit_type == CORBA_dk_all ||
	   limit_type == cs[i] -> def_kind())
	{
	    CORBA_Contained::Description_var description =
		cs[i] -> describe();
	    
	    CORBA_Container::Description desc;
	    desc.contained_object = cs[i];
	    desc.kind = description -> kind;
	    desc.value = description -> value;
	    
	    s -> append(desc);
	}
    }
    
    return s;
}

CORBA_ModuleDef_ptr
CORBA_Container_impl::create_module(const char* id,
				    const char* name,
				    const char* version)
{
    CORBA_Container_var self = _this();
    CORBA_ModuleDef_var p = new CORBA_ModuleDef_impl(orb_, self);
    p -> name(name);
    p -> id(id);
    p -> version(version);
    contents_.append(CORBA_ModuleDef::_duplicate(p));
    return CORBA_ModuleDef::_duplicate(p);
}

CORBA_ConstantDef_ptr
CORBA_Container_impl::create_constant(const char* id,
				      const char* name,
				      const char* version,
				      CORBA_IDLType_ptr type,
				      const CORBA_Any& value)
{
    CORBA_Container_var self = _this();
    CORBA_ConstantDef_var p = new CORBA_ConstantDef_impl(orb_, self);
    p -> name(name);
    p -> id(id);
    p -> version(version);
    p -> type_def(type);
    p -> value(value);
    contents_.append(CORBA_ConstantDef::_duplicate(p));
    return CORBA_ConstantDef::_duplicate(p);
}

CORBA_StructDef_ptr
CORBA_Container_impl::create_struct(const char* id,
				    const char* name,
				    const char* version,
				    const CORBA_StructMemberSeq& members)
{
    CORBA_Container_var self = _this();
    CORBA_StructDef_var p = new CORBA_StructDef_impl(orb_, self);
    p -> name(name);
    p -> id(id);
    p -> version(version);
    p -> members(members);
    contents_.append(CORBA_StructDef::_duplicate(p));
    return CORBA_StructDef::_duplicate(p);
}

CORBA_UnionDef_ptr
CORBA_Container_impl::create_union(const char* id,
				   const char* name,
				   const char* version,
				   CORBA_IDLType_ptr discriminator_type,
				   const CORBA_UnionMemberSeq& members)
{
    CORBA_Container_var self = _this();
    CORBA_UnionDef_var p = new CORBA_UnionDef_impl(orb_, self);
    p -> name(name);
    p -> id(id);
    p -> version(version);
    p -> discriminator_type_def(discriminator_type);
    p -> members(members);
    contents_.append(CORBA_UnionDef::_duplicate(p));
    return CORBA_UnionDef::_duplicate(p);
}

CORBA_EnumDef_ptr
CORBA_Container_impl::create_enum(const char* id,
				  const char* name,
				  const char* version,
				  const CORBA_EnumMemberSeq& members)
{
    CORBA_Container_var self = _this();
    CORBA_EnumDef_var p = new CORBA_EnumDef_impl(orb_, self);
    p -> name(name);
    p -> id(id);
    p -> version(version);
    p -> members(members);
    contents_.append(CORBA_EnumDef::_duplicate(p));
    return CORBA_EnumDef::_duplicate(p);
}

CORBA_AliasDef_ptr
CORBA_Container_impl::create_alias(const char* id,
				   const char* name,
				   const char* version,
				   CORBA_IDLType_ptr original_type)
{
    CORBA_Container_var self = _this();
    CORBA_AliasDef_var p = new CORBA_AliasDef_impl(orb_, self);
    p -> name(name);
    p -> id(id);
    p -> version(version);
    p -> original_type_def(original_type);
    contents_.append(CORBA_AliasDef::_duplicate(p));
    return CORBA_AliasDef::_duplicate(p);
}

CORBA_InterfaceDef_ptr
CORBA_Container_impl::
create_interface(const char* id,
		 const char* name,
		 const char* version,
		 const CORBA_InterfaceDefSeq& base_interfaces)
{
    CORBA_Container_var self = _this();
    CORBA_InterfaceDef_var p = new CORBA_InterfaceDef_impl(orb_, self);
    p -> name(name);
    p -> id(id);
    p -> version(version);
    p -> base_interfaces(base_interfaces);
    contents_.append(CORBA_InterfaceDef::_duplicate(p));
    return CORBA_InterfaceDef::_duplicate(p);
}

CORBA_ExceptionDef_ptr
CORBA_Container_impl::create_exception(const char* id,
				       const char* name,
				       const char* version,
				       const CORBA_StructMemberSeq& members)
{
    CORBA_Container_var self = _this();
    CORBA_ExceptionDef_var p = new CORBA_ExceptionDef_impl(orb_, self);
    p -> name(name);
    p -> id(id);
    p -> version(version);
    p -> members(members);
    contents_.append(CORBA_ExceptionDef::_duplicate(p));
    return CORBA_ExceptionDef::_duplicate(p);
}

// ----------------------------------------------------------------------

CORBA_Contained_ptr
CORBA_Repository_impl::lookup_id_in_seq(const CORBA_ContainedSeq& seq,
					const char* search_id)
{
    for(CORBA_ULong i = 0 ; i < seq.length() ; i++)
    {
	CORBA_RepositoryId_var id = seq[i] -> id();
	if(strcmp(id, search_id) == 0)
	    return CORBA_Contained::_duplicate(seq[i]);

	CORBA_Container_var container = CORBA_Container::_narrow(seq[i]);
	if(!CORBA_is_nil(container))
	{
	    CORBA_ContainedSeq_var seq =
		container -> contents(CORBA_dk_all, false);
	    CORBA_Contained_var contained =
		lookup_id_in_seq(seq, search_id);
	    if(!CORBA_is_nil(contained))
		return CORBA_Contained::_duplicate(contained);
	}
    }
    
    return CORBA_Contained::_nil();
}

CORBA_Repository_impl::CORBA_Repository_impl(CORBA_ORB_ptr orb)
    : CORBA_IRObject_impl(orb),
      CORBA_Container_impl(orb)
{
}

CORBA_Repository_impl::~CORBA_Repository_impl()
{
}

void
CORBA_Repository_impl::releaseInternal()
{
    CORBA_ULong i;

    for(i = 0 ; i < strings_.length() ; i++)
    {
	CORBA_StringDef_impl* p =
	    CORBA_StringDef_impl::_narrow_impl(strings_[i]);
	if(p)
	    p -> releaseInternal();
    }
    
    for(i = 0 ; i < sequences_.length() ; i++)
    {
	CORBA_SequenceDef_impl* p =
	    CORBA_SequenceDef_impl::_narrow_impl(sequences_[i]);
	if(p)
	    p -> releaseInternal();
    }
    
    for(i = 0 ; i < arrays_.length() ; i++)
    {
	CORBA_ArrayDef_impl* p =
	    CORBA_ArrayDef_impl::_narrow_impl(arrays_[i]);
	if(p)
	    p -> releaseInternal();
    }
    
    primDefNull = CORBA_PrimitiveDef::_nil();
    primDefVoid = CORBA_PrimitiveDef::_nil();
    primDefShort = CORBA_PrimitiveDef::_nil();
    primDefLong = CORBA_PrimitiveDef::_nil();
    primDefUShort = CORBA_PrimitiveDef::_nil();
    primDefULong = CORBA_PrimitiveDef::_nil();
    primDefFloat = CORBA_PrimitiveDef::_nil();
    primDefDouble = CORBA_PrimitiveDef::_nil();
    primDefBoolean = CORBA_PrimitiveDef::_nil();
    primDefChar = CORBA_PrimitiveDef::_nil();
    primDefOctet = CORBA_PrimitiveDef::_nil();
    primDefAny = CORBA_PrimitiveDef::_nil();
    primDefTypeCode = CORBA_PrimitiveDef::_nil();
    primDefPrincipal = CORBA_PrimitiveDef::_nil();
    primDefString = CORBA_PrimitiveDef::_nil();
    primDefObjref = CORBA_PrimitiveDef::_nil();

    strings_.length(0);
    sequences_.length(0);
    arrays_.length(0);

    CORBA_Container_impl::releaseInternal();
}

void
CORBA_Repository_impl::destroy()
{
    //
    // Invoking destroy on a CORBA_Repository is an error
    //
    throw CORBA_INTF_REPOS(OBMinorRepositoryDestroy, CORBA_COMPLETED_NO);
}

CORBA_Contained_ptr
CORBA_Repository_impl::lookup(const char* search_name)
{
    //
    // Make name relative (everything is relative to the repository)
    //
    while(strncmp(search_name, "::", 2) == 0)
	search_name += 2;

    return CORBA_Container_impl::lookup(search_name);
}

CORBA_Contained_ptr
CORBA_Repository_impl::lookup_id(const char* search_id)
{
    CORBA_ContainedSeq_var seq = contents(CORBA_dk_all, false);
    return lookup_id_in_seq(seq, search_id);
}

CORBA_PrimitiveDef_ptr
CORBA_Repository_impl::get_primitive(CORBA_PrimitiveKind kind)
{
    switch(kind)
    {
    case CORBA_pk_null:
	if(CORBA_is_nil(primDefNull))
	    primDefNull = new CORBA_PrimitiveDef_impl(orb_,
						      CORBA_pk_null);
	return CORBA_PrimitiveDef::_duplicate(primDefNull);
	
    case CORBA_pk_void:
	if(CORBA_is_nil(primDefVoid))
	    primDefVoid = new CORBA_PrimitiveDef_impl(orb_,
						      CORBA_pk_void);
	return CORBA_PrimitiveDef::_duplicate(primDefVoid);
	
    case CORBA_pk_short:
	if(CORBA_is_nil(primDefShort))
	    primDefShort = new CORBA_PrimitiveDef_impl(orb_,
						       CORBA_pk_short);
	return CORBA_PrimitiveDef::_duplicate(primDefShort);
	
    case CORBA_pk_long:
	if(CORBA_is_nil(primDefLong))
	    primDefLong = new CORBA_PrimitiveDef_impl(orb_,
						      CORBA_pk_long);
	return CORBA_PrimitiveDef::_duplicate(primDefLong);
	
    case CORBA_pk_ushort:
	if(CORBA_is_nil(primDefUShort))
	    primDefUShort = new CORBA_PrimitiveDef_impl(orb_,
							CORBA_pk_ushort);
	return CORBA_PrimitiveDef::_duplicate(primDefUShort);
	
    case CORBA_pk_ulong:
	if(CORBA_is_nil(primDefULong))
	    primDefULong = new CORBA_PrimitiveDef_impl(orb_,
						       CORBA_pk_ulong);
	return CORBA_PrimitiveDef::_duplicate(primDefULong);
	
    case CORBA_pk_float:
	if(CORBA_is_nil(primDefFloat))
	    primDefFloat = new CORBA_PrimitiveDef_impl(orb_,
						       CORBA_pk_float);
	return CORBA_PrimitiveDef::_duplicate(primDefFloat);
	
    case CORBA_pk_double:
	if(CORBA_is_nil(primDefDouble))
	    primDefDouble = new CORBA_PrimitiveDef_impl(orb_,
							CORBA_pk_double);
	return CORBA_PrimitiveDef::_duplicate(primDefDouble);
	
    case CORBA_pk_boolean:
	if(CORBA_is_nil(primDefBoolean))
	    primDefBoolean = new CORBA_PrimitiveDef_impl(orb_,
							 CORBA_pk_boolean);
	return CORBA_PrimitiveDef::_duplicate(primDefBoolean);
	
    case CORBA_pk_char:
	if(CORBA_is_nil(primDefChar))
	    primDefChar = new CORBA_PrimitiveDef_impl(orb_,
						      CORBA_pk_char);
	return CORBA_PrimitiveDef::_duplicate(primDefChar);
	
    case CORBA_pk_octet:
	if(CORBA_is_nil(primDefOctet))
	    primDefOctet = new CORBA_PrimitiveDef_impl(orb_,
						       CORBA_pk_octet);
	return CORBA_PrimitiveDef::_duplicate(primDefOctet);
	
    case CORBA_pk_any:
	if(CORBA_is_nil(primDefAny))
	    primDefAny = new CORBA_PrimitiveDef_impl(orb_,
						     CORBA_pk_any);
	return CORBA_PrimitiveDef::_duplicate(primDefAny);
	
    case CORBA_pk_TypeCode:
	if(CORBA_is_nil(primDefTypeCode))
	    primDefTypeCode = new CORBA_PrimitiveDef_impl(orb_,
							  CORBA_pk_TypeCode);
	return CORBA_PrimitiveDef::_duplicate(primDefTypeCode);
	
    case CORBA_pk_Principal:
	if(CORBA_is_nil(primDefPrincipal))
	    primDefPrincipal = new CORBA_PrimitiveDef_impl(orb_,
							   CORBA_pk_Principal);
	return CORBA_PrimitiveDef::_duplicate(primDefPrincipal);
	
    case CORBA_pk_string:
	if(CORBA_is_nil(primDefString))
	    primDefString = new CORBA_PrimitiveDef_impl(orb_,
							CORBA_pk_string);
	return CORBA_PrimitiveDef::_duplicate(primDefString);
	
    case CORBA_pk_objref:
	if(CORBA_is_nil(primDefObjref))
	    primDefObjref = new CORBA_PrimitiveDef_impl(orb_,
							CORBA_pk_objref);
	return CORBA_PrimitiveDef::_duplicate(primDefObjref);
    }

    return CORBA_PrimitiveDef::_nil();
}

CORBA_StringDef_ptr
CORBA_Repository_impl::create_string(CORBA_ULong bound)
{
    CORBA_TypeCode_var t1 = orb_ -> create_string_tc(bound);
    
    for(CORBA_ULong i = 0 ; i < strings_.length() ; i++)
    {
	CORBA_StringDef_ptr p2 = strings_[i];
	CORBA_TypeCode_var t2 = p2 -> type();

	if(t1 -> exactly_equal(t2))
	    return CORBA_StringDef::_duplicate(strings_[i]);
    }

    CORBA_Repository_var self = _this();
    CORBA_StringDef_var p = new CORBA_StringDef_impl(orb_, self);
    p -> bound(bound);
    strings_.append(p);
    return CORBA_StringDef::_duplicate(p);
}

CORBA_SequenceDef_ptr
CORBA_Repository_impl::create_sequence(CORBA_ULong bound,
				       CORBA_IDLType_ptr element_type)
{
    CORBA_TypeCode_var elem = element_type -> type();
    CORBA_TypeCode_var t1 = orb_ -> create_sequence_tc(bound, elem);
    
    for(CORBA_ULong i = 0 ; i < sequences_.length() ; i++)
    {
	CORBA_SequenceDef_ptr p2 = sequences_[i];
	CORBA_TypeCode_var t2 = p2 -> type();

	if(t1 -> exactly_equal(t2))
	    return CORBA_SequenceDef::_duplicate(sequences_[i]);
    }

    CORBA_Repository_var self = _this();
    CORBA_SequenceDef_var p = new CORBA_SequenceDef_impl(orb_, self);
    p -> bound(bound);
    p -> element_type_def(element_type);
    sequences_.append(p);
    return CORBA_SequenceDef::_duplicate(p);
}

CORBA_ArrayDef_ptr
CORBA_Repository_impl::create_array(CORBA_ULong length,
				    CORBA_IDLType_ptr element_type)
{
    CORBA_TypeCode_var elem = element_type -> type();
    CORBA_TypeCode_var t1 = orb_ -> create_array_tc(length, elem);
    
    for(CORBA_ULong i = 0 ; i < arrays_.length() ; i++)
    {
	CORBA_ArrayDef_ptr p2 = arrays_[i];
	CORBA_TypeCode_var t2 = p2 -> type();

	if(t1 -> exactly_equal(t2))
	    return CORBA_ArrayDef::_duplicate(arrays_[i]);
    }

    CORBA_Repository_var self = _this();
    CORBA_ArrayDef_var p = new CORBA_ArrayDef_impl(orb_, self);
    p -> length(length);
    p -> element_type_def(element_type);
    arrays_.append(p);
    return CORBA_ArrayDef::_duplicate(p);
}

// ----------------------------------------------------------------------

CORBA_ModuleDef_impl::CORBA_ModuleDef_impl(CORBA_ORB_ptr orb,
					   CORBA_Container_ptr p)
    : CORBA_IRObject_impl(orb),
      CORBA_Container_impl(orb),
      CORBA_Contained_impl(orb, p)
{
}

CORBA_ModuleDef_impl::~CORBA_ModuleDef_impl()
{
}

void
CORBA_ModuleDef_impl::releaseInternal()
{
    CORBA_Container_impl::releaseInternal();
    CORBA_Contained_impl::releaseInternal();
}

CORBA_Contained::Description*
CORBA_ModuleDef_impl::describe()
{
    CORBA_ModuleDescription* desc = new CORBA_ModuleDescription;

    desc -> name = name();
    desc -> id = id();

    CORBA_Contained_var contained = CORBA_Contained::_narrow(definedIn_);
    if(!CORBA_is_nil(contained))
	desc -> defined_in = contained -> id();
    else
	desc -> defined_in = CORBA_string_dup("");

    desc -> version = version();

    CORBA_Contained::Description* description =
	new CORBA_Contained::Description;
    description -> kind = def_kind();
    description -> value <<= desc;

    return description;
}

// ----------------------------------------------------------------------

CORBA_ConstantDef_impl::CORBA_ConstantDef_impl(CORBA_ORB_ptr orb,
					       CORBA_Container_ptr p)
    : CORBA_IRObject_impl(orb),
      CORBA_Contained_impl(orb, p)
{
}

CORBA_ConstantDef_impl::~CORBA_ConstantDef_impl()
{
}

void
CORBA_ConstantDef_impl::releaseInternal()
{
    idlType_ = CORBA_IDLType::_nil();
    CORBA_Contained_impl::releaseInternal();
}

CORBA_Contained::Description*
CORBA_ConstantDef_impl::describe()
{
    CORBA_ConstantDescription* desc = new CORBA_ConstantDescription;

    desc -> name = name();
    desc -> id = id();

    CORBA_Contained_var contained = CORBA_Contained::_narrow(definedIn_);
    if(!CORBA_is_nil(contained))
	desc -> defined_in = contained -> id();
    else
	desc -> defined_in = CORBA_string_dup("");

    desc -> version = version();
    desc -> type = type();
    desc -> value = value_;

    CORBA_Contained::Description* description =
	new CORBA_Contained::Description;
    description -> kind = def_kind();
    description -> value <<= desc;

    return description;
}

CORBA_TypeCode_ptr
CORBA_ConstantDef_impl::type()
{
    return idlType_ -> type();
}

CORBA_IDLType_ptr
CORBA_ConstantDef_impl::type_def()
{
    return CORBA_IDLType::_duplicate(idlType_);
}

void
CORBA_ConstantDef_impl::type_def(CORBA_IDLType_ptr t)
{
    idlType_ = CORBA_IDLType::_duplicate(t);
}

CORBA_Any*
CORBA_ConstantDef_impl::value()
{
    return new CORBA_Any(value_);
}

void
CORBA_ConstantDef_impl::value(const CORBA_Any& v)
{
    value_ = v;
}

// ----------------------------------------------------------------------

CORBA_TypedefDef_impl::CORBA_TypedefDef_impl(CORBA_ORB_ptr orb,
					     CORBA_Container_ptr p)
    : CORBA_IRObject_impl(orb),
      CORBA_Contained_impl(orb, p),
      CORBA_IDLType_impl(orb)
{
}

CORBA_TypedefDef_impl::~CORBA_TypedefDef_impl()
{
}

CORBA_Contained::Description*
CORBA_TypedefDef_impl::describe()
{
    CORBA_TypeDescription* desc = new CORBA_TypeDescription;

    desc -> name = name();
    desc -> id = id();

    CORBA_Contained_var contained = CORBA_Contained::_narrow(definedIn_);
    if(!CORBA_is_nil(contained))
	desc -> defined_in = contained -> id();
    else
	desc -> defined_in = CORBA_string_dup("");

    desc -> version = version();
    desc -> type = type();

    CORBA_Contained::Description* description =
	new CORBA_Contained::Description;
    description -> kind = def_kind();
    description -> value <<= desc;

    return description;
}

// ----------------------------------------------------------------------

CORBA_StructDef_impl::CORBA_StructDef_impl(CORBA_ORB_ptr orb,
					   CORBA_Container_ptr p)
    : CORBA_IRObject_impl(orb),
      CORBA_Contained_impl(orb, p),
      CORBA_IDLType_impl(orb),
      CORBA_TypedefDef_impl(orb, p)
{
}

CORBA_StructDef_impl::~CORBA_StructDef_impl()
{
}

void
CORBA_StructDef_impl::releaseInternal()
{
    members_.length(0);
    CORBA_TypedefDef_impl::releaseInternal();
}

CORBA_TypeCode_ptr
CORBA_StructDef_impl::type()
{
    //
    // Recalculate member TypeCodes (ids may have changed)
    //
    for(CORBA_ULong i = 0 ; i < members_.length() ; i++)
    {
	//
	// Don't follow recursive sequences
	//
	CORBA_TypeCode_var type = members_[i].type;
	if(!(type -> kind() == CORBA_tk_sequence && type -> offset() != 0))
	    members_[i].type = members_[i].type_def -> type();
    }

    return orb_ -> create_struct_tc(id_, name_, members_);
}

CORBA_StructMemberSeq*
CORBA_StructDef_impl::members()
{
    //
    // Recalculate member TypeCodes (ids may have changed)
    //
    for(CORBA_ULong i = 0 ; i < members_.length() ; i++)
    {
	//
	// Don't follow recursive sequences
	//
	CORBA_TypeCode_var type = members_[i].type;
	if(!(type -> kind() == CORBA_tk_sequence && type -> offset() != 0))
	    members_[i].type = members_[i].type_def -> type();
    }

    return new CORBA_StructMemberSeq(members_);
}

void
CORBA_StructDef_impl::members(const CORBA_StructMemberSeq& m)
{
    CORBA_StructMemberSeq members = m;

    //
    // Check for recursion
    //
    for(CORBA_ULong i = 0 ; i < members.length() ; i++)
    {
	CORBA_TypeCode_var type = members[i].type;
	
	//
	// Check for legal sequence recursion
	//
	if(type -> kind() == CORBA_tk_sequence)
	{
	    CORBA_TypeCode_var contentType = type -> content_type();
	    
	    if(contentType -> kind() == CORBA_tk_struct)
	    {
		if(strcmp(id_, contentType -> id()) == 0)
		{
		    //
		    // Legal recursion, set new type
		    //
		    members[i].type = orb_ -> create_recursive_sequence_tc(
			members[i].type -> length(), 1);
		    continue;
		}
	    }
	}
	
	//
	// Check for illegal recursion
	//
	if(IdlCheckForRecursion(id_, type))
	{
	    throw CORBA_INTF_REPOS(OBMinorIllegalRecursion,
				   CORBA_COMPLETED_NO);
	}
    }

    members_ = members;
}

// ----------------------------------------------------------------------

CORBA_UnionDef_impl::CORBA_UnionDef_impl(CORBA_ORB_ptr orb,
					 CORBA_Container_ptr p)
    : CORBA_IRObject_impl(orb),
      CORBA_Contained_impl(orb, p),
      CORBA_IDLType_impl(orb),
      CORBA_TypedefDef_impl(orb, p)
{
}

CORBA_UnionDef_impl::~CORBA_UnionDef_impl()
{
}

void
CORBA_UnionDef_impl::releaseInternal()
{
    discType_ = CORBA_IDLType::_nil();
    members_.length(0);
    CORBA_TypedefDef_impl::releaseInternal();
}

CORBA_TypeCode_ptr
CORBA_UnionDef_impl::type()
{
    //
    // Recalculate member TypeCodes (ids may have changed)
    //
    for(CORBA_ULong i = 0 ; i < members_.length() ; i++)
    {
	//
	// Don't follow recursive sequences
	//
	CORBA_TypeCode_var type = members_[i].type;
	if(!(type -> kind() == CORBA_tk_sequence && type -> offset() != 0))
	    members_[i].type = members_[i].type_def -> type();
    }

    CORBA_TypeCode_var disc = discType_ -> type();
    return orb_ -> create_union_tc(id_, name_, disc, members_);
}

CORBA_TypeCode_ptr
CORBA_UnionDef_impl::discriminator_type()
{
    return discType_ -> type();
}

CORBA_IDLType_ptr
CORBA_UnionDef_impl::discriminator_type_def()
{
    return CORBA_IDLType::_duplicate(discType_);
}

void
CORBA_UnionDef_impl::discriminator_type_def(CORBA_IDLType_ptr d)
{
    discType_ = CORBA_IDLType::_duplicate(d);
}

CORBA_UnionMemberSeq*
CORBA_UnionDef_impl::members()
{
    //
    // Recalculate member TypeCodes (ids may have changed)
    //
    for(CORBA_ULong i = 0 ; i < members_.length() ; i++)
    {
	//
	// Don't follow recursive sequences
	//
	CORBA_TypeCode_var type = members_[i].type;
	if(!(type -> kind() == CORBA_tk_sequence && type -> offset() != 0))
	    members_[i].type = members_[i].type_def -> type();
    }

    return new CORBA_UnionMemberSeq(members_);
}

void
CORBA_UnionDef_impl::members(const CORBA_UnionMemberSeq& m)
{
    CORBA_UnionMemberSeq members = m;

    //
    // Check for recursion
    //
    for(CORBA_ULong i = 0 ; i < members.length() ; i++)
    {
	CORBA_TypeCode_var type = members[i].type;
	
	//
	// Check for legal sequence recursion
	//
	if(type -> kind() == CORBA_tk_sequence)
	{
	    CORBA_TypeCode_var contentType = type -> content_type();
	    
	    if(contentType -> kind() == CORBA_tk_union)
	    {
		if(strcmp(id_, contentType -> id()) == 0)
		{
		    //
		    // Legal recursion, set new type
		    //
		    members[i].type = orb_ -> create_recursive_sequence_tc(
			members[i].type -> length(), 1);
		    continue;
		}
	    }
	}
	
	//
	// Check for illegal recursion
	//
	if(IdlCheckForRecursion(id_, type))
	{
	    throw CORBA_INTF_REPOS(OBMinorIllegalRecursion,
				   CORBA_COMPLETED_NO);
	}
    }

    members_ = members;
}

// ----------------------------------------------------------------------

CORBA_EnumDef_impl::CORBA_EnumDef_impl(CORBA_ORB_ptr orb,
				       CORBA_Container_ptr p)
    : CORBA_IRObject_impl(orb),
      CORBA_Contained_impl(orb, p),
      CORBA_IDLType_impl(orb),
      CORBA_TypedefDef_impl(orb, p)
{
}

CORBA_EnumDef_impl::~CORBA_EnumDef_impl()
{
}

CORBA_TypeCode_ptr
CORBA_EnumDef_impl::type()
{
    return orb_ -> create_enum_tc(id_, name_, members_);
}

CORBA_EnumMemberSeq*
CORBA_EnumDef_impl::members()
{
    return new CORBA_EnumMemberSeq(members_);
}

void
CORBA_EnumDef_impl::members(const CORBA_EnumMemberSeq& m)
{
    members_ = m;
}

// ----------------------------------------------------------------------

CORBA_AliasDef_impl::CORBA_AliasDef_impl(CORBA_ORB_ptr orb,
					 CORBA_Container_ptr p)
    : CORBA_IRObject_impl(orb),
      CORBA_Contained_impl(orb, p),
      CORBA_IDLType_impl(orb),
      CORBA_TypedefDef_impl(orb, p)
{
}

CORBA_AliasDef_impl::~CORBA_AliasDef_impl()
{
}

void
CORBA_AliasDef_impl::releaseInternal()
{
    idlType_ = CORBA_IDLType::_nil();
    CORBA_TypedefDef_impl::releaseInternal();
}

CORBA_TypeCode_ptr
CORBA_AliasDef_impl::type()
{
    CORBA_TypeCode_var t = idlType_ -> type();
    return orb_ -> create_alias_tc(id_, name_, t);
}

CORBA_IDLType_ptr
CORBA_AliasDef_impl::original_type_def()
{
    return CORBA_IDLType::_duplicate(idlType_);
}

void
CORBA_AliasDef_impl::original_type_def(CORBA_IDLType_ptr t)
{
    idlType_ = CORBA_IDLType::_duplicate(t);
}

// ----------------------------------------------------------------------

CORBA_PrimitiveDef_impl::CORBA_PrimitiveDef_impl(CORBA_ORB_ptr orb,
						 CORBA_PrimitiveKind pk)
    : CORBA_IRObject_impl(orb),
      CORBA_IDLType_impl(orb),
      primitiveKind(pk)
{
}

CORBA_PrimitiveDef_impl::~CORBA_PrimitiveDef_impl()
{
}

void
CORBA_PrimitiveDef_impl::destroy()
{
    //
    // Invoking destroy on a CORBA_PrimitiveDef is an error
    //
    throw CORBA_INTF_REPOS(OBMinorPrimitiveDefDestroy, CORBA_COMPLETED_NO);
}

CORBA_TypeCode_ptr
CORBA_PrimitiveDef_impl::type()
{
    CORBA_TypeCode_ptr p = CORBA_TypeCode::_nil();

    switch(primitiveKind)
    {
    case CORBA_pk_null:
	p = CORBA__tc_null;
	break;

    case CORBA_pk_void:
	p = CORBA__tc_void;
	break;

    case CORBA_pk_short:
	p = CORBA__tc_short;
	break;

    case CORBA_pk_long:
	p = CORBA__tc_long;
	break;

    case CORBA_pk_ushort:
	p = CORBA__tc_ushort;
	break;

    case CORBA_pk_ulong:
	p = CORBA__tc_ulong;
	break;

    case CORBA_pk_float:
	p = CORBA__tc_float;
	break;

    case CORBA_pk_double:
	p = CORBA__tc_double;
	break;

    case CORBA_pk_boolean:
	p = CORBA__tc_boolean;
	break;

    case CORBA_pk_char:
	p = CORBA__tc_char;
	break;

    case CORBA_pk_octet:
	p = CORBA__tc_octet;
	break;

    case CORBA_pk_any:
	p = CORBA__tc_any;
	break;

    case CORBA_pk_TypeCode:
	p = CORBA__tc_TypeCode;
	break;

    case CORBA_pk_Principal:
	p = CORBA__tc_Principal;
	break;

    case CORBA_pk_string:
	p = CORBA__tc_string;
	break;

    case CORBA_pk_objref:
	p = CORBA__tc_Object;
	break;
    }
    
    return CORBA_TypeCode::_duplicate(p);
}

CORBA_PrimitiveKind
CORBA_PrimitiveDef_impl::kind()
{
    return primitiveKind;
}

// ----------------------------------------------------------------------

CORBA_StringDef_impl::CORBA_StringDef_impl(CORBA_ORB_ptr orb,
					   CORBA_Repository_ptr p)
    : CORBA_IRObject_impl(orb),
      CORBA_IDLType_impl(orb),
      repository_(CORBA_Repository::_duplicate(p))
{
}

CORBA_StringDef_impl::~CORBA_StringDef_impl()
{
}

void
CORBA_StringDef_impl::releaseInternal()
{
    repository_ = CORBA_Repository::_nil();
    CORBA_IDLType_impl::releaseInternal();
}

CORBA_TypeCode_ptr
CORBA_StringDef_impl::type()
{
    return orb_ -> create_string_tc(bound_);
}

CORBA_ULong
CORBA_StringDef_impl::bound()
{
    return bound_;
}

void
CORBA_StringDef_impl::bound(CORBA_ULong b)
{
    bound_ = b;
}

// ----------------------------------------------------------------------

CORBA_SequenceDef_impl::CORBA_SequenceDef_impl(CORBA_ORB_ptr orb,
					       CORBA_Repository_ptr p)
    : CORBA_IRObject_impl(orb),
      CORBA_IDLType_impl(orb),
      repository_(CORBA_Repository::_duplicate(p))
{
}

CORBA_SequenceDef_impl::~CORBA_SequenceDef_impl()
{
}

void
CORBA_SequenceDef_impl::releaseInternal()
{
    repository_ = CORBA_Repository::_nil();
    elementType_ = CORBA_IDLType::_nil();
    CORBA_IDLType_impl::releaseInternal();
}

CORBA_TypeCode_ptr
CORBA_SequenceDef_impl::type()
{
    CORBA_TypeCode_var t = elementType_ -> type();
    return orb_ -> create_sequence_tc(bound_, t);
}

CORBA_ULong
CORBA_SequenceDef_impl::bound()
{
    return bound_;
}

void
CORBA_SequenceDef_impl::bound(CORBA_ULong b)
{
    bound_ = b;
}

CORBA_TypeCode_ptr
CORBA_SequenceDef_impl::element_type()
{
    return elementType_ -> type();
}

CORBA_IDLType_ptr
CORBA_SequenceDef_impl::element_type_def()
{
    return CORBA_IDLType::_duplicate(elementType_);
}

void
CORBA_SequenceDef_impl::element_type_def(CORBA_IDLType_ptr p)
{
    elementType_ = CORBA_IDLType::_duplicate(p);
}

// ----------------------------------------------------------------------

CORBA_ArrayDef_impl::CORBA_ArrayDef_impl(CORBA_ORB_ptr orb,
					 CORBA_Repository_ptr p)
    : CORBA_IRObject_impl(orb),
      CORBA_IDLType_impl(orb),
      repository_(CORBA_Repository::_duplicate(p))
{
}

CORBA_ArrayDef_impl::~CORBA_ArrayDef_impl()
{
}

void
CORBA_ArrayDef_impl::releaseInternal()
{
    repository_ = CORBA_Repository::_nil();
    elementType_ = CORBA_IDLType::_nil();
    CORBA_IDLType_impl::releaseInternal();
}

CORBA_TypeCode_ptr
CORBA_ArrayDef_impl::type()
{
    CORBA_TypeCode_var t = elementType_ -> type();
    return orb_ -> create_array_tc(length_, t);
}

CORBA_ULong
CORBA_ArrayDef_impl::length()
{
    return length_;
}

void
CORBA_ArrayDef_impl::length(CORBA_ULong b)
{
    length_ = b;
}

CORBA_TypeCode_ptr
CORBA_ArrayDef_impl::element_type()
{
    return elementType_ -> type();
}

CORBA_IDLType_ptr
CORBA_ArrayDef_impl::element_type_def()
{
    return CORBA_IDLType::_duplicate(elementType_);
}

void
CORBA_ArrayDef_impl::element_type_def(CORBA_IDLType_ptr p)
{
    elementType_ = CORBA_IDLType::_duplicate(p);
}

// ----------------------------------------------------------------------

CORBA_ExceptionDef_impl::CORBA_ExceptionDef_impl(CORBA_ORB_ptr orb,
						 CORBA_Container_ptr p)
    : CORBA_IRObject_impl(orb),
      CORBA_Contained_impl(orb, p)
{

}

CORBA_ExceptionDef_impl::~CORBA_ExceptionDef_impl()
{
}

void
CORBA_ExceptionDef_impl::releaseInternal()
{
    members_.length(0);
    CORBA_Contained_impl::releaseInternal();
}

CORBA_Contained::Description*
CORBA_ExceptionDef_impl::describe()
{
    CORBA_ExceptionDescription* desc = new CORBA_ExceptionDescription;

    desc -> name = name();
    desc -> id = id();

    CORBA_Contained_var contained = CORBA_Contained::_narrow(definedIn_);
    if(!CORBA_is_nil(contained))
	desc -> defined_in = contained -> id();
    else
	desc -> defined_in = CORBA_string_dup("");

    desc -> version = version();
    desc -> type = type();

    CORBA_Contained::Description* description =
	new CORBA_Contained::Description;
    description -> kind = def_kind();
    description -> value <<= desc;

    return description;
}

CORBA_TypeCode_ptr
CORBA_ExceptionDef_impl::type()
{
    //
    // Recalculate member TypeCodes (ids may have changed)
    //
    for(CORBA_ULong i = 0 ; i < members_.length() ; i++)
    {
	//
	// Don't follow recursive sequences
	//
	CORBA_TypeCode_var type = members_[i].type;
	if(!(type -> kind() == CORBA_tk_sequence && type -> offset() != 0))
	    members_[i].type = members_[i].type_def -> type();
    }

    return orb_ -> create_exception_tc(id_, name_, members_);
}

CORBA_StructMemberSeq*
CORBA_ExceptionDef_impl::members()
{
    //
    // Recalculate member TypeCodes (ids may have changed)
    //
    for(CORBA_ULong i = 0 ; i < members_.length() ; i++)
    {
	//
	// Don't follow recursive sequences
	//
	CORBA_TypeCode_var type = members_[i].type;
	if(!(type -> kind() == CORBA_tk_sequence && type -> offset() != 0))
	    members_[i].type = members_[i].type_def -> type();
    }

    return new CORBA_StructMemberSeq(members_);
}

void
CORBA_ExceptionDef_impl::members(const CORBA_StructMemberSeq& m)
{
    CORBA_StructMemberSeq members = m;

    //
    // Check for recursion
    //
    for(CORBA_ULong i = 0 ; i < members.length() ; i++)
    {
	CORBA_TypeCode_var type = members[i].type;
	
	//
	// Check for legal sequence recursion
	//
	if(type -> kind() == CORBA_tk_sequence)
	{
	    CORBA_TypeCode_var contentType = type -> content_type();
	    
	    if(contentType -> kind() == CORBA_tk_except)
	    {
		if(strcmp(id_, contentType -> id()) == 0)
		{
		    //
		    // Legal recursion, set new type
		    //
		    members[i].type = orb_ -> create_recursive_sequence_tc(
			members[i].type -> length(), 1);
		    continue;
		}
	    }
	}
	
	//
	// Check for illegal recursion
	//
	if(IdlCheckForRecursion(id_, type))
	{
	    throw CORBA_INTF_REPOS(OBMinorIllegalRecursion,
				   CORBA_COMPLETED_NO);
	}
    }

    members_ = members;
}

// ----------------------------------------------------------------------

CORBA_AttributeDef_impl::CORBA_AttributeDef_impl(CORBA_ORB_ptr orb,
						 CORBA_Container_ptr p)
    : CORBA_IRObject_impl(orb),
      CORBA_Contained_impl(orb, p)
{
}

CORBA_AttributeDef_impl::~CORBA_AttributeDef_impl()
{
}

void
CORBA_AttributeDef_impl::releaseInternal()
{
    idlType_ = CORBA_IDLType::_nil();
    CORBA_Contained_impl::releaseInternal();
}

void
CORBA_AttributeDef_impl::name(const char* s)
{
    if(name_.in() && strcmp(name_, s) == 0)
	return;

    //
    // Find out whether attribute already exists in a base
    // interface. Using case-insensitive comparison.
    //
    CORBA_ULong i, j;

    // Do NOT exclude inherited names
    CORBA_ContainedSeq_var seq = definedIn_ -> contents(CORBA_dk_Attribute,
							false);

    CORBA_String_var s1 = s;
    for(j = 0 ; j < strlen(s1) ; j++)
	if(isupper(s1[j]))
	    s1[j] = tolower(s1[j]);

    for(i = 0 ; i < seq -> length() ; i++)
    {
	CORBA_String_var s2 = seq[i] -> name();
	for(j = 0 ; j < strlen(s2) ; j++)
	    if(isupper(s2[j]))
		s2[j] = tolower(s2[j]);

	if(strcmp(s1, s2) == 0)
	{
	    //
	    // Attribute does already exist
	    //
	    throw CORBA_INTF_REPOS(OBMinorAttrExists, CORBA_COMPLETED_NO);
	}
    }
    
    CORBA_Contained_impl::name(s);
}

CORBA_Contained::Description*
CORBA_AttributeDef_impl::describe()
{
    CORBA_AttributeDescription* desc = new CORBA_AttributeDescription;

    desc -> name = name();
    desc -> id = id();

    CORBA_Contained_var contained = CORBA_Contained::_narrow(definedIn_);
    if(!CORBA_is_nil(contained))
	desc -> defined_in = contained -> id();
    else
	desc -> defined_in = CORBA_string_dup("");

    desc -> version = version();
    desc -> type = type();
    desc -> mode = mode();

    CORBA_Contained::Description* description =
	new CORBA_Contained::Description;
    description -> kind = def_kind();
    description -> value <<= desc;

    return description;
}

CORBA_TypeCode_ptr
CORBA_AttributeDef_impl::type()
{
    return idlType_ -> type();
}

CORBA_IDLType_ptr
CORBA_AttributeDef_impl::type_def()
{
    return CORBA_IDLType::_duplicate(idlType_);
}

void
CORBA_AttributeDef_impl::type_def(CORBA_IDLType_ptr type)
{
    idlType_ = CORBA_IDLType::_duplicate(type);
}

CORBA_AttributeMode
CORBA_AttributeDef_impl::mode()
{
    return attributeMode_;
}

void
CORBA_AttributeDef_impl::mode(CORBA_AttributeMode mode)
{
    attributeMode_ = mode;
}

// ----------------------------------------------------------------------

CORBA_OperationDef_impl::CORBA_OperationDef_impl(CORBA_ORB_ptr orb,
						 CORBA_Container_ptr p)
    : CORBA_IRObject_impl(orb),
      CORBA_Contained_impl(orb, p)
{
}

CORBA_OperationDef_impl::~CORBA_OperationDef_impl()
{
}

void
CORBA_OperationDef_impl::releaseInternal()
{
    params_.length(0);
    result_ = CORBA_IDLType::_nil();
    CORBA_Contained_impl::releaseInternal();
}

void
CORBA_OperationDef_impl::name(const char* s)
{
    if(name_.in() && strcmp(name_, s) == 0)
	return;

    //
    // Find out whether operation already exists in a base
    // interface. Using case-insensitive comparison.
    //
    CORBA_ULong i, j;

    // Do NOT exclude inherited names
    CORBA_ContainedSeq_var seq = definedIn_ -> contents(CORBA_dk_Operation,
							false);

    CORBA_String_var s1 = s;
    for(j = 0 ; j < strlen(s1) ; j++)
	if(isupper(s1[j]))
	    s1[j] = tolower(s1[j]);

    for(i = 0 ; i < seq -> length() ; i++)
    {
	CORBA_String_var s2 = seq[i] -> name();
	for(j = 0 ; j < strlen(s2) ; j++)
	    if(isupper(s2[j]))
		s2[j] = tolower(s2[j]);

	if(strcmp(s1, s2) == 0)
	{
	    //
	    // Operation does already exist
	    //
	    throw CORBA_INTF_REPOS(OBMinorOperExists, CORBA_COMPLETED_NO);
	}
    }
   
    CORBA_Contained_impl::name(s);
}

CORBA_Contained::Description*
CORBA_OperationDef_impl::describe()
{
    CORBA_ULong i;
    CORBA_OperationDescription* desc = new CORBA_OperationDescription;

    desc -> name = name();
    desc -> id = id();

    CORBA_Contained_var contained = CORBA_Contained::_narrow(definedIn_);
    if(!CORBA_is_nil(contained))
	desc -> defined_in = contained -> id();
    else
	desc -> defined_in = CORBA_string_dup("");

    desc -> version = version();
    desc -> result = result();
    desc -> mode = mode();
    desc -> contexts = contexts_;

    //
    // Recalculate parameter TypeCodes (ids may have changed)
    //
    for(i = 0 ; i < params_.length() ; i++)
	params_[i].type = params_[i].type_def -> type();

    desc -> parameters = params_;

    for(i = 0 ; i < exceptions_.length() ; i++)
    {
	CORBA_Contained::Description_var d = exceptions_[i] -> describe();
	CORBA_ExceptionDescription* excDesc;
	CORBA_Boolean b = d -> value >>= excDesc;
	assert(b);

	desc -> exceptions.append(*excDesc);
    }

    CORBA_Contained::Description* description =
	new CORBA_Contained::Description;
    description -> kind = def_kind();
    description -> value <<= desc;

    return description;
}

CORBA_TypeCode_ptr
CORBA_OperationDef_impl::result()
{
    return result_ -> type();
}

CORBA_IDLType_ptr
CORBA_OperationDef_impl::result_def()
{
    return CORBA_IDLType::_duplicate(result_);
}

void
CORBA_OperationDef_impl::result_def(CORBA_IDLType_ptr res)
{
    result_ = CORBA_IDLType::_duplicate(res);
}

CORBA_ParDescriptionSeq*
CORBA_OperationDef_impl::params()
{
    //
    // Recalculate parameter TypeCodes (ids may have changed)
    //
    for(CORBA_ULong i = 0 ; i < params_.length() ; i++)
	params_[i].type = params_[i].type_def -> type();

    return new CORBA_ParDescriptionSeq(params_);
}

void
CORBA_OperationDef_impl::params(const CORBA_ParDescriptionSeq& p)
{
    //
    // Ensure we don't have duplicate parameter names
    //
    for(CORBA_ULong i = 0 ; i < p.length() ; i++)
    {
	CORBA_String_var s1 = p[i].name;
	for(CORBA_ULong k = 0 ; k < strlen(s1) ; k++)
	    if(isupper(s1[k]))
		s1[k] = tolower(s1[k]);

	for(CORBA_ULong j = i + 1 ; j < p.length() ; j++)
	{
	    CORBA_String_var s2 = p[j].name;
	    for(CORBA_ULong k = 0 ; k < strlen(s2) ; k++)
		if(isupper(s2[k]))
		    s2[k] = tolower(s2[k]);
	    
	    if(strcmp(s1, s2) == 0)
		throw CORBA_INTF_REPOS(OBMinorDupParameter,
				       CORBA_COMPLETED_NO);
	}
    }

    params_ = p;
}

CORBA_OperationMode
CORBA_OperationDef_impl::mode()
{
    return mode_;
}

void
CORBA_OperationDef_impl::mode(CORBA_OperationMode m)
{
    mode_ = m;
}

CORBA_ContextIdSeq*
CORBA_OperationDef_impl::contexts()
{
    return new CORBA_ContextIdSeq(contexts_);
}

void
CORBA_OperationDef_impl::contexts(const CORBA_ContextIdSeq& c)
{
    contexts_ = c;
}

CORBA_ExceptionDefSeq*
CORBA_OperationDef_impl::exceptions()
{
    return new CORBA_ExceptionDefSeq(exceptions_);
}

void
CORBA_OperationDef_impl::exceptions(const CORBA_ExceptionDefSeq& e)
{
    exceptions_ = e;
}

// ----------------------------------------------------------------------

CORBA_InterfaceDef_impl::CORBA_InterfaceDef_impl(CORBA_ORB_ptr orb,
						 CORBA_Container_ptr p)
    : CORBA_IRObject_impl(orb),
      CORBA_Container_impl(orb),
      CORBA_Contained_impl(orb, p),
      CORBA_IDLType_impl(orb)
{
}

CORBA_InterfaceDef_impl::~CORBA_InterfaceDef_impl()
{
}

void
CORBA_InterfaceDef_impl::releaseInternal()
{
    baseInterfaces_.length(0);
    CORBA_Container_impl::releaseInternal();
    CORBA_Contained_impl::releaseInternal();
    CORBA_IDLType_impl::releaseInternal();
}

CORBA_TypeCode_ptr
CORBA_InterfaceDef_impl::type()
{
    return orb_ -> create_interface_tc(id_, name_);
}

CORBA_Contained::Description*
CORBA_InterfaceDef_impl::describe()
{
    CORBA_InterfaceDescription* desc = new CORBA_InterfaceDescription;

    desc -> name = name();
    desc -> id = id();

    CORBA_Contained_var contained = CORBA_Contained::_narrow(definedIn_);
    if(!CORBA_is_nil(contained))
	desc -> defined_in = contained -> id();
    else
	desc -> defined_in = CORBA_string_dup("");

    desc -> version = version();

    for(CORBA_ULong i = 0 ; i < baseInterfaces_.length() ; i++)
    {
	CORBA_Contained_var baseContained =
	    CORBA_Contained::_narrow(baseInterfaces_[i]);
	if(!CORBA_is_nil(baseContained))
	    desc -> base_interfaces.append(baseContained -> id());
    }

    CORBA_Contained::Description* description =
	new CORBA_Contained::Description;
    description -> kind = def_kind();
    description -> value <<= desc;

    return description;
}

CORBA_Contained_ptr
CORBA_InterfaceDef_impl::lookup(const char* search_name)
{
    CORBA_Contained_var contained = CORBA_Container_impl::lookup(search_name);

    if(CORBA_is_nil(contained))
    {
	for(CORBA_ULong i = 0 ; i < baseInterfaces_.length() ; i++)
	{
	    CORBA_Contained_var contained2 =
		baseInterfaces_[i] -> lookup(search_name);
	    
	    if(!CORBA_is_nil(contained2))
	    {
		if(!CORBA_is_nil(contained))
		{
		    if(!contained -> _is_equivalent(contained2))
		    {
			//
			// Name is ambiguous
			//
			throw CORBA_INTF_REPOS(OBMinorLookupAmbiguous,
					       CORBA_COMPLETED_NO);
		    }
		}

		contained = contained2;
	    }
	}
    }

    return contained._retn();
}

CORBA_ContainedSeq*
CORBA_InterfaceDef_impl::contents(CORBA_DefinitionKind limit_type,
				  CORBA_Boolean exclude_inherited)
{
    CORBA_ULong i, j, k;

    CORBA_ContainedSeq* s =
	CORBA_Container_impl::contents(limit_type, exclude_inherited);
    
    if(!exclude_inherited)
    {
	for(i = 0 ; i < baseInterfaces_.length() ; i++)
	{
	    CORBA_ContainedSeq_var s2 =
		baseInterfaces_[i] -> contents(limit_type, exclude_inherited);
	    
	    for(j = 0 ; j < s2 -> length() ; j++)
	    {
		CORBA_RepositoryId_var id2 = s2[j] -> id(); 

		for(k = 0 ; k < s -> length() ; k++)
		{
		    CORBA_RepositoryId_var id = (*s)[k] -> id(); 

		    if(strcmp(id, id2) == 0)
			break;
		}

		if(k == s -> length())
		    s -> append(s2[j]);
	    }
	}
    }
    
    return s;
}

CORBA_ContainedSeq*
CORBA_InterfaceDef_impl::lookup_name(const char* search_name,
				     CORBA_Long levels_to_search,
				     CORBA_DefinitionKind limit_type,
				     CORBA_Boolean exclude_inherited)
{
    CORBA_ULong i, j, k;

    CORBA_ContainedSeq* s =
	CORBA_Container_impl::lookup_name(search_name,
					  levels_to_search,
					  limit_type,
					  exclude_inherited);

    if(!exclude_inherited)
    {
	for(i = 0 ; i < baseInterfaces_.length() ; i++)
	{
	    CORBA_ContainedSeq_var s2 =
		baseInterfaces_[i] -> lookup_name(search_name,
						  levels_to_search,
						  limit_type,
						  exclude_inherited);
	    
	    for(j = 0 ; j < s2 -> length() ; j++)
	    {
		CORBA_RepositoryId_var id2 = s2[j] -> id(); 

		for(k = 0 ; k < s -> length() ; k++)
		{
		    CORBA_RepositoryId_var id = (*s)[k] -> id(); 

		    if(strcmp(id, id2) == 0)
			break;
		}

		if(k == s -> length())
		    s -> append(s2[j]);
	    }
	}
    }
		
    return s;
}

CORBA_InterfaceDefSeq*
CORBA_InterfaceDef_impl::base_interfaces()
{
    return new CORBA_InterfaceDefSeq(baseInterfaces_);
}

void
CORBA_InterfaceDef_impl::base_interfaces(const CORBA_InterfaceDefSeq& bi)
{
    CORBA_ContainedSeq conSeq;

    CORBA_ULong i;

    for(i = 0 ; i < bi.length() ; i++)
    {
	CORBA_ContainedSeq_var seq =
	    bi[i] -> contents(CORBA_dk_Operation, false);

	for(CORBA_ULong j = 0 ; j < seq -> length() ; j++)
	{
	    CORBA_String_var name1 = seq[j] -> name();
	    CORBA_String_var id1 = seq[j] -> id();

	    for(CORBA_ULong k = 0 ; k < conSeq.length() ; k++)
	    {
		CORBA_String_var name2 = conSeq[k] -> name();
		CORBA_String_var id2 = conSeq[k] -> id();

		if(strcmp(id1, id2) != 0 && strcmp(name1, name2) == 0)
		{
		    //
		    // Operation defined in multiple base interfaces
		    //
		    throw CORBA_INTF_REPOS(OBMinorOperAmbiguous,
					   CORBA_COMPLETED_NO);
		}
	    }

	    conSeq.append(seq[j]);
	}
    }

    conSeq.length(0);

    for(i = 0 ; i < bi.length() ; i++)
    {
	CORBA_ContainedSeq_var seq =
	    bi[i] -> contents(CORBA_dk_Attribute, false);

	for(CORBA_ULong j = 0 ; j < seq -> length() ; j++)
	{
	    CORBA_String_var name1 = seq[j] -> name();
	    CORBA_String_var id1 = seq[j] -> id();

	    for(CORBA_ULong k = 0 ; k < conSeq.length() ; k++)
	    {
		CORBA_String_var name2 = conSeq[k] -> name();
		CORBA_String_var id2 = conSeq[k] -> id();

		if(strcmp(id1, id2) != 0 && strcmp(name1, name2) == 0)
		{
		    //
		    // Attribute defined in multiple base interfaces
		    //
		    throw CORBA_INTF_REPOS(OBMinorAttrAmbiguous,
					   CORBA_COMPLETED_NO);
		}
	    }

	    conSeq.append(seq[j]);
	}
    }

    baseInterfaces_ = bi;
}

CORBA_Boolean
CORBA_InterfaceDef_impl::is_a(const char* interface_id)
{
    if(strcmp(id_, interface_id) == 0)
	return true;

    for(CORBA_ULong i = 0 ; i < baseInterfaces_.length() ; i++)
	if(baseInterfaces_[i] -> is_a(interface_id))
	    return true;

    return false;
}

CORBA_InterfaceDef::FullInterfaceDescription*
CORBA_InterfaceDef_impl::describe_interface()
{
    FullInterfaceDescription* desc = new FullInterfaceDescription;

    desc -> name = name();
    desc -> id = id();

    CORBA_Contained_var contained = CORBA_Contained::_narrow(definedIn_);
    if(!CORBA_is_nil(contained))
	desc -> defined_in = contained -> id();
    else
	desc -> defined_in = CORBA_string_dup("");

    desc -> version = version();

    CORBA_ULong i;

    for(i = 0 ; i < contents_.length() ; i++)
    {
	CORBA_Contained_ptr contained = contents_[i];
	
	CORBA_OperationDef_var operation =
	    CORBA_OperationDef::_narrow(contained);
	CORBA_AttributeDef_var attribute =
	    CORBA_AttributeDef::_narrow(contained);

	if(!CORBA_is_nil(operation))
	{
	    CORBA_Contained::Description_var d = operation -> describe();
	    CORBA_OperationDescription* operationDesc;
	    CORBA_Boolean b = d -> value >>= operationDesc;
	    assert(b);

	    desc -> operations.append(*operationDesc);
	}
	else if(!CORBA_is_nil(attribute))
	{
	    CORBA_Contained::Description_var d = attribute -> describe();
	    CORBA_AttributeDescription* attributeDesc;
	    CORBA_Boolean b = d -> value >>= attributeDesc;
	    assert(b);

	    desc -> attributes.append(*attributeDesc);
	}
    }

    for(i = 0 ; i < baseInterfaces_.length() ; i++)
    {
	CORBA_Contained_var baseContained =
	    CORBA_Contained::_narrow(baseInterfaces_[i]);
	if(!CORBA_is_nil(baseContained))
	    desc -> base_interfaces.append(baseContained -> id());
    }

    desc -> type = type();

    return desc;
}

CORBA_AttributeDef_ptr
CORBA_InterfaceDef_impl::create_attribute(const char* id,
					  const char* name,
					  const char* version,
					  CORBA_IDLType_ptr type,
					  CORBA_AttributeMode mode)
{
    CORBA_InterfaceDef_var self = _this();
    CORBA_AttributeDef_var p =
	new CORBA_AttributeDef_impl(orb_, (CORBA_InterfaceDef_ptr)self);
    p -> name(name);
    p -> id(id);
    p -> version(version);
    p -> type_def(type);
    p -> mode(mode);
    contents_.append(CORBA_AttributeDef::_duplicate(p));
    return CORBA_AttributeDef::_duplicate(p);
}

CORBA_OperationDef_ptr
CORBA_InterfaceDef_impl::
create_operation(const char* id,
		 const char* name,
		 const char* version,
		 CORBA_IDLType_ptr result,
		 CORBA_OperationMode mode,
		 const CORBA_ParDescriptionSeq& params,
		 const CORBA_ExceptionDefSeq& exceptions,
		 const CORBA_ContextIdSeq& contexts)
{
    CORBA_InterfaceDef_var self = _this();
    CORBA_OperationDef_var p =
	new CORBA_OperationDef_impl(orb_, (CORBA_InterfaceDef_ptr)self);
    p -> name(name);
    p -> id(id);
    p -> version(version);
    p -> result_def(result);
    p -> mode(mode);
    p -> params(params);
    p -> exceptions(exceptions);
    p -> contexts(contexts);
    contents_.append(CORBA_OperationDef::_duplicate(p));
    return CORBA_OperationDef::_duplicate(p);
}
