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

Container.cc

Go to the documentation of this file.
00001 //                            Package   : omniIFR
00002 //  Container.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 "Container.h"
00024 
00025 #include "Contained.h"
00026 #include "Repository.h"
00027 #include "ModuleDef.h"
00028 
00029 #include "ConstantDef.h"
00030 #include "StructDef.h"
00031 #include "UnionDef.h"
00032 #include "EnumDef.h"
00033 #include "AliasDef.h"
00034 #include "InterfaceDef.h"
00035 #include "ExceptionDef.h"
00036 
00037 #include "PersistNode.h"
00038 #include "Creche.h"
00039 
00040 #include <string.h>
00041 #include <algorithm>
00042 
00043 namespace Omniifr {
00044 
00045 Contained_ptr Container_impl::lookup(const char* search_name)
00046 {
00047   Contained_impl* result =lookupServant(search_name,true); // Case sensitive
00048   if(result)
00049       return result->_this();
00050   else
00051       return Contained::_nil();
00052 }
00053 
00054 
00058 ContainedSeq* Container_impl::contents(
00059   DefinitionKind limit_type,
00060   CORBA::Boolean exclude_inherited
00061 )
00062 {
00063   ContainedSeq_var result = new ContainedSeq();
00064   ULong resultLength =0;
00065 
00066   for(list<Contained_impl*>::iterator it =_contents.begin();
00067       it!=_contents.end();
00068       ++it)
00069   {
00070     if(limit_type==dk_all || limit_type==(*it)->def_kind())
00071     {
00072       result->length(resultLength+1);
00073       result[resultLength]=(*it)->_this();
00074       ++resultLength;
00075     }
00076   }
00077   return result._retn();
00078 }
00079 
00083 ContainedSeq* Container_impl::lookup_name(
00084   const char*    search_name,
00085   CORBA::Long    levels_to_search,
00086   DefinitionKind limit_type,
00087   CORBA::Boolean exclude_inherited
00088 )
00089 {
00090   ContainedSeq_var result =new ContainedSeq();
00091   ULong resultLength =0;
00092   Long subLevels =levels_to_search<0? levels_to_search : levels_to_search-1;
00093   EqualName equalName(search_name,true); // true -> case sensitive
00094 
00095   // Obtain all contents (even inherited) that match the limit_type.
00096   ContainedSeq_var contents =this->contents(limit_type,exclude_inherited);
00097   for(ULong i=0; i<contents->length(); ++i)
00098   {
00099     if(equalName(contents[i]) && // name match
00100         limit_type==dk_all || limit_type==contents[i]->def_kind()) // type match
00101     {
00102       result->length(resultLength+1);
00103       result[resultLength]=contents[i];
00104       ++resultLength;
00105     }
00106   }
00107 
00108   // Search sub levels, if required.
00109   if(subLevels!=0)
00110   {
00111     for(list<Contained_impl*>::iterator it =_contents.begin();
00112         it!=_contents.end();
00113         ++it)
00114     {
00115       Container_impl* subContainer =dynamic_cast<Container_impl*>(*it);
00116       if(subContainer)
00117       {
00118         ContainedSeq_var subResult =subContainer->
00119           lookup_name(search_name,subLevels,limit_type,exclude_inherited);
00120         result->length( resultLength+subResult->length() );
00121         for(ULong j=0; j<subResult->length(); ++j)
00122             result[resultLength++]=subResult[j]._retn();
00123       }
00124     }
00125   }
00126   return result._retn();
00127 }
00128 
00129 CORBA::Container::DescriptionSeq* Container_impl::describe_contents(
00130   DefinitionKind limit_type,
00131   Boolean        exclude_inherited,
00132   Long           max_returned_objs
00133 )
00134 {
00135   ContainedSeq_var containedseq =contents(limit_type,exclude_inherited);
00136 
00137   ULong numObjectsToReturn =containedseq->length();
00138   if(max_returned_objs>=Long(numObjectsToReturn))
00139       numObjectsToReturn=max_returned_objs;     
00140 
00141   CORBA::Container::DescriptionSeq_var result =
00142     new CORBA::Container::DescriptionSeq();
00143   result->length(numObjectsToReturn);
00144 
00145   for(ULong i=0; i<numObjectsToReturn; ++i)
00146   {
00147     CORBA::Contained::Description_var iDescription =containedseq[i]->describe();
00148     result[i].contained_object=containedseq[i];
00149     result[i].kind            =iDescription->kind;
00150     result[i].value           =iDescription->value;
00151   }
00152   return result._retn();
00153 }
00154 
00155 ModuleDef_ptr Container_impl::create_module(
00156   const char* id, const char* name, const char* version
00157 )
00158 {
00159   DB(5,"Container::create_module("<<id<<","<<name<<","<<version<<")")
00160   checkReadonly();
00161   Creche<ModuleDef_impl> newmodule(new ModuleDef_impl());
00162   newmodule->init(id,name,version,this);
00163   return newmodule.release()->_this();
00164 }
00165 
00166 ConstantDef_ptr Container_impl::create_constant(
00167   const char* id, const char* name, const char* version,
00168   IDLType_ptr type,
00169   const Any&  value
00170 )
00171 {
00172   DB(5,"Container::create_constant("<<id<<","<<name<<","<<version<<",...)")
00173   checkReadonly();
00174   Creche<ConstantDef_impl> newconstant(new ConstantDef_impl());
00175   newconstant->init(id,name,version,this);
00176   // Order is important.
00177   newconstant->type_def(type);
00178   newconstant->value(value);
00179   return newconstant.release()->_this();
00180 }
00181 
00182 StructDef_ptr Container_impl::create_struct(
00183   const char* id, const char* name, const char* version,
00184   const StructMemberSeq& members
00185 )
00186 {
00187   DB(5,"Container::create_struct("<<id<<","<<name<<","<<version<<",...)")
00188   checkReadonly();
00189   Creche<StructDef_impl> newstruct(new StructDef_impl());
00190   newstruct->init(id,name,version,this);
00191   newstruct->members(members);
00192   return newstruct.release()->_this();
00193 }
00194 
00195 UnionDef_ptr Container_impl::create_union(
00196   const char* id, const char* name, const char* version,
00197   IDLType_ptr           discriminator_type,
00198   const UnionMemberSeq& members
00199 ) 
00200 {
00201   DB(5,"Container::create_union("<<id<<","<<name<<","<<version<<",...)")
00202   checkReadonly();
00203   Creche<UnionDef_impl> newunion(new UnionDef_impl());
00204   newunion->init(id,name,version,this);
00205   // Note, order is important.
00206   newunion->discriminator_type_def(discriminator_type);
00207   newunion->members(members);
00208   return newunion.release()->_this();
00209 }
00210 
00211 EnumDef_ptr Container_impl::create_enum(
00212   const char* id, const char* name, const char* version,
00213   const EnumMemberSeq& members
00214 )
00215 {
00216   DB(5,"Container::create_enum("<<id<<","<<name<<","<<version<<",...)")
00217   checkReadonly();
00218   Creche<EnumDef_impl> newenum(new EnumDef_impl());
00219   newenum->init(id,name,version,this);
00220   newenum->members(members);
00221   return newenum.release()->_this();
00222 }
00223 
00224 AliasDef_ptr Container_impl::create_alias(
00225   const char* id, const char* name, const char* version,
00226   IDLType_ptr original_type
00227 )
00228 {
00229   DB(5,"Container::create_alias("<<id<<","<<name<<","<<version<<",...)")
00230   checkReadonly();
00231   Creche<AliasDef_impl> newalias(new AliasDef_impl());
00232   newalias->init(id,name,version,this);
00233   newalias->original_type_def(original_type);
00234   return newalias.release()->_this();
00235 }
00236 
00237 InterfaceDef_ptr Container_impl::create_interface(
00238   const char* id, const char* name, const char* version,
00239   const InterfaceDefSeq& base_interfaces
00240 )
00241 {
00242   DB(5,"Container::create_interface("<<id<<","<<name<<","<<version<<",...)")
00243   checkReadonly();
00244   Creche<InterfaceDef_impl> newinterface(new InterfaceDef_impl());
00245   newinterface->init(id,name,version,this);
00246   newinterface->base_interfaces(base_interfaces);
00247   return newinterface.release()->_this();
00248 }
00249 
00250 ExceptionDef_ptr Container_impl::create_exception(
00251   const char* id, const char* name, const char* version,
00252   const StructMemberSeq& members
00253 )
00254 {
00255   DB(5,"Container::create_exception("<<id<<","<<name<<","<<version<<",...)")
00256   checkReadonly();
00257   Creche<ExceptionDef_impl> newexception(new ExceptionDef_impl());
00258   newexception->init(id,name,version,this);
00259   newexception->members(members);
00260   return newexception.release()->_this();
00261 }
00262 
00263 ValueDef_ptr Container_impl::create_value(
00264   const char* id, const char* name, const char* version,
00265   Boolean                is_custom,
00266   Boolean                is_abstract,
00267   ValueDef_ptr           base_value,
00268   Boolean                is_truncatable,
00269   const ValueDefSeq&     abstract_base_values,
00270   const InterfaceDefSeq& supported_interfaces,
00271   const InitializerSeq&  initializers
00272 )
00273 {
00274   DB(5,"Container::create_value("<<id<<","<<name<<","<<version<<",...)")
00275   checkReadonly();
00276   // not supported
00277   return ValueDef::_nil();
00278 }
00279 
00280 ValueBoxDef_ptr Container_impl::create_value_box(
00281   const char* id, const char* name, const char* version,
00282   IDLType_ptr original_type_def
00283 )
00284 {
00285   DB(5,"Container::create_value_box("<<id<<","<<name<<","<<version<<",...)")
00286   checkReadonly();
00287   // not supported
00288   return ValueBoxDef::_nil();    
00289 }
00290 
00291 NativeDef_ptr Container_impl::create_native(
00292   const char* id, const char* name, const char* version
00293 )
00294 {
00295   DB(5,"Container::create_native("<<id<<","<<name<<","<<version<<",...)")
00296   checkReadonly();
00297   // not supported
00298   return NativeDef::_nil();
00299 }
00300 
00301 AbstractInterfaceDef_ptr Container_impl:: create_abstract_interface(
00302   const char* id, const char* name, const char* version,
00303   const AbstractInterfaceDefSeq& base_interfaces
00304 )
00305 {
00306   DB(5,"Container::create_abstract_interface("<<id<<","<<name<<","<<version<<",...)")
00307   checkReadonly();
00308   // not supported
00309   return AbstractInterfaceDef::_nil();
00310 }
00311 
00312 //
00313 // added members
00314 //
00315 
00316 void Container_impl::dependentObjectSet(set<const IRObject_impl*>& result) const
00317 {
00318   IRObject_impl::dependentObjectSet(result); // parent's implementation.
00319   // now add in contained objects
00320   for(list<Contained_impl*>::const_iterator i=_contents.begin();
00321       i!=_contents.end();
00322       ++i)
00323   {
00324     (**i).dependentObjectSet(result);
00325   }
00326 }
00327 
00328 void Container_impl::containedObjectSet(set<const IRObject_impl*>& result) const
00329 {
00330   IRObject_impl::containedObjectSet(result); // parent's implementation.
00331   // now add in contained objects
00332   for(list<Contained_impl*>::const_iterator i=_contents.begin();
00333       i!=_contents.end();
00334       ++i)
00335   {
00336     (**i).containedObjectSet(result);
00337   }
00338 }
00339 
00340 void Container_impl::recreate(
00341   PersistNode*                      node,
00342   map<IRObject_impl*,PersistNode*>& todo)
00343 {
00344   if(!node)
00345   {
00346     DB(1,"Container_impl::recreate(): NULL child node encountered.")
00347     return;
00348   }
00349 
00350   for(map<string,PersistNode*>::const_iterator i =node->_child.begin();
00351                                                i!=node->_child.end();
00352                                              ++i)
00353   {
00354     const string iOid     =i->second->attrString("oid");
00355     const string iId      =i->second->attrString("id");
00356     const string iVersion =i->second->attrString("version");
00357     const string iClass   =i->second->attrString("class");
00358     const int    iIndex   =i->second->attrLong("index");
00359     if(iOid.empty() || iId.empty() || iVersion.empty() || iClass.empty())
00360     {
00361       DB(1,"Container_impl::recreate(): expected 'Contained' type child node.")
00362       i->second->output(cerr,i->first);
00363       continue;
00364     }
00365     // OK
00366     if("ModuleDef"==iClass)
00367     {
00368       Creche<ModuleDef_impl> servant(new ModuleDef_impl());
00369       servant->init(iId.c_str(),i->first.c_str(),iVersion.c_str(),this,iIndex);
00370       servant->recreate(i->second,todo);
00371       servant.release(iOid.c_str());
00372     }
00373     else if("ConstantDef"==iClass)
00374     {
00375       Creche<ConstantDef_impl> servant(new ConstantDef_impl());
00376       servant->init(iId.c_str(),i->first.c_str(),iVersion.c_str(),this,iIndex);
00377       todo[servant.get()]=i->second;
00378       servant.release(iOid.c_str());
00379     }
00380     else if("StructDef"==iClass)
00381     {
00382       Creche<StructDef_impl> servant(new StructDef_impl());
00383       servant->init(iId.c_str(),i->first.c_str(),iVersion.c_str(),this,iIndex);
00384       servant->recreate(i->second,todo);
00385       todo[servant.get()]=i->second;
00386       servant.release(iOid.c_str());
00387     }
00388     else if("UnionDef"==iClass)
00389     {
00390       Creche<UnionDef_impl> servant(new UnionDef_impl());
00391       servant->init(iId.c_str(),i->first.c_str(),iVersion.c_str(),this,iIndex);
00392       servant->recreate(i->second,todo);
00393       todo[servant.get()]=i->second;
00394       servant.release(iOid.c_str());
00395     }
00396     else if("EnumDef"==iClass)
00397     {
00398       Creche<EnumDef_impl> servant(new EnumDef_impl());
00399       servant->init(iId.c_str(),i->first.c_str(),iVersion.c_str(),this,iIndex);
00400       todo[servant.get()]=i->second;
00401       servant.release(iOid.c_str());
00402     }
00403     else if("AliasDef"==iClass)
00404     {
00405       Creche<AliasDef_impl> servant(new AliasDef_impl());
00406       servant->init(iId.c_str(),i->first.c_str(),iVersion.c_str(),this,iIndex);
00407       todo[servant.get()]=i->second;
00408       servant.release(iOid.c_str());
00409     }
00410     else if("InterfaceDef"==iClass)
00411     {
00412       Creche<InterfaceDef_impl> servant(new InterfaceDef_impl());
00413       servant->init(iId.c_str(),i->first.c_str(),iVersion.c_str(),this,iIndex);
00414       servant->recreate(i->second,todo);
00415       todo[servant.get()]=i->second;
00416       servant.release(iOid.c_str());
00417     }
00418     else if("ExceptionDef"==iClass)
00419     {
00420       Creche<ExceptionDef_impl> servant(new ExceptionDef_impl());
00421       servant->init(iId.c_str(),i->first.c_str(),iVersion.c_str(),this,iIndex);
00422       servant->recreate(i->second,todo);
00423       todo[servant.get()]=i->second;
00424       servant.release(iOid.c_str());
00425     }
00426     else if("AttributeDef"!=iClass && "OperationDef"!=iClass)
00427     {
00428       DB(1,"Container_impl::recreate(): "
00429            "unexpected child class "<<iClass.c_str())
00430     }
00431   } // end for(i)
00432 } // end Container_impl::recreate()
00433 
00434 void Container_impl::outputContents(ostream &os) const
00435 {
00436   for(list<Contained_impl*>::const_iterator i=_contents.begin();
00437       i!=_contents.end();
00438       ++i)
00439   {
00440     (**i).output(os);
00441   }
00442 }
00443 
00444 Container_impl::Container_impl() : _contents()
00445 {
00446   _contents.clear();
00447 }
00448 
00449 void Container_impl::uncheckedDestroy() 
00450 {
00451   for(list<Contained_impl*>::const_iterator i=_contents.begin();
00452       i!=_contents.end();
00453       ++i)
00454   {
00455     (**i).uncheckedDestroy();
00456   }
00457   _contents.clear();
00458 }
00459 
00460 Contained_impl* Container_impl::lookupServant(
00461   const char* searchName,
00462   bool        matchCase
00463 )
00464 {
00465   assert(searchName);
00466   if(!searchName[0])// Empty string
00467       return NULL;
00468 
00469   // Split into: first::theRest
00470   const char* offset =strstr(searchName,"::");
00471   string first(searchName,offset?offset-searchName:strlen(searchName));
00472   string theRest(offset?offset+2:"");
00473 
00474   Contained_impl* result =NULL;
00475 
00476   if(first.empty())
00477   {
00478     result=Repository_impl::inst().lookupServant(theRest.c_str(),matchCase);
00479   }
00480   else
00481   {
00482     list<Contained_impl*>::iterator pos =
00483       find_if(
00484         _contents.begin(),
00485         _contents.end(),
00486         EqualName(first.c_str(),matchCase)
00487       );
00488     if(pos!=_contents.end()) // match found
00489     {
00490       if(theRest.empty())
00491       {
00492         result=*pos;
00493       }
00494       else
00495       {
00496         Container_impl* container =dynamic_cast<Container_impl*>(*pos);
00497         if(container)
00498             result=container->lookupServant(theRest.c_str(),matchCase);
00499       }
00500     }
00501   }
00502   return result;
00503 }
00504 
00505 void Container_impl::addContained(Contained_impl* contained)
00506 {
00507   // Precondition: We know that the contained->name is not already in use by
00508   // this container, either because we've checked for that in
00509   // Contained_impl::name() or because we've set it to "" during a
00510   // Contained_impl::move().
00511 
00512   this->_add_ref(); // Do this now to ensure we aren't destroyed during the call
00513   try
00514   {
00515     // Verify that we don't already contain it.
00516     assert(find_if(_contents.begin(),_contents.end(),
00517                    bind2nd(equal_to<Contained_impl*>(),contained))
00518            ==_contents.end()
00519     );
00520     // Check that we are able to contain the specified type.
00521     if(!canContain(contained->def_kind()))
00522         throw CORBA::BAD_PARAM(
00523           IFELSE_OMNIORB4(omni::BAD_PARAM_TargetIsInvalidContainer,4),
00524           CORBA::COMPLETED_NO
00525         );
00526     // proceed...
00527     if(contained->_index > 0)
00528     {
00529       // we are being reincarnated: Put the it back in the right place.
00530       list<Contained_impl*>::iterator pos=_contents.begin();
00531       while(pos!=_contents.end() && (*pos)->_index < contained->_index)
00532           ++pos;
00533       _contents.insert(pos,contained);
00534     }
00535     else
00536     {
00537       // A newly added object - put it at the end.
00538       contained->_index=(_contents.empty()? 1: 1+_contents.back()->_index);
00539       _contents.push_back(contained);
00540     }
00541   }
00542   catch(...)
00543   {
00544     this->_remove_ref();
00545     throw;
00546   }
00547 }
00548 
00549 void Container_impl::removeContained(Contained_impl* contained)
00550 {
00551   list<Contained_impl*>::iterator pos =
00552     find_if(_contents.begin(),_contents.end(),
00553             bind2nd(equal_to<Contained_impl*>(),contained));
00554   assert(pos!=_contents.end());
00555   _contents.erase(pos);
00556   this->_remove_ref();
00557 }
00558 
00559 bool Container_impl::EqualName::operator()(Contained_impl* c)
00560 {
00561   return test(c->name());
00562 }
00563 
00564 } // end namespace Omniifr

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