Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

UnionDef.cc

Go to the documentation of this file.
00001 //                            Package   : omniIFR
00002 //  UnionDef.cc               Created   : 2004/02/22
00003 //                            Author    : Alex Tingle
00004 //
00005 //    Copyright (C) 2004 Alex Tingle.
00006 //
00007 //    This file is part of the omniIFR application.
00008 //
00009 //    omniIFR is free software; you can redistribute it and/or
00010 //    modify it under the terms of the GNU Lesser General Public
00011 //    License as published by the Free Software Foundation; either
00012 //    version 2.1 of the License, or (at your option) any later version.
00013 //
00014 //    omniIFR is distributed in the hope that it will be useful,
00015 //    but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017 //    Lesser General Public License for more details.
00018 //
00019 //    You should have received a copy of the GNU Lesser General Public
00020 //    License along with this library; if not, write to the Free Software
00021 //    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022 //
00023 #include "UnionDef.h"
00024 
00025 #include "Repository.h"
00026 #include "PersistNode.h"
00027 #include "string_to.h"
00028 
00029 #include <string.h>
00030 
00031 namespace Omniifr {
00032 
00033 TypeCode_ptr UnionDef_impl::discriminator_type()
00034 {
00035   return _discriminator_type_def.in()->type();
00036 }
00037 
00038 IDLType_ptr UnionDef_impl::discriminator_type_def()
00039 {
00040   return _discriminator_type_def.copy();
00041 }
00042 
00043 void UnionDef_impl::discriminator_type_def(IDLType_ptr v)
00044 {
00045   checkReadonly();
00046   TypeCode_var tc    =v->type();
00047   TCKind       kind  =tc->kind();
00048   // Strip out aliases.
00049   while(kind==tk_alias)
00050   {
00051     tc=tc->content_type();
00052     kind=tc->kind();
00053   }
00054 
00055   switch(kind)
00056   {
00057     case tk_short: // <integer_type>
00058     case tk_ushort:
00059     case tk_long:
00060     case tk_ulong:
00061 #ifdef HAS_LongLong
00062     case tk_longlong:
00063     case tk_ulonglong:
00064 #endif
00065     case tk_char: // <char_type>
00066     case tk_wchar: // <wide_char_type>
00067     case tk_boolean: // <boolean_type>
00068     case tk_enum:
00069       {
00070         // If discriminator type has changed, then erase _members here,
00071         // to protect against type incompatability.
00072         if(!is_nil(_discriminator_type_def.in()))
00073         {
00074           TypeCode_var oldTc =discriminator_type();
00075           if(!tc->equivalent(oldTc.in()))
00076               _members.assign(UnionMemberSeq()); // clear _members.
00077         }
00078         _discriminator_type_def.assign(CORBA::IDLType::_duplicate(v));
00079       }
00080       break;
00081 
00082     default:
00083       throw CORBA::BAD_PARAM(
00084         IFELSE_OMNIORB4(omni::BAD_PARAM_IllegitimateDiscriminatorType,20),
00085         CORBA::COMPLETED_NO
00086       );
00087   }
00088 }
00089 
00090 UnionMemberSeq* UnionDef_impl::members()
00091 {
00092   return _members.copy();
00093 }
00094 
00095 void UnionDef_impl::members(const UnionMemberSeq& v)
00096 {
00097   checkReadonly();
00098   UnionMemberSeq temp(v); // take a copy (v is const).
00099   TypeCode_var discriminatorType =discriminator_type();
00100   
00101   // Note: These checks are similar to Dependency3::check(), but more
00102   // extensive.
00103   
00104   for(ULong i=0; i<temp.length(); ++i)
00105   {
00106     IdentifierUtil::checkInvalid(temp[i].name);
00107     if(CORBA::is_nil(temp[i].type_def))
00108         throw CORBA::BAD_PARAM(
00109           IFELSE_OMNIORB4(omni::BAD_PARAM_InvalidObjectRef,43),
00110           CORBA::COMPLETED_NO
00111         );
00112 
00113     // Set type to match type_def. (Ignore type's current value.)
00114     try
00115     {
00116       temp[i].type=temp[i].type_def->type();
00117     }
00118     catch(...)
00119     {
00120       DB(15,"Caught exception at "<<__FILE__<<":"<<__LINE__)
00121       throw; // If an exception occurs, just propagate it as-is.
00122     }
00123 
00124     // The default label (Octet with the value zero) is always allowed.
00125     CORBA::Octet oct;
00126     bool isDefaultLabel=((temp[i].label>>=CORBA::Any::to_octet(oct)) && oct==0);
00127     if(!isDefaultLabel)
00128     {
00129       // Check that label's type matches discriminator_type.
00130       TypeCode_var labelType =temp[i].label.type();
00131       if(!labelType->equivalent(discriminatorType.in()))
00132           throw CORBA::BAD_PARAM(
00133             IFELSE_OMNIORB4(omni::BAD_PARAM_IncompatibleDiscriminatorType,19),
00134             CORBA::COMPLETED_NO
00135           );
00136 
00137       // Check that the label is unique.
00138       DynamicAny::DynAny_var dai =
00139         Repository_impl::inst()._DynAnyFactory->create_dyn_any(temp[i].label);
00140       bool uniqueLabel =true;
00141       for(ULong j=0; uniqueLabel && j<i; ++j)
00142       {
00143         DynamicAny::DynAny_var daj =
00144           Repository_impl::inst()._DynAnyFactory->create_dyn_any(temp[j].label);
00145         if(dai->equal(daj))
00146             uniqueLabel=false;
00147         daj->destroy();
00148       }
00149       dai->destroy();
00150       if(!uniqueLabel)
00151           throw CORBA::BAD_PARAM(
00152             IFELSE_OMNIORB4(omni::BAD_PARAM_DuplicateLabelValue,18),
00153             CORBA::COMPLETED_NO
00154           );
00155     }
00156 
00157     // Check that name/type is legal.
00158     // name must be unique, UNLESS it AND ITS TYPE are the same as the previous
00159     // member.
00160     bool match =true;
00161     for(Long k=i-1; k>=0; --k)
00162     {
00163       switch(IdentifierUtil::compare(temp[i].name,temp[k].name))
00164       {
00165         case IdentifierUtil::equalMatch:
00166             if(! (match && temp[i].type->equal(temp[k].type)) )
00167                 throw CORBA::BAD_PARAM(); // ?? Minor code?
00168             break;
00169 
00170         case IdentifierUtil::equivalentMatch:
00171             throw CORBA::BAD_PARAM(
00172               IFELSE_OMNIORB4(omni::BAD_PARAM_InvalidMemberName,17),
00173               CORBA::COMPLETED_NO
00174             );
00175 
00176         case IdentifierUtil::noMatch:
00177             match=false;
00178             break;
00179 
00180         default:
00181             assert(false); // Never get here.
00182       }; // end switch.
00183     }
00184   }
00185   
00186   // Do it.
00187   _members.uncheckedAssign(temp);
00188 }
00189 
00190 TypeCode_ptr UnionDef_impl::type()
00191 {
00192   TypeCode_var tc =discriminator_type();
00193   return Repository_impl::inst()._orb
00194     ->create_union_tc(_id.in(),_name.in(),tc.in(),_members.in());
00195 }
00196 
00197 void UnionDef_impl::uncheckedDestroy()
00198 {
00199   _members.clear();
00200   _discriminator_type_def.clear();
00201   Contained_impl::uncheckedDestroy();
00202   Container_impl::uncheckedDestroy();
00203 }
00204 
00205 bool UnionDef_impl::canContain(DefinitionKind kind)
00206 {
00207   switch(kind)
00208   {
00209     case dk_Struct:
00210     case dk_Union:
00211     case dk_Enum:
00212       return true;
00213     default:
00214       return false;
00215   }
00216 }
00217 
00218 void UnionDef_impl::reincarnate(const PersistNode& node)
00219 {
00220   _discriminator_type_def.assign(
00221    string_to_<CORBA::IDLType>(node.attrString("discriminator_type_def").c_str())
00222   );
00223 
00224   cdrMemoryStream memstr =node.attrCdrStream("state");
00225   UnionMemberSeq m;
00226   m<<=memstr;
00227   _members.uncheckedAssign(m); // Skip the checks performed by members(m)
00228 }
00229 
00230 void UnionDef_impl::output(ostream &os)
00231 {
00232   outputSelf(os,"UnionDef");
00233   PersistNode::outputIOR(os,
00234     _discriminator_type_def.in(),
00235     "\n discriminator_type_def="
00236   );
00237   cdrMemoryStream memstr(CORBA::ULong(0),CORBA::Boolean(1)/*clearMemory*/);
00238   _members.in()>>=memstr;
00239   PersistNode::outputCdrMemoryStream(os,memstr,"\n state=");
00240   os<<" ;;\n";
00241   outputContents(os);
00242 }
00243 
00244 } // end namespace Omniifr

Generated on Fri Mar 4 13:03:23 2005 for OmniIFR by  doxygen 1.4.1