ObjectClass.cc

Go to the documentation of this file.
00001 // ----------------------------------------------------------------------------
00002 // CERTI - HLA RunTime Infrastructure
00003 // Copyright (C) 2002-2005  ONERA
00004 //
00005 // This file is part of CERTI-libCERTI
00006 //
00007 // CERTI-libCERTI is free software ; you can redistribute it and/or
00008 // modify it under the terms of the GNU Lesser General Public License
00009 // as published by the Free Software Foundation ; either version 2 of
00010 // the License, or (at your option) any later version.
00011 //
00012 // CERTI-libCERTI is distributed in the hope that it will be useful, but
00013 // WITHOUT ANY WARRANTY ; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00015 // Lesser General Public License for more details.
00016 //
00017 // You should have received a copy of the GNU Lesser General Public
00018 // License along with this program ; if not, write to the Free Software
00019 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00020 // USA
00021 //
00022 // $Id: ObjectClass.cc,v 3.64 2008/12/16 07:08:29 approx Exp $
00023 // ----------------------------------------------------------------------------
00024 
00025 #include  "Object.hh"
00026 #include  "ObjectAttribute.hh"
00027 #include  "ObjectClass.hh"
00028 #include  "ObjectClassAttribute.hh"
00029 #include  "ObjectClassSet.hh"
00030 #include  "ObjectClassBroadcastList.hh"
00031 #include  "NM_Classes.hh"
00032 
00033 #include "SocketTCP.hh"
00034 #include "PrettyDebug.hh"
00035 #include "helper.hh"
00036 #include <sstream>
00037 #include <memory>
00038 
00039 #ifdef _WIN32
00040     #include <windows.h>
00041     #include <algorithm>
00042     #ifdef max
00043         #undef max
00044     #endif
00045 #else
00046     #include <iostream>
00047 #endif
00048 #include <assert.h>
00049 
00050 using std::cout ;
00051 using std::endl ;
00052 using std::list ;
00053 
00054 namespace certi {
00055 
00056 static pdCDebug D("OBJECTCLASS", __FILE__);
00057 static PrettyDebug G("GENDOC",__FILE__);
00058 
00059 // ----------------------------------------------------------------------------
00061 AttributeHandle
00062 ObjectClass::addAttribute(ObjectClassAttribute *theAttribute,
00063                           bool is_inherited)
00064 {
00065     if (theAttribute == NULL)
00066         throw RTIinternalError("Tried to add NULL attribute.");
00067 
00068     theAttribute->setHandle(attributeSet.size() + 1);
00069     theAttribute->server = server ;
00070 
00071     // If the attribute is inherited, it keeps its security level.
00072     // If not, it takes the default security level of the class.
00073     if (!is_inherited)
00074         theAttribute->level = securityLevelId ;
00075 
00076     attributeSet.push_front(theAttribute);
00077 
00078     D.Out(pdProtocol, "ObjectClass %u has a new attribute %u.",
00079           handle, theAttribute->getHandle());
00080 
00081     return theAttribute->getHandle();
00082 }
00083 
00084 // ----------------------------------------------------------------------------
00086 void
00087 ObjectClass::addInheritedClassAttributes(ObjectClass *the_child)
00088 {
00089     // The Attribute List is read backwards to respect the same attribute order
00090     // for the child(Attributes are inserted at the beginning of the list).
00091     ObjectClassAttribute *childAttribute = NULL ;
00092     list<ObjectClassAttribute *>::reverse_iterator a ;
00093     for (a = attributeSet.rbegin(); a != attributeSet.rend(); a++) {
00094         assert((*a) != NULL);
00095 
00096         childAttribute = new ObjectClassAttribute(*a);
00097         assert(childAttribute != NULL);
00098 
00099         D.Out(pdProtocol,
00100               "ObjectClass %u adding new attribute %d to child class %u.",
00101               handle, (*a)->getHandle(), the_child->getHandle());
00102 
00103         the_child->addAttribute(childAttribute);
00104 
00105         if (childAttribute->getHandle() != (*a)->getHandle())
00106             throw RTIinternalError("Error while copying child's attributes.");
00107     }
00108 } /* end of addInheritedClassAttributes */
00109 
00110 // ----------------------------------------------------------------------------
00115 void
00116 ObjectClass::broadcastClassMessage(ObjectClassBroadcastList *ocbList,
00117                    const Object *source)
00118 {
00119     int i, trouve;
00120     G.Out(pdGendoc,"enter ObjectClass::broadcastClassMessage");
00121     // 1. Set ObjectHandle to local class Handle.
00122     ocbList->message->objectClass = handle ;
00123 
00124     G.Out(pdGendoc,"      ObjectClass::broadcastClassMessage handle=%d",handle);
00125 
00126     // 2. Update message attribute list by removing child's attributes.
00127     if ((ocbList->message->getType() == NetworkMessage::REFLECT_ATTRIBUTE_VALUES) ||
00128         (ocbList->message->getType() == NetworkMessage::REQUEST_ATTRIBUTE_OWNERSHIP_ASSUMPTION)) {
00129         int attr = 0 ;
00130         while (attr < ocbList->message->handleArraySize) {
00131             // If the attribute is not in that class, remove it from
00132             // the message.
00133             try {
00134                 getAttribute(ocbList->message->handleArray[attr]);
00135                 attr++ ;
00136             }
00137             catch (AttributeNotDefined &e) {
00138                 ocbList->message->removeAttribute(attr);
00139             }
00140         }
00141     }
00142 
00143     // 3. Add class/attributes subscribers to the list.
00144     switch(ocbList->message->getType()) {
00145       case NetworkMessage::DISCOVER_OBJECT:
00146       case NetworkMessage::REMOVE_OBJECT: {
00147           // For each federate, add it to list if at least one attribute has
00148           // been subscribed.
00149           FederateHandle federate = 0 ;
00150           for (federate = 1 ; federate <= maxSubscriberHandle ; federate++) {
00151               if (isSubscribed(federate) && (federate != ocbList->message->federate)) {
00152                   ocbList->addFederate(federate);
00153               }
00154           }
00155       } break ;
00156 
00157       case NetworkMessage::REFLECT_ATTRIBUTE_VALUES: {
00158           // For each class attribute, update the list be adding federates who
00159           // subscribed to the attribute.
00160           list<ObjectClassAttribute *>::const_iterator a ;
00161           for (a = attributeSet.begin(); a != attributeSet.end(); a++) {
00162               // Do not consider attributes that are not updated
00163               trouve = 0;
00164               for (i=0 ; i< ocbList->message->handleArraySize ; i++) {
00165                   if ((*a)->getHandle() == ocbList->message->handleArray[i])
00166                      trouve = 1;
00167               }
00168               if (trouve) {
00169              ObjectAttribute *attr = source->getAttribute((*a)->getHandle());
00170                  const RTIRegion *update_region = attr->getRegion();
00171              D[pdTrace] << "RAV: attr " << (*a)->getHandle()
00172                 << " / region " << (update_region ? update_region->getHandle() : 0)
00173                 << std::endl ;
00174                  (*a)->updateBroadcastList(ocbList, update_region);
00175               }
00176           }
00177       } break ;
00178 
00179       case NetworkMessage::REQUEST_ATTRIBUTE_OWNERSHIP_ASSUMPTION: {
00180           // For each class attribute, update the list be adding federates who
00181           // subscribed to the attribute.
00182           list<ObjectClassAttribute *>::const_iterator a ;
00183           for (a = attributeSet.begin(); a != attributeSet.end(); a++) {
00184               (*a)->updateBroadcastList(ocbList);
00185           }
00186       } break ;
00187 
00188       default:
00189         throw RTIinternalError("BroadcastClassMsg: Unknown type.");
00190     }
00191 
00192     // 4. Send pending messages.
00193     ocbList->sendPendingMessage(server);
00194     G.Out(pdGendoc,"exit  ObjectClass::broadcastClassMessage");
00195 }
00196 
00197 // ----------------------------------------------------------------------------
00199 void
00200 ObjectClass::sendToFederate(NetworkMessage *msg, FederateHandle theFederate)
00201 {
00202     // Send the message 'msg' to the Federate which Handle is theFederate.
00203     Socket *socket = NULL ;
00204     try {
00205 #ifdef HLA_USES_UDP
00206         socket = server->getSocketLink(theFederate, BEST_EFFORT);
00207 #else
00208         socket = server->getSocketLink(theFederate);
00209 #endif
00210         msg->send(socket,NM_msgBufSend);
00211     }
00212     catch (RTIinternalError &e) {
00213         D.Out(pdExcept,
00214               "Reference to a killed Federate while broadcasting.");
00215     }
00216     catch (NetworkError &e) {
00217         D.Out(pdExcept, "Network error while broadcasting, ignoring.");
00218     }
00219     // BUG: If except = 0, could use Multicast.
00220 }
00221 
00222 // ----------------------------------------------------------------------------
00224 void
00225 ObjectClass::sendToOwners(CDiffusion *diffusionList,
00226                           ObjectHandle theObjectHandle,
00227                           FederateHandle theFederate,
00228                           const char *theTag,
00229                           NetworkMessage::Type type)
00230 {
00231     int nbAttributes = diffusionList->size ;
00232 
00233     FederateHandle toFederate ;
00234     for (int i = 0 ; i < nbAttributes ; i++) {
00235         toFederate = diffusionList->DiffArray[i].federate ;
00236         if (toFederate != 0) {
00237             std::auto_ptr<NetworkMessage> answer(NM_Factory::create(type));
00238             answer->federation = server->federation();
00239             answer->federate = theFederate ;
00240             answer->object = theObjectHandle ;
00241             answer->setLabel(theTag);
00242             answer->handleArray.resize(nbAttributes) ;
00243 
00244             int index = 0 ;
00245             for (int j = i ; j < nbAttributes ; j++) {
00246                 if (diffusionList->DiffArray[j].federate == toFederate) {
00247                     D.Out(pdDebug, "handle : %u",
00248                           diffusionList->DiffArray[j].attribute);
00249                     diffusionList->DiffArray[j].federate = 0 ;
00250                     answer->handleArray[index] = diffusionList
00251                         ->DiffArray[j].attribute ;
00252                     index++ ;
00253                 }
00254             }
00255             answer->handleArraySize = index ;
00256             D.Out(pdDebug, "Envoi message type %u ", type);
00257             sendToFederate(answer.get(), toFederate);
00258         }
00259     }
00260 }
00261 
00262 // ----------------------------------------------------------------------------
00266 void
00267 ObjectClass::checkFederateAccess(FederateHandle the_federate,
00268                                  const char *reason)
00269     throw (SecurityError)
00270 {
00271     D.Out(pdInit, "Beginning of CheckFederateAccess for the federate %d",
00272           the_federate);
00273 
00274     // BUG: Should at least but a line in Audit
00275     if (server == NULL)
00276         return ;
00277 
00278     bool result = server->canFederateAccessData(the_federate, securityLevelId);
00279 
00280     // BUG: Should use Audit.
00281     if (!result) {
00282         cout << "Object Class " << handle << " : SecurityError for federate "
00283              << the_federate << '(' << reason << ")." << endl ;
00284         throw SecurityError("Federate should not access Object Class.");
00285     }
00286 }
00287 
00288 // ----------------------------------------------------------------------------
00289 ObjectClass::ObjectClass(std::string name, ObjectClassHandle handle)
00290     : Named(name), server(NULL), handle(handle), maxSubscriberHandle(0), securityLevelId(PublicLevelID),
00291       superClass(0), subClasses(NULL)
00292 {
00293     subClasses = new ObjectClassSet(NULL);
00294 }
00295 
00296 // ----------------------------------------------------------------------------
00298 ObjectClass::~ObjectClass()
00299 {
00300     // Deleting instances
00301     if (!objectSet.empty())
00302         D.Out(pdError,
00303               "ObjectClass %d : Instances remaining while exiting...", handle);
00304 
00305     // Deleting Class Attributes
00306     while (!attributeSet.empty()) {
00307         delete attributeSet.front();
00308         attributeSet.pop_front();
00309     }
00310     // Deleting subclasses
00311     if (NULL!=subClasses) {
00312         delete subClasses;
00313     }
00314 } /* end of ObjectClass destructor */
00315 
00316 // ----------------------------------------------------------------------------
00317 /* Delete Instance with time.
00318    Delete the object instance 'theObjectHandle', and starts to
00319    broadcast the RemoveObject message. Return a BroadcastList of
00320    Federates, in order to allow our ObjectClassSet to go on with
00321    the message broadcasting, by giving the list to our parent
00322    class.
00323 */
00324 ObjectClassBroadcastList *
00325 ObjectClass::deleteInstance(FederateHandle the_federate,
00326                             ObjectHandle the_object,
00327                 FederationTime theTime,
00328                             std::string the_tag)
00329     throw (DeletePrivilegeNotHeld,
00330            ObjectNotKnown,
00331            RTIinternalError)
00332 {
00333 
00334     // 1. Pre-conditions checking(may throw ObjectNotKnown)
00335     Object *object = getInstanceWithID(the_object);
00336 
00337     // Is the Federate really the Object Owner?(Checked only on RTIG)
00338     if ((server != 0) && (object->getOwner() != the_federate)) {
00339         D.Out(pdExcept, "Delete Object %d: Federate %d not owner.",
00340               the_object, the_federate);
00341         throw DeletePrivilegeNotHeld("");
00342     }
00343 
00344     // 2. Remove Instance from list.
00345     list<Object *>::iterator o ;
00346     for (o = objectSet.begin(); o != objectSet.end(); o++) {
00347         if ((*o)->getHandle() == the_object) {
00348             objectSet.erase(o); // i is dereferenced.
00349             break ;
00350         }
00351     }
00352 
00353     // 3. Prepare and broadcast message.
00354     ObjectClassBroadcastList *ocbList = NULL ;
00355     if (server != NULL) {
00356         D.Out(pdRegister,
00357               "Object %u deleted in class %u, now broadcasting...",
00358               the_object, handle);
00359 
00360         NetworkMessage *answer = NM_Factory::create(NetworkMessage::REMOVE_OBJECT);
00361         answer->federation = server->federation();
00362         answer->federate = the_federate ;
00363         answer->exception = e_NO_EXCEPTION ;
00364         answer->objectClass = handle ; // Class Handle
00365         answer->object = the_object ;
00366 
00367     // with time
00368         answer->setDate(theTime);
00369         answer->setLabel(the_tag);
00370 
00371         ocbList = new ObjectClassBroadcastList(answer, 0);
00372         broadcastClassMessage(ocbList);
00373     }
00374     else {
00375         D.Out(pdRegister,
00376               "Object %u deleted in class %u, no broadcast to do.",
00377               the_object, handle);
00378     }
00379 
00380     // Return the BroadcastList in case it had to be passed to the parent
00381     // class.
00382     return ocbList ;
00383 }
00384 
00385 // ----------------------------------------------------------------------------
00386 /* Delete Instance without time.
00387    Delete the object instance 'theObjectHandle', and starts to
00388    broadcast the RemoveObject message. Return a BroadcastList of
00389    Federates, in order to allow our ObjectClassSet to go on with
00390    the message broadcasting, by giving the list to our parent
00391    class.
00392 */
00393 ObjectClassBroadcastList *
00394 ObjectClass::deleteInstance(FederateHandle the_federate,
00395                             ObjectHandle the_object,
00396                             std::string the_tag)
00397     throw (DeletePrivilegeNotHeld,
00398            ObjectNotKnown,
00399            RTIinternalError)
00400 {
00401     // 1. Pre-conditions checking(may throw ObjectNotKnown)
00402     Object *object = getInstanceWithID(the_object);
00403 
00404     // Is the Federate really the Object Owner?(Checked only on RTIG)
00405     if ((server != 0) && (object->getOwner() != the_federate)) {
00406         D.Out(pdExcept, "Delete Object %d: Federate %d not owner.",
00407               the_object, the_federate);
00408         throw DeletePrivilegeNotHeld("");
00409     }
00410 
00411     // 2. Remove Instance from list.
00412     list<Object *>::iterator o ;
00413     for (o = objectSet.begin(); o != objectSet.end(); o++) {
00414         if ((*o)->getHandle() == the_object) {
00415             objectSet.erase(o); // i is dereferenced.
00416             break ;
00417         }
00418     }
00419 
00420     // 3. Prepare and broadcast message.
00421     ObjectClassBroadcastList *ocbList = NULL ;
00422     if (server != NULL) {
00423         D.Out(pdRegister,
00424               "Object %u deleted in class %u, now broadcasting...",
00425               the_object, handle);
00426 
00427         NetworkMessage *answer = NM_Factory::create(NetworkMessage::REMOVE_OBJECT);
00428         answer->federation = server->federation();
00429         answer->federate = the_federate ;
00430         answer->objectClass = handle ; // Class Handle
00431         answer->object = the_object ;
00432 
00433         // without time
00434 
00435         answer->setLabel(the_tag);
00436 
00437         ocbList = new ObjectClassBroadcastList(answer, 0);
00438         broadcastClassMessage(ocbList);
00439     }
00440     else {
00441         D.Out(pdRegister,
00442               "Object %u deleted in class %u, no broadcast to do.",
00443               the_object, handle);
00444     }
00445 
00446     // Return the BroadcastList in case it had to be passed to the parent
00447     // class.
00448     return ocbList ;
00449 }
00450 
00451 // ----------------------------------------------------------------------------
00453 void ObjectClass::display() const
00454 {
00455     cout << " ObjectClass #" << handle << " \"" << name << "\":" << endl ;
00456 
00457     // Display inheritance
00458     cout << " Parent Class Handle: " << superClass << endl ;
00459     cout << " Security Level: " << securityLevelId << endl ;
00460     cout << " " << subClasses->size() << " Child(s):" << endl ;
00461     cout << " Subclasses handles:" ;
00462     ObjectClassSet::const_iterator i ;
00463     for (i = subClasses->begin(); i != subClasses->end(); ++i) {
00464         cout << " " << i->second->getHandle() << endl;
00465     }
00466 
00467 
00468     // Display Attributes
00469     cout << " " << attributeSet.size() << " Attribute(s):" << endl ;
00470     list<ObjectClassAttribute *>::const_iterator a ;
00471     for (a = attributeSet.begin(); a != attributeSet.end(); a++) {
00472         (*a)->display();
00473     }
00474 
00475     // Display Instances
00476     cout << " " << objectSet.size() << " Instances(s):" << endl ;
00477     list<Object *>::const_iterator o ;
00478     for (o = objectSet.begin(); o != objectSet.end(); o++) {
00479         (*o)->display();
00480     }
00481 }
00482 
00483 // ----------------------------------------------------------------------------
00485 AttributeHandle
00486 ObjectClass::getAttributeHandle(const char *the_name) const
00487     throw (NameNotFound, RTIinternalError)
00488 {
00489     G.Out(pdGendoc,"enter ObjectClass::getAttributeHandle");
00490 
00491     list<ObjectClassAttribute *>::const_iterator a ;
00492     for (a = attributeSet.begin(); a != attributeSet.end(); a++) {
00493         if ((*a)->isNamed(std::string(the_name))) {
00494             G.Out(pdGendoc,"exit  ObjectClass::getAttributeHandle");
00495             return (*a)->getHandle();
00496         }
00497     }
00498 
00499     D.Out(pdExcept, "ObjectClass %u: Attribute \"%s\" not defined.",
00500           handle, the_name);
00501     G.Out(pdGendoc,"exit  ObjectClass::getAttributeHandle on NameNotFound");
00502     throw NameNotFound(the_name);
00503 }
00504 
00505 // ----------------------------------------------------------------------------
00507 const char *
00508 ObjectClass::getAttributeName(AttributeHandle the_handle) const
00509     throw (AttributeNotDefined,
00510            RTIinternalError)
00511 {
00512     return getAttribute(the_handle)->getCName();
00513 }
00514 
00515 
00516 // ----------------------------------------------------------------------------
00521 ObjectClassAttribute *
00522 ObjectClass::getAttribute(AttributeHandle the_handle) const
00523     throw (AttributeNotDefined)
00524 {
00525     list<ObjectClassAttribute *>::const_iterator a ;
00526     for (a = attributeSet.begin(); a != attributeSet.end(); a++) {
00527         if ((*a)->getHandle() == the_handle)
00528             return (*a);
00529     }
00530 
00531     D.Out(pdExcept, "ObjectClass %d: Attribute %d not defined.",
00532           handle, the_handle);
00533 
00534     throw AttributeNotDefined("");
00535 }
00536 
00537 // ----------------------------------------------------------------------------
00539 Object *
00540 ObjectClass::getInstanceWithID(ObjectHandle the_id) const
00541     throw (ObjectNotKnown)
00542 {
00543     std::stringstream msg;
00544 
00545     list<Object *>::const_iterator o ;
00546     for (o = objectSet.begin(); o != objectSet.end(); o++) {
00547         if ((*o)->getHandle() == the_id)
00548             return (*o);
00549     }
00550 
00551     msg << "Could not find ObjectHandle <" << the_id << "> among <"
00552            << objectSet.size() << "> objects of ObjectClass "
00553            << handle;
00554 
00555     D[pdError] << msg.str().c_str() << std::endl ;
00556 
00557     throw ObjectNotKnown(msg.str().c_str());
00558 }
00559 
00560 // ----------------------------------------------------------------------------
00562 bool
00563 ObjectClass::isFederatePublisher(FederateHandle the_federate) const
00564 {
00565     D.Out(pdRegister, "attributeSet.size() = %d.", attributeSet.size());
00566 
00567     list<ObjectClassAttribute *>::const_iterator a ;
00568     for (a = attributeSet.begin(); a != attributeSet.end(); a++) {
00569         if ((*a)->isPublishing(the_federate))
00570             return true ;
00571     }
00572     return false ;
00573 }
00574 
00575 // ----------------------------------------------------------------------------
00581 bool
00582 ObjectClass::isSubscribed(FederateHandle fed) const
00583 {
00584     list<ObjectClassAttribute *>::const_iterator a ;
00585     for (a = attributeSet.begin(); a != attributeSet.end(); a++) {
00586         if ((*a)->isSubscribed(fed))
00587             return true ;
00588     }
00589     return false ;
00590 }
00591 
00592 // ----------------------------------------------------------------------------
00596 bool
00597 ObjectClass::isInstanceInClass(ObjectHandle theID)
00598 {
00599     try {
00600         getInstanceWithID(theID);
00601     }
00602     catch (ObjectNotKnown &e) {
00603         return false ;
00604     }
00605     return true ;
00606 }
00607 
00608 // ----------------------------------------------------------------------------
00610 ObjectClassBroadcastList *
00611 ObjectClass::killFederate(FederateHandle the_federate)
00612     throw ()
00613 {
00614     D.Out(pdRegister, "Object Class %d: Killing Federate %d.",
00615           handle, the_federate);
00616     std::vector <AttributeHandle> liste_vide ;
00617     liste_vide.empty();
00618     try {
00619         // Does federate is publishing something ? (not important)
00620         if (isFederatePublisher(the_federate)) {
00621             publish(the_federate, liste_vide, 0, false);
00622         }
00623 
00624         // Does federate subscribed something ?
00625         // Problem, no removeObject or discover must not be sent to it.
00626         if (isSubscribed(the_federate)) {
00627             unsubscribe(the_federate);
00628         }
00629     }
00630     catch (SecurityError &e) {}
00631 
00632     // Does federate owns instances ?
00633     list<Object *>::iterator o ;
00634     for (o = objectSet.begin(); o != objectSet.end(); o++) {
00635         if ((*o)->getOwner() == the_federate) {
00636             // Return non-NULL to indicate that :
00637             // 1- A RemoveObject message should be broadcasted through parent
00638             // class
00639             // 2- The federate may own another instance, and this function
00640             // must be called again.
00641             // BUG: String \/
00642             return deleteInstance(the_federate, (*o)->getHandle(), "Killed");
00643         }
00644     }
00645 
00646     D.Out(pdRegister, "Object Class %d:Federate %d killed.",
00647           handle, the_federate);
00648 
00649     // Return NULL if the Federate did not own any instance.
00650     return NULL ;
00651 }
00652 
00653 // ----------------------------------------------------------------------------
00655 void
00656 ObjectClass::publish(FederateHandle theFederateHandle,
00657                      std::vector <AttributeHandle> &theAttributeList,
00658                      UShort theListSize,
00659                      bool PubOrUnpub)
00660     throw (AttributeNotDefined,
00661            RTIinternalError,
00662            SecurityError)
00663 {
00664     D.Out(pdInit, "Beginning of Publish for the federate %d",
00665           theFederateHandle);
00666 
00667     // Do all attribute handles exist ? It may throw AttributeNotDefined.
00668     for (UShort index = 0 ; index < theListSize ; index++)
00669         getAttribute(theAttributeList[index]);
00670 
00671     // Check Security Levels
00672     checkFederateAccess(theFederateHandle, "Publish");
00673 
00674     // Reset all previous publish information.
00675     D.Out(pdInit, "ObjectClass %d: Reset publish info of Federate %d.",
00676           handle, theFederateHandle);
00677 
00678     list<ObjectClassAttribute *>::const_iterator a ;
00679     for (a = attributeSet.begin(); a != attributeSet.end(); a++) {
00680         if ((*a)->isPublishing(theFederateHandle))
00681             (*a)->unpublish(theFederateHandle);
00682     }
00683 
00684     // Publish attributes one by one.
00685     ObjectClassAttribute * attribute ;
00686     for (UShort i = 0 ; i < theListSize ; i++) {
00687         D.Out(pdInit, "ObjectClass %d: Federate %d publishes attribute %d.",
00688               handle, theFederateHandle, theAttributeList[i]);
00689         attribute = getAttribute(theAttributeList[i]);
00690     if (PubOrUnpub)
00691         attribute->publish(theFederateHandle);
00692     else
00693         attribute->unpublish(theFederateHandle);
00694     }
00695 }
00696 
00697 // ----------------------------------------------------------------------------
00703 ObjectClassBroadcastList *
00704 ObjectClass::registerObjectInstance(FederateHandle the_federate,
00705                                     Object *the_object,
00706                                     ObjectClassHandle classHandle)
00707     throw (ObjectClassNotPublished,
00708            ObjectAlreadyRegistered,
00709            RTIinternalError)
00710 {
00711     // Pre-conditions checking
00712     if (isInstanceInClass(the_object->getHandle())) {
00713         D.Out(pdExcept, "exception : ObjectAlreadyRegistered.");
00714         throw ObjectAlreadyRegistered(the_object->getName().c_str());
00715     }
00716 
00717     // This condition is only to be checked on the RTIG
00718     if ((server != NULL) && (!isFederatePublisher(the_federate))) {
00719         D.Out(pdExcept, "exception : ObjectClassNotPublished.");
00720         throw ObjectClassNotPublished("");
00721     }
00722 
00723     // Ownership management :
00724     // Copy instance attributes
00725     // Federate only owns attributes it publishes.
00726     ObjectAttribute * oa ;
00727     list<ObjectClassAttribute *>::reverse_iterator a ;
00728     for (a = attributeSet.rbegin(); a != attributeSet.rend(); a++) {
00729     oa = new ObjectAttribute((*a)->getHandle(),
00730                  (*a)->isPublishing(the_federate) ? the_federate : 0,
00731                  *a);
00732 
00733         // privilegeToDelete is owned by federate even not published.
00734         if ((*a)->isNamed("privilegeToDelete")) {
00735             oa->setOwner(the_federate);
00736         }
00737 
00738         the_object->addAttribute(oa);
00739     }
00740 
00741     objectSet.push_front(the_object);
00742     D[pdTrace] << "Added object " << the_object->getHandle() << "/"
00743            << objectSet.size() << " to class " << handle << std::endl ;
00744 
00745     // Prepare and Broadcast message for this class
00746     ObjectClassBroadcastList *ocbList = NULL ;
00747     if (server != NULL) {
00748         D.Out(pdRegister,
00749               "Object %u registered in class %u, now broadcasting...",
00750               the_object->getHandle(), handle);
00751 
00752         NM_Discover_Object *answer = new NM_Discover_Object();
00753         answer->federation  = server->federation();
00754         answer->federate    = the_federate ;
00755         answer->exception   = e_NO_EXCEPTION ;
00756         answer->objectClass = handle ; // Class Handle
00757         answer->object      = the_object->getHandle();
00758         answer->setLabel(the_object->getName().c_str());
00759     // BUG FIXME strange!!
00760     //answer->setDate(0.0);
00761 
00762         ocbList = new ObjectClassBroadcastList(answer, 0);
00763         broadcastClassMessage(ocbList);
00764     }
00765     else {
00766         D.Out(pdRegister,
00767               "Object %u registered in class %u, no broadcast to do.",
00768               the_object->getHandle(), handle);
00769     }
00770 
00771     // Return the BroadcastList in case it had to be passed to the parent
00772     // class.
00773     return ocbList ;
00774 }
00775 
00776 // ----------------------------------------------------------------------------
00786 bool
00787 ObjectClass::sendDiscoverMessages(FederateHandle federate,
00788                                   ObjectClassHandle super_handle)
00789 {
00790     // If we are in a subclass to which the federate is already subscribed,
00791     if ((handle != super_handle) && isSubscribed(federate))
00792         return false ;
00793 
00794     // Else, send message for each object
00795     list<Object *>::const_iterator o ;
00796     for (o = objectSet.begin(); o != objectSet.end(); ++o) {
00797     if ((*o)->getOwner() != federate) {
00798         NM_Discover_Object message;
00799         D.Out(pdInit,
00800           "Sending DiscoverObj to Federate %d for Object %u in class %u ",
00801           federate, (*o)->getHandle(), handle, message.getLabel().c_str());
00802 
00803         message.federation  = server->federation();
00804         message.federate    = federate ;
00805         message.exception   = e_NO_EXCEPTION ;
00806         message.objectClass = super_handle ;
00807         message.object      = (*o)->getHandle();
00808         message.setLabel((*o)->getName().c_str());
00809         //BUG FIXME strange!!
00810         //message.setDate(0.0);
00811 
00812         Socket *socket = NULL ;
00813         try {
00814         socket = server->getSocketLink(federate);
00815         message.send(socket,NM_msgBufSend);
00816         }
00817         catch (RTIinternalError &e) {
00818         D.Out(pdExcept,
00819               "Reference to a killed Federate while sending DO msg.");
00820         }
00821         catch (NetworkError &e) {
00822         D.Out(pdExcept, "Network error while sending DO msg, ignoring.");
00823         }
00824         }
00825     }
00826 
00827     return true ;
00828 }
00829 
00830 // A class' LevelID can only be increased.
00831 void
00832 ObjectClass::setSecurityLevelId(SecurityLevelID new_levelID) throw (SecurityError)
00833 {
00834     if (!server->dominates(new_levelID, securityLevelId))
00835         throw SecurityError("Attempt to lower object class level.");
00836 
00837     securityLevelId = new_levelID ;
00838 }
00839 
00840 // ----------------------------------------------------------------------------
00850 bool
00851 ObjectClass::subscribe(FederateHandle fed,
00852         std::vector <AttributeHandle> &attributes,
00853         int nb_attributes,
00854         const RTIRegion *region)
00855 throw (AttributeNotDefined, RTIinternalError, SecurityError)
00856 {
00857     checkFederateAccess(fed, "Subscribe");
00858 
00859     for (int i = 0 ; i < nb_attributes ; ++i) // Check attributes
00860         getAttribute(attributes[i]);
00861 
00862     if (nb_attributes > 0)
00863         maxSubscriberHandle = std::max(fed, maxSubscriberHandle);
00864 
00865     bool was_subscriber = isSubscribed(fed);
00866 
00867     // FIXME what does this means?
00868     unsubscribe(fed, region);
00869 
00870     D[pdTrace] << "ObjectClass::subscribe" << " : fed " << fed << ", class " << handle
00871     << ", " << nb_attributes << " attributes, region "
00872     << (region ? region->getHandle() : 0) << std::endl ;
00873 
00874     for (int i = 0 ; i < nb_attributes ; ++i) {
00875         getAttribute(attributes[i])->subscribe(fed, region);
00876     }
00877 
00878     return (nb_attributes > 0) && !was_subscriber ;
00879 } /* end of subscribe */
00880 
00881 // ----------------------------------------------------------------------------
00883 ObjectClassBroadcastList *
00884 ObjectClass::updateAttributeValues(FederateHandle the_federate,
00885                                    Object *object,
00886                                    std::vector <AttributeHandle> &the_attributes,
00887                                    std::vector <AttributeValue_t> &the_values,
00888                                    int the_size,
00889                                    FederationTime the_time,
00890                                    const char *the_tag)
00891     throw (ObjectNotKnown,
00892            AttributeNotDefined,
00893            AttributeNotOwned,
00894            RTIinternalError,
00895            InvalidObjectHandle)
00896 {
00897     // Ownership management: Test ownership on each attribute before updating.
00898     ObjectAttribute * oa ;
00899     for (int i = 0 ; i < the_size ; i++) {
00900         oa = object->getAttribute(the_attributes[i]);
00901 
00902         if (oa->getOwner() != the_federate)
00903             throw AttributeNotOwned("");
00904     }
00905 
00906     // Prepare and Broadcast message for this class
00907     ObjectClassBroadcastList *ocbList = NULL ;
00908     if (server != NULL) {
00909         NetworkMessage *answer = NM_Factory::create(NetworkMessage::REFLECT_ATTRIBUTE_VALUES);
00910         answer->federation = server->federation();
00911         answer->federate = the_federate ;
00912         answer->exception = e_NO_EXCEPTION ;
00913         answer->object = object->getHandle();
00914         // with time
00915         answer->setDate(the_time);
00916         answer->setLabel(the_tag);
00917         answer->handleArray.resize(the_size) ;
00918         answer->handleArraySize = the_size ;
00919         answer->sizeValueArray(the_size) ;
00920 
00921         for (int i = 0 ; i < the_size ; i++) {
00922             answer->handleArray[i] = the_attributes[i] ;
00923             answer->valueArray[i] = the_values[i] ;
00924         }
00925 
00926         ocbList = new ObjectClassBroadcastList(answer, attributeSet.size());
00927 
00928         D.Out(pdProtocol,
00929               "Object %u updated in class %u, now broadcasting...",
00930               object->getHandle(), handle);
00931 
00932         broadcastClassMessage(ocbList, object);
00933     }
00934     else {
00935         D.Out(pdExcept,
00936               "UpdateAttributeValues should not be called on the RTIA.");
00937         throw RTIinternalError("UpdateAttributeValues called on the RTIA.");
00938     }
00939 
00940     // Return the BroadcastList in case it had to be passed to the parent
00941     // class.
00942     return ocbList ;
00943 }
00944 
00945 // ----------------------------------------------------------------------------
00947 ObjectClassBroadcastList *
00948 ObjectClass::updateAttributeValues(FederateHandle the_federate,
00949                                    Object *object,
00950                                    std::vector <AttributeHandle> &the_attributes,
00951                                    std::vector <AttributeValue_t> &the_values,
00952                                    int the_size,
00953                                    const char *the_tag)
00954     throw (ObjectNotKnown,
00955            AttributeNotDefined,
00956            AttributeNotOwned,
00957            RTIinternalError,
00958            InvalidObjectHandle)
00959 {
00960     // Ownership management: Test ownership on each attribute before updating.
00961     ObjectAttribute * oa ;
00962     for (int i = 0 ; i < the_size ; i++) {
00963         oa = object->getAttribute(the_attributes[i]);
00964 
00965         if (oa->getOwner() != the_federate)
00966             throw AttributeNotOwned("");
00967     }
00968 
00969     // Prepare and Broadcast message for this class
00970     ObjectClassBroadcastList *ocbList = NULL ;
00971     if (server != NULL) {
00972         NetworkMessage *answer = NM_Factory::create(NetworkMessage::REFLECT_ATTRIBUTE_VALUES) ;
00973         answer->federation = server->federation();
00974         answer->federate = the_federate ;
00975         answer->exception = e_NO_EXCEPTION ;
00976         answer->object = object->getHandle();
00977         // without time
00978 
00979         answer->setLabel(the_tag);
00980 
00981         answer->handleArraySize = the_size ;
00982         answer->handleArray.resize(the_size) ;
00983         answer->sizeValueArray(the_size) ;
00984 
00985         for (int i = 0 ; i < the_size ; i++) {
00986             answer->handleArray[i] = the_attributes[i] ;
00987             answer->valueArray[i] = the_values[i];
00988         }
00989 
00990         ocbList = new ObjectClassBroadcastList(answer, attributeSet.size());
00991 
00992         D.Out(pdProtocol,
00993               "Object %u updated in class %u, now broadcasting...",
00994               object->getHandle(), handle);
00995 
00996         broadcastClassMessage(ocbList, object);
00997     }
00998     else {
00999         D.Out(pdExcept,
01000               "UpdateAttributeValues should not be called on the RTIA.");
01001         throw RTIinternalError("UpdateAttributeValues called on the RTIA.");
01002     }
01003 
01004     // Return the BroadcastList in case it had to be passed to the parent
01005     // class.
01006     return ocbList ;
01007 }
01008 
01009 // ----------------------------------------------------------------------------
01011 ObjectClassBroadcastList * ObjectClass::
01012 negotiatedAttributeOwnershipDivestiture(FederateHandle theFederateHandle,
01013                                         ObjectHandle theObjectHandle,
01014                                         std::vector <AttributeHandle> &theAttributeList,
01015                                         UShort theListSize,
01016                                         const char *theTag)
01017     throw (ObjectNotKnown,
01018            AttributeNotDefined,
01019            AttributeNotOwned,
01020            AttributeAlreadyBeingDivested,
01021            RTIinternalError)
01022 {
01023     // Pre-conditions checking
01024 
01025     // may throw ObjectNotKnown
01026     Object *object = getInstanceWithID(theObjectHandle);
01027 
01028     // Do all attribute handles exist ? It may throw AttributeNotDefined.
01029     for (int index = 0 ; index < theListSize ; index++)
01030         getAttribute(theAttributeList[index]);
01031 
01032     // Does federate owns every attributes.
01033     // Does federate has called NegotiatedAttributeOwnershipDivestiture.
01034     D.Out(pdDebug, "NegotiatedDivestiture Demandeur : %u", theFederateHandle);
01035 
01036     ObjectAttribute * oa ;
01037     ObjectClassAttribute * oca ;
01038     for (int i = 0 ; i < theListSize ; i++) {
01039         oca = getAttribute(theAttributeList[i]);
01040         oa = object->getAttribute(theAttributeList[i]);
01041 
01042         D.Out(pdDebug, "Attribute Name : %s", oca->getName().c_str());
01043         D.Out(pdDebug, "Attribute Handle : %u", oa->getHandle());
01044         D.Out(pdDebug, "Attribute Owner : %u", oa->getOwner());
01045         if (oa->getOwner() != theFederateHandle)
01046             throw AttributeNotOwned("");
01047         if (oa->beingDivested())
01048             throw AttributeAlreadyBeingDivested("");
01049     }
01050 
01051     int compteur_acquisition = 0 ;
01052     int compteur_assumption = 0 ;
01053     int compteur_divestiture = 0 ;
01054     ObjectClassBroadcastList *List = NULL ;
01055     FederateHandle NewOwner ;
01056 
01057     if (server != NULL) {
01058         NetworkMessage *AnswerAssumption = NM_Factory::create(NetworkMessage::REQUEST_ATTRIBUTE_OWNERSHIP_ASSUMPTION) ;
01059         NM_Attribute_Ownership_Divestiture_Notification AnswerDivestiture;
01060 
01061         AnswerAssumption->handleArraySize = theListSize ;
01062         AnswerAssumption->handleArray.resize(theListSize) ;
01063 
01064         // Maximum size
01065         AnswerDivestiture.handleArray.resize(theListSize) ;
01066 
01067         CDiffusion diffusionAcquisition;
01068 
01069         ObjectAttribute * oa ;
01070         ObjectClassAttribute * oca ;
01071         for (int i = 0 ; i < theListSize ; i++) {
01072             oa = object->getAttribute(theAttributeList[i]);
01073 
01074             if (oa->hasCandidates()) {
01075                 // An attributeOwnershipAcquisition is on the way
01076                 // with this attribute.
01077 
01078                 // Le demandeur le plus recent devient proprietaire
01079                 NewOwner = oa->getCandidate(1);
01080 
01081                 oa->setOwner(NewOwner);
01082 
01083                 // On le supprime de la liste des demandeurs
01084                 oa->removeCandidate(NewOwner);
01085 
01086                 // On reinitialise divesting
01087                 oa->setDivesting(false);
01088 
01089                 diffusionAcquisition.DiffArray[compteur_acquisition]
01090                     .federate = NewOwner ;
01091                 diffusionAcquisition.DiffArray[compteur_acquisition]
01092                     .attribute = oa->getHandle();
01093                 compteur_acquisition++ ;
01094 
01095                 AnswerDivestiture.handleArray[compteur_divestiture]
01096                     = theAttributeList[i] ;
01097                 compteur_divestiture++ ;
01098 
01099                 if (oca->isNamed("privilegeToDelete")) {
01100                     object->setOwner(NewOwner);
01101                 }
01102             }
01103             else {
01104                 AnswerAssumption->handleArray[compteur_assumption]
01105                     = theAttributeList[i] ;
01106                 oa->setDivesting(true);
01107                 compteur_assumption++ ;
01108             }
01109         }
01110 
01111         if (compteur_acquisition != 0) {
01112             diffusionAcquisition.size = compteur_acquisition ;
01113             sendToOwners(&diffusionAcquisition, theObjectHandle,
01114                          theFederateHandle, theTag,
01115                          NetworkMessage::ATTRIBUTE_OWNERSHIP_ACQUISITION_NOTIFICATION);
01116         }
01117 
01118         if (compteur_divestiture !=0) {
01119             AnswerDivestiture.federation = server->federation();
01120             AnswerDivestiture.federate = theFederateHandle ;
01121             AnswerDivestiture.object = theObjectHandle ;
01122             AnswerDivestiture.setLabel(std::string(""));
01123             AnswerDivestiture.handleArraySize = compteur_divestiture ;
01124 
01125             sendToFederate(&AnswerDivestiture, theFederateHandle);
01126         }
01127 
01128         if (compteur_assumption !=0) {
01129             AnswerAssumption->federation = server->federation();
01130             AnswerAssumption->federate = theFederateHandle ;
01131             AnswerAssumption->exception = e_NO_EXCEPTION ;
01132             AnswerAssumption->object = theObjectHandle ;
01133             AnswerAssumption->setLabel(theTag);
01134             AnswerAssumption->handleArraySize = compteur_assumption ;
01135 
01136             List = new ObjectClassBroadcastList(AnswerAssumption,
01137                                                 attributeSet.size());
01138 
01139             D.Out(pdProtocol,
01140                   "Object %u divestiture in class %u, now broadcasting...",
01141                   theObjectHandle, handle);
01142             broadcastClassMessage(List);
01143         }
01144         else
01145             delete AnswerAssumption ;
01146     }
01147     else {
01148         D.Out(pdExcept,
01149               "NegotiatedAttributeOwnershipDivestiture should not "
01150               "be called on the RTIA.");
01151         throw RTIinternalError("NegotiatedAttributeOwnershipDivestiture "
01152                                "called on the RTIA.");
01153     }
01154 
01155     // Return the BroadcastList in case it had to be passed to the parent
01156     // class.
01157     return List ;
01158 }
01159 
01160 // ----------------------------------------------------------------------------
01162 void ObjectClass::
01163 attributeOwnershipAcquisitionIfAvailable(FederateHandle the_federate,
01164                                          ObjectHandle the_object,
01165                                          std::vector <AttributeHandle> &the_attributes,
01166                                          UShort theListSize)
01167     throw (ObjectNotKnown,
01168            ObjectClassNotPublished,
01169            AttributeNotDefined,
01170            AttributeNotPublished,
01171            FederateOwnsAttributes,
01172            AttributeAlreadyBeingAcquired,
01173            RTIinternalError)
01174 {
01175     //It may throw ObjectNotKnown.
01176     Object *object = getInstanceWithID(the_object);
01177 
01178     // Do all attribute handles exist ? It may throw AttributeNotDefined.
01179     for (int index = 0 ; index < theListSize ; index++) {
01180         getAttribute(the_attributes[index]);
01181     }
01182 
01183     if (server) {
01184         // Federate must publish the class.
01185         if (!isFederatePublisher(the_federate)) {
01186             D.Out(pdExcept, "exception : ObjectClassNotPublished.");
01187             throw ObjectClassNotPublished("");
01188         }
01189 
01190         //rem attributeSet.size()=attributeState.size()
01191         ObjectAttribute * oa ;
01192         ObjectClassAttribute * oca ;
01193         for (int i = 0 ; i < theListSize ; i++) {
01194             oca = getAttribute(the_attributes[i]);
01195             oa = object->getAttribute(the_attributes[i]);
01196 
01197             // The federate has to publish attributes he desire to
01198             // acquire.
01199             if (!oca->isPublishing(the_federate) &&
01200                 (!oca->isNamed("privilegeToDelete")))
01201                 throw AttributeNotPublished("");
01202             // Does federate already owns some attributes.
01203             if (oa->getOwner() == the_federate)
01204                 throw FederateOwnsAttributes("");
01205             // Does federate is on the way to acquire something.
01206             if (oa->isCandidate(the_federate))
01207                 throw AttributeAlreadyBeingAcquired("");
01208         }
01209 
01210         NetworkMessage *Answer_notification = NM_Factory::create(NetworkMessage::ATTRIBUTE_OWNERSHIP_ACQUISITION_NOTIFICATION);
01211         Answer_notification->federation = server->federation();
01212         Answer_notification->federate = the_federate ;
01213         Answer_notification->exception = e_NO_EXCEPTION ;
01214         Answer_notification->object = the_object ;
01215         Answer_notification->handleArray.resize(theListSize) ;
01216 
01217         NetworkMessage *Answer_unavailable = NM_Factory::create(NetworkMessage::ATTRIBUTE_OWNERSHIP_UNAVAILABLE) ;
01218         Answer_unavailable->federation = server->federation();
01219         Answer_unavailable->federate = the_federate ;
01220         Answer_unavailable->exception = e_NO_EXCEPTION ;
01221         Answer_unavailable->object = the_object ;
01222         Answer_unavailable->handleArray.resize(theListSize) ;
01223 
01224         CDiffusion *diffusionDivestiture = new CDiffusion();
01225 
01226         //
01227         //Ce service ne doit pas ajouter le federe demandeur a la liste
01228         //des candidats!!!
01229         //
01230         int compteur_unavailable = 0 ;
01231         int compteur_notification = 0 ;
01232         int compteur_divestiture = 0 ;
01233         FederateHandle oldOwner ;
01234 
01235         for (int i = 0 ; i < theListSize ; i++) {
01236             oca = getAttribute(the_attributes[i]);
01237             oa = object->getAttribute(the_attributes[i]);
01238 
01239             oldOwner = oa->getOwner();
01240             if ((oldOwner == 0) || (oa->beingDivested())) {
01241                 //Cet attribut est libre ou offert par son proprietaire
01242                 //S'il est offert
01243                 if (oa->beingDivested()) {
01244                     diffusionDivestiture->DiffArray[compteur_divestiture].federate
01245                         = oldOwner ;
01246                     diffusionDivestiture->DiffArray[compteur_divestiture].attribute
01247                         = oa->getHandle();
01248                     compteur_divestiture++ ;
01249                 }
01250                 //Qu'il soit offert ou libre
01251                 Answer_notification->handleArray[compteur_notification]
01252                     = the_attributes[i] ;
01253                 oa->setOwner(the_federate);
01254                 oa->setDivesting(false);
01255                 compteur_notification++ ;
01256                 //object->Owner reste le champ de reference
01257                 //pour le privilegeToDelete
01258                 if (oca->isNamed("privilegeToDelete"))
01259                     object->setOwner(the_federate);
01260             }
01261             else {
01262                 //Cet attribut n'est pas disponible!!!
01263                 Answer_unavailable->handleArray[compteur_unavailable]
01264                     = the_attributes[i] ;
01265                 oa->addCandidate(the_federate);
01266                 compteur_unavailable++ ;
01267             }
01268         }
01269 
01270         if (compteur_notification != 0) {
01271             Answer_notification->handleArraySize = compteur_notification ;
01272             sendToFederate(Answer_notification, the_federate);
01273         }
01274         else
01275             delete Answer_notification ;
01276 
01277         D.Out(pdDebug,
01278               "Debut traitement : send divestiture notification message");
01279 
01280         if (compteur_divestiture != 0) {
01281             diffusionDivestiture->size =compteur_divestiture ;
01282             sendToOwners(diffusionDivestiture, the_object,
01283                          the_federate, "\0",
01284                          NetworkMessage::ATTRIBUTE_OWNERSHIP_DIVESTITURE_NOTIFICATION);
01285         }
01286         delete diffusionDivestiture ;
01287 
01288         if (compteur_unavailable != 0) {
01289             Answer_unavailable->handleArraySize = compteur_unavailable ;
01290             sendToFederate(Answer_unavailable, the_federate);
01291         }
01292         else
01293             delete Answer_unavailable ;
01294     }
01295     else {
01296         D.Out(pdExcept, "AttributeOwnershipAcquisitionIfAvailable should not "
01297               "be called on the RTIA.");
01298         throw RTIinternalError("AttributeOwnershipAcquisitionIfAvailable "
01299                                "called on the RTIA.");
01300     }
01301 }
01302 
01303 // ----------------------------------------------------------------------------
01305 ObjectClassBroadcastList * ObjectClass::
01306 unconditionalAttributeOwnershipDivestiture(FederateHandle theFederateHandle,
01307                                            ObjectHandle theObjectHandle,
01308                                            std::vector <AttributeHandle> &theAttributeList,
01309                                            UShort theListSize)
01310     throw (ObjectNotKnown,
01311            AttributeNotDefined,
01312            AttributeNotOwned,
01313            RTIinternalError)
01314 {
01315     // Pre-conditions checking
01316 
01317     // may throw ObjectNotKnown
01318     Object *object = getInstanceWithID(theObjectHandle);
01319 
01320     // Do all attribute handles exist ? It may throw AttributeNotDefined.
01321     for (int index = 0 ; index < theListSize ; index++)
01322         getAttribute(theAttributeList[index]);
01323 
01324     //Le federe est-il proprietaire de tous les attributs
01325     ObjectAttribute * oa ;
01326     for (int i = 0 ; i < theListSize ; i++) {
01327         oa = object->getAttribute(theAttributeList[i]);
01328 
01329         if (oa->getOwner() != theFederateHandle)
01330             throw AttributeNotOwned("");
01331     }
01332 
01333     int compteur_assumption = 0 ;
01334     int compteur_acquisition = 0 ;
01335     NM_Request_Attribute_Ownership_Assumption *AnswerAssumption = NULL ;
01336     ObjectClassBroadcastList *List = NULL ;
01337     FederateHandle NewOwner ;
01338 
01339     if (server != NULL) {
01340         AnswerAssumption = new NM_Request_Attribute_Ownership_Assumption();
01341         AnswerAssumption->handleArraySize = theListSize ;
01342         AnswerAssumption->handleArray.resize(theListSize) ;
01343         CDiffusion *diffusionAcquisition = new CDiffusion();
01344 
01345         ObjectAttribute * oa ;
01346         ObjectClassAttribute * oca ;
01347         for (int i = 0 ; i < theListSize ; i++) {
01348             oca = getAttribute(theAttributeList[i]);
01349             oa = object->getAttribute(theAttributeList[i]);
01350 
01351             if (oa->hasCandidates()) {
01352                 // An attributeOwnershipAcquisition is on the way
01353                 // on this attribute.
01354 
01355                 // Le demandeur le plus recent devient proprietaire
01356                 NewOwner = oa->getCandidate(1);
01357 
01358                 oa->setOwner(NewOwner);
01359 
01360                 // We remove it from candidate list.
01361                 oa->removeCandidate(NewOwner);
01362 
01363                 // We reinitialize divesting.
01364                 oa->setDivesting(false);
01365 
01366                 diffusionAcquisition->DiffArray[compteur_acquisition]
01367                     .federate = NewOwner ;
01368                 diffusionAcquisition->DiffArray[compteur_acquisition]
01369                     .attribute = oa->getHandle();
01370                 compteur_acquisition++ ;
01371 
01372                 if (oca->isNamed("privilegeToDelete")) {
01373                     object->setOwner(NewOwner);
01374                 }
01375             }
01376             else {
01377                 AnswerAssumption->handleArray[compteur_assumption] =
01378                     theAttributeList[i] ;
01379                 oa->setOwner(0);
01380                 oa->setDivesting(false);
01381                 compteur_assumption++ ;
01382             }
01383         }
01384 
01385         if (compteur_assumption != 0) {
01386             AnswerAssumption->federation = server->federation();
01387             AnswerAssumption->federate = theFederateHandle ;
01388             AnswerAssumption->exception = e_NO_EXCEPTION ;
01389             AnswerAssumption->object = theObjectHandle ;
01390             AnswerAssumption->setLabel(std::string(""));
01391             AnswerAssumption->handleArraySize = compteur_assumption ;
01392 
01393             List = new ObjectClassBroadcastList(AnswerAssumption,
01394                                                 attributeSet.size());
01395 
01396             D.Out(pdProtocol,
01397                   "Object %u updated in class %u, now broadcasting...",
01398                   theObjectHandle, handle);
01399 
01400             broadcastClassMessage(List);
01401         }
01402         else
01403             delete AnswerAssumption ;
01404 
01405         if (compteur_acquisition != 0) {
01406             diffusionAcquisition->size =compteur_acquisition ;
01407             sendToOwners(diffusionAcquisition, theObjectHandle,
01408                          theFederateHandle, "\0",
01409                          NetworkMessage::ATTRIBUTE_OWNERSHIP_ACQUISITION_NOTIFICATION);
01410         }
01411         delete diffusionAcquisition ;
01412     }
01413     else {
01414         D.Out(pdExcept, "UnconditionalAttributeOwnershipDivestiture should "
01415               "not be called on the RTIA.");
01416         throw RTIinternalError("UnconditionalAttributeOwnershipDivestiture "
01417                                "called on the RTIA.");
01418     }
01419 
01420     // Return the BroadcastList in case it had to be passed to the parent
01421     // class.
01422     return List ;
01423 }
01424 
01425 // ----------------------------------------------------------------------------
01427 void
01428 ObjectClass::attributeOwnershipAcquisition(FederateHandle theFederateHandle,
01429                                            ObjectHandle theObjectHandle,
01430                                            std::vector <AttributeHandle> &theAttributeList,
01431                                            UShort theListSize,
01432                                            const char *theTag)
01433     throw (ObjectNotKnown,
01434            ObjectClassNotPublished,
01435            AttributeNotDefined,
01436            AttributeNotPublished,
01437            FederateOwnsAttributes,
01438            RTIinternalError)
01439 {
01440     //Les v�rifications des conditions doivent �tre faites avant
01441     //toute modification!!!
01442 
01443     // Pre-conditions checking
01444 
01445     // may throw ObjectNotKnown
01446     Object *object = getInstanceWithID(theObjectHandle);
01447 
01448     ObjectAttribute * oa ;
01449     ObjectClassAttribute * oca ;
01450     for (int i = 0 ; i < theListSize ; i++) {
01451         // Do all attribute handles exist ? It may throw AttributeNotDefined.
01452         oca = getAttribute(theAttributeList[i]);
01453         oa = object->getAttribute(theAttributeList[i]);
01454 
01455         //Le f�d�r� est-il d�j� propri�taire de certains attributs
01456         if (oa->getOwner() == theFederateHandle)
01457             throw FederateOwnsAttributes("");
01458         //Le f�d�r� publie-t-il les attributs
01459         if (!oca->isPublishing(theFederateHandle) &&
01460             (!oca->isNamed("privilegeToDelete")))
01461             throw AttributeNotPublished("");
01462     }
01463 
01464     int compteur_notification = 0 ;
01465     int compteur_divestiture = 0 ;
01466     int compteur_release = 0 ;
01467     FederateHandle oldOwner ;
01468     if (server != NULL) {
01469         //Le f�d�r� doit publier la classe
01470         if (!isFederatePublisher(theFederateHandle)) {
01471             D.Out(pdExcept, "exception : ObjectClassNotPublished.");
01472             throw ObjectClassNotPublished("");
01473         }
01474 
01475         NetworkMessage *AnswerNotification = NM_Factory::create(NetworkMessage::ATTRIBUTE_OWNERSHIP_ACQUISITION_NOTIFICATION);
01476 
01477         AnswerNotification->federation = server->federation();
01478         AnswerNotification->federate = theFederateHandle ;
01479         AnswerNotification->exception = e_NO_EXCEPTION ;
01480         AnswerNotification->object = theObjectHandle ;
01481         AnswerNotification->handleArray.resize(theListSize) ;
01482 
01483         CDiffusion *diffusionDivestiture = new CDiffusion();
01484 
01485         CDiffusion *diffusionRelease = new CDiffusion();
01486 
01487         ObjectAttribute * oa ;
01488         ObjectClassAttribute * oca ;
01489         for (int i = 0 ; i < theListSize ; i++) {
01490             oca = getAttribute(theAttributeList[i]);
01491             oa = object->getAttribute(theAttributeList[i]);
01492 
01493             oldOwner = oa->getOwner();
01494             if ((oldOwner == 0) || (oa->beingDivested())) {
01495                 //Cet attribut est libre ou offert par son propri�taire s'il est offert
01496                 if (oa->beingDivested()) {
01497                     diffusionDivestiture->DiffArray[compteur_divestiture].federate =
01498                         oldOwner ;
01499                     diffusionDivestiture->DiffArray[compteur_divestiture].attribute =
01500                         oa->getHandle();
01501                     compteur_divestiture++ ;
01502                 }
01503                 //Qu'il soit offert ou libre
01504                 if (oa->isCandidate(theFederateHandle) != 0)
01505                     oa->removeCandidate(theFederateHandle);
01506                 AnswerNotification->handleArray[compteur_notification]
01507                     = theAttributeList[i] ;
01508                 oa->setOwner(theFederateHandle);
01509                 oa->setDivesting(false);
01510                 compteur_notification++ ;
01511 
01512                 // object->Owner reste le champ de r�f�rence pour
01513                 // le privilegeToDelete
01514                 if (oca->isNamed("privilegeToDelete"))
01515                     object->setOwner(theFederateHandle);
01516             }
01517             else {
01518                 diffusionRelease->DiffArray[compteur_release].federate = oldOwner ;
01519                 diffusionRelease->DiffArray[compteur_release].attribute =
01520                     oa->getHandle();
01521                 compteur_release++ ;
01522 
01523                 //On l'enl�ve de la liste des demandeurs s'il y �tait
01524                 oa->removeCandidate(theFederateHandle);
01525 
01526                 //pour le rajouter en 1ere position
01527                 oa->addCandidate(theFederateHandle);
01528             }
01529         }
01530 
01531         if (compteur_notification != 0) {
01532             AnswerNotification->handleArraySize = compteur_notification ;
01533             sendToFederate(AnswerNotification, theFederateHandle);
01534         }
01535         else
01536             delete AnswerNotification ;
01537 
01538         if (compteur_divestiture != 0) {
01539             diffusionDivestiture->size =compteur_divestiture ;
01540             sendToOwners(diffusionDivestiture, theObjectHandle,
01541                          theFederateHandle, "\0",
01542                          NetworkMessage::ATTRIBUTE_OWNERSHIP_DIVESTITURE_NOTIFICATION);
01543         }
01544         delete diffusionDivestiture ;
01545 
01546         if (compteur_release != 0) {
01547             diffusionRelease->size =compteur_release ;
01548             sendToOwners(diffusionRelease, theObjectHandle, theFederateHandle,
01549                          theTag, NetworkMessage::REQUEST_ATTRIBUTE_OWNERSHIP_RELEASE);
01550         }
01551         delete diffusionRelease ;
01552     }
01553     else {
01554         D.Out(pdExcept,
01555               "AttributeOwnershipAcquisition should not be called "
01556               "on the RTIA.");
01557         throw RTIinternalError("AttributeOwnershipAcquisition called "
01558                                "on the RTIA");
01559     }
01560 }
01561 
01562 // ----------------------------------------------------------------------------
01564 AttributeHandleSet *
01565 ObjectClass::
01566 attributeOwnershipReleaseResponse(FederateHandle the_federate,
01567                                   ObjectHandle the_object,
01568                                   std::vector <AttributeHandle> &the_attributes,
01569                                   UShort the_size)
01570     throw (ObjectNotKnown,
01571            AttributeNotDefined,
01572            AttributeNotOwned,
01573            FederateWasNotAskedToReleaseAttribute,
01574            RTIinternalError)
01575 {
01576     // Pre-conditions checking
01577 
01578     // may throw ObjectNotKnown
01579     Object *object = getInstanceWithID(the_object);
01580 
01581     // Do all attribute handles exist ? It may throw AttributeNotDefined.
01582     for (int index = 0 ; index < the_size ; index++) {
01583         getAttribute(the_attributes[index]);
01584     }
01585 
01586     //Le f�d�r� est-il propri�taire de tous les attributs
01587     //Y a-t-il des acqu�reurs pour les attributs
01588     ObjectAttribute * oa ;
01589     for (int i = 0 ; i < the_size ; i++) {
01590         oa = object->getAttribute(the_attributes[i]);
01591 
01592         if (oa->getOwner() != the_federate) {
01593             throw AttributeNotOwned("");
01594         }
01595         if (!oa->hasCandidates()) {
01596             throw FederateWasNotAskedToReleaseAttribute("");
01597         }
01598     }
01599 
01600     int compteur_acquisition = 0 ;
01601     FederateHandle newOwner ;
01602     AttributeHandleSet *theAttribute ;
01603     if (server != NULL) {
01604         CDiffusion *diffusionAcquisition = new CDiffusion();
01605 
01606         theAttribute = new AttributeHandleSet(the_size);
01607 
01608         ObjectClassAttribute * oca ;
01609         for (int i = 0 ; i < the_size ; i++) {
01610             oca = getAttribute(the_attributes[i]);
01611             oa = object->getAttribute(the_attributes[i]);
01612 
01613             //Le demandeur le plus r�cent devient propri�taire
01614             newOwner = oa->getCandidate(1);
01615 
01616             oa->setOwner(newOwner);
01617 
01618             //On le supprime de la liste des demandeurs
01619             oa->removeCandidate(newOwner);
01620 
01621             //On r�initialise divesting
01622             oa->setDivesting(false);
01623 
01624             diffusionAcquisition->DiffArray[compteur_acquisition].federate = newOwner ;
01625             diffusionAcquisition->DiffArray[compteur_acquisition].attribute =
01626                 oa->getHandle();
01627             compteur_acquisition++ ;
01628             theAttribute->add(oa->getHandle());
01629 
01630             D.Out(pdDebug, "Acquisition handle %u compteur %u",
01631                   the_attributes[i], compteur_acquisition);
01632 
01633             if (oca->isNamed("privilegeToDelete"))
01634                 object->setOwner(newOwner);
01635         }
01636 
01637         if (compteur_acquisition != 0) {
01638             diffusionAcquisition->size =compteur_acquisition ;
01639             sendToOwners(diffusionAcquisition, the_object, the_federate, "\0",
01640                          NetworkMessage::ATTRIBUTE_OWNERSHIP_ACQUISITION_NOTIFICATION);
01641         }
01642         delete diffusionAcquisition ;
01643     }
01644     else {
01645         D.Out(pdExcept, "NegotiatedAttributeOwnershipDivestiture should not "
01646               "be called on the RTIA.");
01647         throw RTIinternalError("NegotiatedAttributeOwnershipDivestiture called"
01648                                " on the RTIA.");
01649     }
01650 
01651     return(theAttribute);
01652 }
01653 
01654 // ----------------------------------------------------------------------------
01656 void
01657 ObjectClass::
01658 cancelAttributeOwnershipAcquisition(FederateHandle federate_handle,
01659                                     ObjectHandle object_handle,
01660                                     std::vector <AttributeHandle> &attribute_list,
01661                                     UShort list_size)
01662     throw (ObjectNotKnown,
01663            AttributeNotDefined,
01664            AttributeAlreadyOwned,
01665            AttributeAcquisitionWasNotRequested,
01666            RTIinternalError)
01667 {
01668     // Pre-conditions checking
01669 
01670     //It may throw ObjectNotKnown.
01671     Object *object = getInstanceWithID(object_handle);
01672 
01673     // Do all attribute handles exist ? It may throw AttributeNotDefined.
01674     for (int index = 0 ; index < list_size ; index++)
01675         getAttribute(attribute_list[index]);
01676 
01677     for (int i = 0 ; i < list_size ; i++)
01678         D.Out(pdDebug, "CancelAcquisition Object %u Attribute %u ",
01679               object_handle, attribute_list[i]);
01680 
01681     if (server != NULL) {
01682         //rem attributeSet.size()=attributeState.size()
01683         ObjectAttribute * oa ;
01684         ObjectClassAttribute * oca ;
01685 
01686         for (int i = 0 ; i < list_size ; i++) {
01687             oca = getAttribute(attribute_list[i]);
01688             oa = object->getAttribute(attribute_list[i]);
01689 
01690             D.Out(pdDebug, "Attribut %u Owner %u", attribute_list[i], oa->getOwner());
01691             // Does federate is already owning some attributes ?
01692             if (oa->getOwner() == federate_handle)
01693                 throw AttributeAlreadyOwned("");
01694             // Does federate is already doing an acquisition ?
01695             if (oa->isCandidate(federate_handle) == 0)
01696                 throw AttributeAcquisitionWasNotRequested("");
01697         }
01698 
01699         NetworkMessage *answer_confirmation = NM_Factory::create(NetworkMessage::CONFIRM_ATTRIBUTE_OWNERSHIP_ACQUISITION_CANCELLATION);
01700         answer_confirmation->federation = server->federation();
01701         answer_confirmation->federate = federate_handle ;
01702         answer_confirmation->exception = e_NO_EXCEPTION ;
01703         answer_confirmation->object = object_handle ;
01704         answer_confirmation->handleArray.resize(list_size) ;
01705 
01706         int compteur_confirmation = 0 ;
01707         for (int i = 0 ; i < list_size ; i++) {
01708             oa = object->getAttribute(attribute_list[i]);
01709 
01710             answer_confirmation->handleArray[compteur_confirmation] = attribute_list[i] ;
01711 
01712             // We remove federate from candidates.
01713             oa->removeCandidate(federate_handle);
01714             D.Out(pdDebug, "Adding federate %u to attribute %u object %u",
01715                   federate_handle, attribute_list[i], object_handle);
01716             compteur_confirmation++ ;
01717         }
01718 
01719         if (compteur_confirmation != 0) {
01720             answer_confirmation->handleArraySize = compteur_confirmation ;
01721             sendToFederate(answer_confirmation, federate_handle);
01722         }
01723         else
01724             delete answer_confirmation ;
01725     }
01726     else {
01727         D.Out(pdExcept, "CancelAttributeOwnershipAcquisition should not "
01728               "be called on the RTIA.");
01729         throw RTIinternalError("CancelAttributeOwnershipAcquisition called "
01730                                "on the RTIA.");
01731     }
01732 }
01733 
01734 // ----------------------------------------------------------------------------
01735 ObjectClassHandle
01736 ObjectClass::getHandle() const
01737 {
01738     return handle ;
01739 }
01740 
01741 // ----------------------------------------------------------------------------
01744 void
01745 ObjectClass::unsubscribe(FederateHandle fed, const RTIRegion *region)
01746 {
01747     D[pdTrace] << "ObjectClass::unsubscribe" << ": fed " << fed << ", region "
01748            << (region ? region->getHandle() : 0) << std::endl ;
01749 
01750     list<ObjectClassAttribute *>::iterator i ;
01751     for (i = attributeSet.begin(); i != attributeSet.end(); ++i) {
01752     if ((*i)->isSubscribed(fed, region)) {
01753         (*i)->unsubscribe(fed, region);
01754     }
01755     }
01756 }
01757 
01758 // ----------------------------------------------------------------------------
01761 void
01762 ObjectClass::unsubscribe(FederateHandle fed)
01763 {
01764     list<ObjectClassAttribute *>::iterator i ;
01765     for (i = attributeSet.begin(); i != attributeSet.end(); ++i) {
01766     if ((*i)->isSubscribed(fed)) {
01767         (*i)->unsubscribe(fed);
01768     }
01769     }
01770 } /* end of unsubscribe */
01771 
01772 void
01773 ObjectClass::addSubClass(ObjectClass *child) {
01774 
01775     /* build parent-child relationship */
01776     /* add child as subclass of parent */
01777     subClasses->addClass(child,NULL);
01778     /* link child to parent */
01779     child->superClass = handle;
01780     /* forward inherited properties to child */
01781     /* Add Object Class Attribute */
01782     addInheritedClassAttributes(child);
01783     /* security server is the same for child */
01784     child->server = server;
01785     /* inherit security Level */
01786     child->setSecurityLevelId(securityLevelId);
01787 
01788 } /* end of addChild */
01789 
01790 // ----------------------------------------------------------------------------
01795 void
01796 ObjectClass::recursiveDiscovering(FederateHandle federate,
01797                   ObjectClassHandle subscription)
01798     throw (ObjectClassNotDefined)
01799 {
01800     D[pdInit] << "Recursive Discovering on class " << handle
01801           << " for Federate " << federate << "." << std::endl ;
01802 
01803     bool go_deeper = sendDiscoverMessages(federate, subscription);
01804 
01805     if (go_deeper) {
01806         ObjectClassSet::const_iterator i ;
01807         for (i = subClasses->begin(); i != subClasses->end(); ++i) {
01808             i->second->recursiveDiscovering(federate, subscription);
01809         }
01810     }
01811 }
01812 
01813 // ----------------------------------------------------------------------------
01818 // void
01819 // ObjectClass::apply(Visitor &v)
01820 // {
01821 //     bool go_deeper = v.execute(*this);
01822 
01823 //     if (go_deeper) {
01824 //         list<ObjectClass *>::const_iterator i ;
01825 //         for (i = subClasses.begin(); i != subClasses.end(); ++i) {
01826 //             (*i)->apply(v);
01827 //         }
01828 //     }
01829 // }
01830 
01831 ObjectClass::AttributeList_t
01832 ObjectClass::getAttributeList(void) {
01833         return attributeSet;
01834 }
01835 
01836 } // namespace certi
01837 
01838 // $Id: ObjectClass.cc,v 3.64 2008/12/16 07:08:29 approx Exp $

Generated on Thu Apr 30 15:53:49 2009 for CERTIDeveloperDocumentation by doxygen 1.5.5