00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "InterfaceDef.h"
00024
00025 #include "TypedefDef.h"
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
00052
00053
00054
00055 NoCaseStrSet vNameSet =inheritedNameSet(v);
00056
00057 NoCaseStrSet myNameSet;
00058 {
00059
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
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
00091 _base_interfaces.assign(v);
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)
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;
00133 result->operations[i] = *operation;
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;
00143 result->attributes[j] = *attribute;
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
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
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
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
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
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();
00271 Container_impl::uncheckedDestroy();
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
00294 cdrMemoryStream memstr =node.attrCdrStream("state");
00295 InterfaceDefSeq b;
00296 b<<=memstr;
00297 _base_interfaces.assign(b);
00298
00299
00300
00301
00302
00303
00304
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
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 }
00337 }
00338
00339
00340 void InterfaceDef_impl::output(ostream &os)
00341 {
00342 outputSelf(os,"InterfaceDef");
00343 cdrMemoryStream memstr(CORBA::ULong(0),CORBA::Boolean(1));
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
00403
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
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
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
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)
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;
00467 }
00468 }
00469 return ok;
00470 }
00471
00472
00473 }