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

InterfaceDef.cc

Go to the documentation of this file.
00001 //                            Package   : omniIFR
00002 //  InterfaceDef.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 "InterfaceDef.h"
00024 
00025 #include "TypedefDef.h" // for CASE_TYPEDEF macro
00026 
00027 #include "AttributeDef.h"
00028 #include "OperationDef.h"
00029 #include "Repository.h"
00030 
00031 #include "Creche.h"
00032 #include "IdentifierUtil.h"
00033 #include "PersistNode.h"
00034 
00035 #include <algorithm>
00036 #include <assert.h>
00037 #include <string.h>
00038 
00039 namespace Omniifr {
00040 
00041 
00042 InterfaceDefSeq* InterfaceDef_impl::base_interfaces()
00043 {
00044   return _base_interfaces.copy();
00045 }
00046 
00047 
00048 void InterfaceDef_impl::base_interfaces(const InterfaceDefSeq& v)
00049 {
00050   checkReadonly();
00051   // Raise BAD_PARAM if the name of any object contained by this object
00052   // conflicts with the name of any object contained by any of the classes
00053   // in v.
00054 
00055   NoCaseStrSet vNameSet =inheritedNameSet(v);
00056 
00057   NoCaseStrSet myNameSet;
00058   {
00059     // ASSERT: There should never be a name clash within a container.
00060     ContainedSeq_var myAttributes=contents(dk_Attribute,1);
00061     ContainedSeq_var myOperations=contents(dk_Operation,1);
00062     assert( nameSetOk(myAttributes.in(),myNameSet) );
00063     assert( nameSetOk(myOperations.in(),myNameSet) );
00064   }
00065 
00066   NoCaseStrSet conflictSet;
00067   set_intersection(
00068     vNameSet.begin(), vNameSet.end(),
00069     myNameSet.begin(),myNameSet.end(), inserter(conflictSet,conflictSet.end())
00070   );
00071   
00072   // conflictSet contains conflicts between this->contents and inherited names.
00073   if(!conflictSet.empty())
00074   {
00075     string badNames="";
00076     for(NoCaseStrSet::const_iterator i=conflictSet.begin();
00077         i!=conflictSet.end();
00078         ++i)
00079     {
00080       badNames+=" \""+(*i)+"\"";
00081     }
00082     DB(1,"BAD_PARAM_InheritedNameClash. InterfaceDef \""<<_name<< \
00083       "\" base_interfaces() rejected duplicate names:"<<badNames.c_str()<<".")
00084     throw CORBA::BAD_PARAM(
00085       IFELSE_OMNIORB4(omni::BAD_PARAM_InheritedNameClash,5),
00086       CORBA::COMPLETED_NO
00087     );
00088   }
00089   
00090   // Procede:
00091   _base_interfaces.assign(v); // May raise BAD_PARAM.
00092 }
00093 
00094 
00095 Boolean InterfaceDef_impl::is_a(const char* interface_id)
00096 {
00097   assert(interface_id);
00098 
00099   if(strcmp(interface_id,"IDL:omg.org/CORBA/Object:1.0")==0)
00100       return true;
00101 
00102   if(strcmp(interface_id,_id.in())==0) // itself
00103       return true;
00104 
00105   const InterfaceDefSeq& bis =_base_interfaces.in();
00106   for(ULong i=0; i<bis.length(); i++)
00107   {
00108     assert(!CORBA::is_nil(bis[i]));
00109     if(bis[i]->is_a(interface_id))
00110         return true;
00111   }
00112   return false;
00113 }
00114 
00115 
00116 CORBA::InterfaceDef::FullInterfaceDescription*
00117 InterfaceDef_impl::describe_interface()
00118 {
00119   CORBA::InterfaceDef::FullInterfaceDescription_var result =
00120       new CORBA::InterfaceDef::FullInterfaceDescription();
00121   result->name            =name();
00122   result->id              =id();
00123   result->defined_in      =definedInId();
00124   result->version         =version();
00125 
00126   ContainedSeq_var containedseq =contents(dk_Operation,false);
00127   result->operations.length(containedseq->length());
00128   for(ULong i=0; i < containedseq->length(); i++ )
00129   {
00130     CORBA::Contained::Description_var description=containedseq[i]->describe();
00131     const OperationDescription* operation;
00132     description->value >>= operation;   // Any still owns memory
00133     result->operations[i] = *operation; // deep copy
00134   }
00135 
00136   containedseq=contents(dk_Attribute,false);
00137   result->attributes.length(containedseq->length());
00138   for(ULong j=0; j<containedseq->length(); j++)
00139   {
00140     CORBA::Contained::Description_var description=containedseq[j]->describe();
00141     const AttributeDescription* attribute;
00142     description->value >>= attribute;   // Any still owns memory
00143     result->attributes[j] = *attribute; // deep copy
00144   }
00145 
00146   result->base_interfaces =baseInterfacesIds();
00147   result->type            =type();
00148 
00149   return result._retn();
00150 }
00151 
00152 
00153 AttributeDef_ptr InterfaceDef_impl::create_attribute(
00154   const char*   id,
00155   const char*   name,
00156   const char*   version,
00157   IDLType_ptr   type,
00158   AttributeMode mode
00159 )
00160 {
00161   DB(5,"InterfaceDef::create_attribute("<<id<<","<<name<<","<<version<<",...)")
00162   checkReadonly();
00163   checkInheritedNameClash(name);
00164 
00165   // Create the attribute.
00166   Creche<AttributeDef_impl> newattribute(new AttributeDef_impl());
00167   newattribute->init(id,name,version,this);
00168   newattribute->mode(mode);
00169   newattribute->type_def(type);
00170   return newattribute.release()->_this();
00171 }
00172 
00173 
00174 OperationDef_ptr InterfaceDef_impl::create_operation(
00175   const char*              id,
00176   const char*              name,
00177   const char*              version,
00178   IDLType_ptr              result,
00179   OperationMode            mode,
00180   const ParDescriptionSeq& params,
00181   const ExceptionDefSeq&   exceptions,
00182   const ContextIdSeq&      contexts
00183 )
00184 {
00185   DB(5,"InterfaceDef::create_operation("<<id<<","<<name<<","<<version<<",...)")
00186   checkReadonly();
00187   checkInheritedNameClash(name);
00188 
00189   // Create the operation.
00190   Creche<OperationDef_impl> newoperation(new OperationDef_impl());
00191   newoperation->init(id,name,version,this);
00192   newoperation->mode(mode);
00193   newoperation->contexts(contexts);
00194   newoperation->result_def(result);
00195   newoperation->params(params);
00196   newoperation->exceptions(exceptions);
00197   return newoperation.release()->_this();
00198 }
00199 
00200 
00201 ContainedSeq* InterfaceDef_impl::contents(
00202   DefinitionKind limit_type,
00203   Boolean        exclude_inherited
00204 )
00205 {
00206   ContainedSeq_var result =Container_impl::contents(limit_type,1);
00207 
00208   // Add in inherited attributes & operations, if required.
00209   if( (!exclude_inherited) &&
00210         (limit_type==dk_all ||
00211          limit_type==dk_Operation ||
00212          limit_type==dk_Attribute))
00213   {
00214     const InterfaceDefSeq& bis=_base_interfaces.in();
00215     for(ULong i=0; i<bis.length(); ++i)
00216     {
00217       // result += inherited operations.
00218       if( limit_type==dk_all || limit_type==dk_Operation )
00219       {
00220         ContainedSeq_var opers =bis[i]->contents(dk_Operation,0);
00221         ULong offset=result->length();
00222         result->length( offset+opers->length() );
00223         for(ULong j=0; j<opers->length(); ++j)
00224             result[offset+j]=opers[j]._retn();
00225       }
00226       // result += inherited attributes.
00227       if( limit_type==dk_all || limit_type==dk_Operation )
00228       {
00229         ContainedSeq_var attrs =bis[i]->contents(dk_Attribute,0);
00230         ULong offset=result->length();
00231         result->length( offset+attrs->length() );
00232         for(ULong k=0; k<attrs->length(); ++k)
00233             result[offset+k]=attrs[k]._retn();
00234       }
00235     }
00236   }
00237   
00238   return result._retn();
00239 }
00240 
00241 
00242 CORBA::Contained::Description* InterfaceDef_impl::describe()
00243 {
00244   InterfaceDescription_var interfacedesc = new InterfaceDescription();
00245   interfacedesc->name           =name();
00246   interfacedesc->id             =id();
00247   interfacedesc->version        =version();
00248   interfacedesc->base_interfaces=baseInterfacesIds();
00249   interfacedesc->defined_in     =definedInId();
00250 
00251   CORBA::Contained::Description_var description =
00252       new CORBA::Contained::Description();
00253   description->kind  =   def_kind();
00254   description->value <<= interfacedesc._retn();
00255 
00256   return description._retn();
00257 }
00258 
00259 
00260 TypeCode_ptr InterfaceDef_impl::type()
00261 {
00262   return Repository_impl::inst()._orb
00263          ->create_interface_tc(_id.in(),_name.in());
00264 }
00265 
00266 
00267 void InterfaceDef_impl::uncheckedDestroy()
00268 {
00269   _base_interfaces.clear();
00270   Contained_impl::uncheckedDestroy(); // superclass
00271   Container_impl::uncheckedDestroy(); // superclass
00272 }
00273 
00274 
00275 bool InterfaceDef_impl::canContain(DefinitionKind kind)
00276 {
00277   switch(kind)
00278   {
00279     CASE_TYPEDEF
00280     case dk_Constant:
00281     case dk_Exception:
00282     case dk_Operation:
00283     case dk_Attribute:
00284       return true;
00285     default:
00286       return false;
00287   }
00288 }
00289 
00290 
00291 void InterfaceDef_impl::reincarnate(const PersistNode& node)
00292 {
00293   // Reincarnate ths object.
00294   cdrMemoryStream memstr =node.attrCdrStream("state");
00295   InterfaceDefSeq b;
00296   b<<=memstr;
00297   _base_interfaces.assign(b);
00298   
00299   // Reincarnate contained objects.
00300   // Compare the implementation of Container_impl::recreate()
00301   // Note that there is no need to defer complete reincarnation of these
00302   // contained object, because they can never be the object of a link from
00303   // elsewhere in the hierarchy. (Operations and Attributes can never be
00304   // referred to by another part of the IDL.)
00305   for(map<string,PersistNode*>::const_iterator i =node._child.begin();
00306                                                i!=node._child.end();
00307                                              ++i)
00308   {
00309     const string iOid     =i->second->attrString("oid");
00310     const string iId      =i->second->attrString("id");
00311     const string iVersion =i->second->attrString("version");
00312     const string iClass   =i->second->attrString("class");
00313     const int    iIndex   =i->second->attrLong("index");
00314     if(iOid.empty() || iId.empty() || iVersion.empty() || iClass.empty())
00315     {
00316       DB(1,"InterfaceDef_impl::reincarnate(): "
00317            "expected 'Contained' type child node.")
00318       i->second->output(cerr,i->first);
00319       continue;
00320     }
00321     // OK
00322     if("AttributeDef"==iClass)
00323     {
00324       Creche<AttributeDef_impl> servant(new AttributeDef_impl());
00325       servant->init(iId.c_str(),i->first.c_str(),iVersion.c_str(),this,iIndex);
00326       servant->reincarnate(*i->second);
00327       servant.release(iOid.c_str());
00328     }
00329     else if("OperationDef"==iClass)
00330     {
00331       Creche<OperationDef_impl> servant(new OperationDef_impl());
00332       servant->init(iId.c_str(),i->first.c_str(),iVersion.c_str(),this,iIndex);
00333       servant->reincarnate(*i->second);
00334       servant.release(iOid.c_str());
00335     }
00336   } // end for(i)
00337 } // end InterfaceDef_impl::reincarnate()
00338 
00339 
00340 void InterfaceDef_impl::output(ostream &os)
00341 {
00342   outputSelf(os,"InterfaceDef");
00343   cdrMemoryStream memstr(CORBA::ULong(0),CORBA::Boolean(1)/*clearMemory*/);
00344   _base_interfaces.in()>>=memstr;
00345   PersistNode::outputCdrMemoryStream(os,memstr,"\n state=");
00346   os<<" ;;\n";
00347   outputContents(os);
00348 }
00349 
00350 
00351 RepositoryIdSeq InterfaceDef_impl::baseInterfacesIds()
00352 {
00353   RepositoryIdSeq result;
00354   try
00355   {
00356     const InterfaceDefSeq& bis =_base_interfaces.in();
00357     result.length(bis.length());
00358     for(ULong i=0; i<bis.length(); ++i)
00359     {
00360       assert(!CORBA::is_nil(bis[i]));
00361       result[i]=bis[i]->id();
00362     }
00363   }
00364   catch(...)
00365   {
00366     result.length(0);
00367     throw;
00368   }
00369   return result;
00370 }
00371 
00372 
00373 void InterfaceDef_impl::checkInheritedNameClash(const char* name)
00374 {
00375   IdentifierUtil::checkInvalid(name);
00376 
00377   NoCaseStrSet nameSet =inheritedNameSet(_base_interfaces.in());
00378 
00379   if(nameSet.find(string(name))!=nameSet.end())
00380   {
00381     DB(1,"BAD_PARAM_InheritedNameClash. InterfaceDef \""<<_name.in()<< \
00382          "\" rejected duplicate name: \""<<name<<"\"")
00383     throw CORBA::BAD_PARAM(
00384       IFELSE_OMNIORB4(omni::BAD_PARAM_InheritedNameClash,5),
00385       CORBA::COMPLETED_NO
00386     );
00387   }
00388 }
00389 
00390 
00391 void InterfaceDef_impl::interfaceSet(
00392   const InterfaceDefSeq& baseInterfaces,
00393   set<string>& repositoryIdSet,
00394   InterfaceDefSeq& allBaseInterfaces
00395 )
00396 {
00397   for(ULong i=0; i<baseInterfaces.length(); ++i)
00398   {
00399     String_var iName =baseInterfaces[i]->name();
00400     if(repositoryIdSet.find(string(iName.in()))==repositoryIdSet.end())
00401     {
00402       // This approach is inefficient when the sequence length might be large,
00403       // but for this case, it's OK.
00404       ULong len =repositoryIdSet.size();
00405       allBaseInterfaces.length(1+len);
00406       allBaseInterfaces[len]=CORBA::InterfaceDef::_duplicate(baseInterfaces[i]);
00407       repositoryIdSet.insert(string(iName.in()));
00408       // Now add in more distant ancestors.
00409       InterfaceDefSeq_var ancestors =baseInterfaces[i]->base_interfaces();
00410       interfaceSet(ancestors.in(),repositoryIdSet,allBaseInterfaces);
00411     }
00412   }
00413 }
00414 
00415 
00416 inline InterfaceDef_impl::NoCaseStrSet
00417 InterfaceDef_impl::inheritedNameSet(
00418   const InterfaceDefSeq& baseInterfaces
00419 )
00420 {
00421   // Find all base interfaces, including indirectly inherited ones.
00422   set<string> ridSet;
00423   InterfaceDefSeq allBaseInterfaces;
00424   interfaceSet(baseInterfaces,ridSet,allBaseInterfaces);
00425 
00426   NoCaseStrSet result;
00427   for(ULong i=0; i<allBaseInterfaces.length(); ++i)
00428   {
00429     // ?? Catch COMMS / TRANSIENT errors here? Translate into BAD_PARAM?
00430     bool ok =true;
00431     ContainedSeq_var iAttrs =allBaseInterfaces[i]->contents(dk_Attribute,1);
00432     ContainedSeq_var iOpers =allBaseInterfaces[i]->contents(dk_Operation,1);
00433     ok=ok&&( nameSetOk(iAttrs.in(),result) );
00434     ok=ok&&( nameSetOk(iOpers.in(),result) );
00435     if(!ok) // Conflict amongst base interfaces
00436     {
00437       string baseIntNames ="";
00438       for(set<string>::const_iterator j=ridSet.begin(); j!=ridSet.end(); ++j)
00439       {
00440         baseIntNames+=" \""+(*j)+"\"";
00441       }
00442       DB(1,"BAD_PARAM_InheritedNameClash. InterfaceDef \""<<_name.in()<< \
00443         "\" detected conflict amongst base interfaces:"<<baseIntNames.c_str()<<".")
00444       throw CORBA::BAD_PARAM(
00445         IFELSE_OMNIORB4(omni::BAD_PARAM_InheritedNameClash,5),
00446         CORBA::COMPLETED_NO
00447       );
00448     }
00449   }
00450   return result;
00451 }
00452 
00453 
00454 inline bool InterfaceDef_impl::nameSetOk(
00455   const ContainedSeq& contents,
00456   NoCaseStrSet&       result
00457 )
00458 {
00459   bool ok =true;
00460   for(ULong i=0; i<contents.length(); ++i)
00461   {
00462     CORBA::String_var iName =contents[i]->name();
00463     if(!result.insert(iName.in()).second)
00464     {
00465       DB(5,"Name clash: \""<<iName.in()<<"\"")
00466       ok=false; // Name clash detected.
00467     }
00468   }
00469   return ok;
00470 }
00471 
00472 
00473 } // end namespace Omniifr

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