00001 #include "Blackboard.h"
00002 #include <assert.h>
00003
00004 Define_Module(Blackboard);
00005
00006 std::ostream& operator<<(std::ostream& os, const Blackboard::SubscriberVector& v)
00007 {
00008 os << v.size() << " client(s) ";
00009 Blackboard::SubscriberVector::const_iterator it;
00010 for (it = v.begin(); it != v.end(); ++it)
00011 {
00012 os << (it == v.begin() ? ": " : ", ");
00013 if (dynamic_cast<cModule*>((*it).client))
00014 {
00015 cModule *mod = dynamic_cast<cModule*>((*it).client);
00016 os << "mod (" << mod->getClassName() << ") " << mod->getFullName() << " id=" << mod->getId();
00017 }
00018 else if (dynamic_cast<cObject*>((*it).client))
00019 {
00020 cObject *obj = dynamic_cast<cObject*>((*it).client);
00021 os << "a " << obj->getClassName();
00022 }
00023 else
00024 {
00025 os << "a " << opp_typename(typeid((*it).client));
00026 }
00027 os << " scope: " << (*it).scopeModuleId;
00028 }
00029 return os;
00030 }
00031
00032
00033
00034 Blackboard::~Blackboard()
00035 {
00036 }
00037
00038 void Blackboard::initialize(int stage) {
00039
00040 if (stage == 0) {
00041 hasPar("coreDebug") ? coreDebug = par("coreDebug").boolValue() : coreDebug = false;
00042
00043 WATCH_VECTOR(clientVector);
00044 WATCH_VECTOR(categoryDescriptions);
00045 }
00046 }
00047
00048 void Blackboard::handleMessage(cMessage *msg) {
00049 error("This module does not handle any messages yet");
00050 }
00051
00052 const char* Blackboard::categoryName(int category)
00053 {
00054 if(categoryDescriptions.size() < static_cast<unsigned>(category)) {
00055 error("BlackBoard::categoryName called with unknown category (%i)", category);
00056 }
00057 return categoryDescriptions[category];
00058 }
00059
00060 int Blackboard::findAndCreateDescription(bool *isNewEntry, const BBItem *category)
00061 {
00062
00063 CategoryDescriptions::size_type it;
00064 std::string desc = category->getClassName();
00065 std::string cName;
00066
00067 for(it = 0; it < categoryDescriptions.size(); ++it)
00068 {
00069 cName = categoryDescriptions[it];
00070 if(cName == desc) {
00071 (*isNewEntry) = false;
00072 break;
00073 }
00074 }
00075 if(it == categoryDescriptions.size()) {
00076 (*isNewEntry) = true;
00077 categoryDescriptions.push_back(category->getClassName());
00078 it = categoryDescriptions.size() - 1;
00079 clientVector.push_back(SubscriberVector());
00080 if(it != clientVector.size()-1)
00081 error("BlackBoard::findAndCreateDescription SubscriberVector creation failed");
00082 parentVector.push_back(-1);
00083 if(it != parentVector.size()-1)
00084 error("BlackBoard::findAndCreateDescription ParentVector creation failed");
00085 nextCategory = categoryDescriptions.size();
00086 }
00087 return static_cast<int>(it);
00088 }
00089
00090 void Blackboard::fillParentVector(const BBItem *category, int cat)
00091 {
00092 bool isNewEntry = true;
00093 int it;
00094
00095 BBItem *parentObject;
00096 BBItem base;
00097
00098 parentObject = category->parentObject();
00099
00100 if(typeid(*parentObject) != typeid(base)) {
00101 it = findAndCreateDescription(&isNewEntry, parentObject);
00102 parentVector[cat] = it;
00103 fillParentVector(parentObject, it);
00104 }
00105 delete parentObject;
00106 }
00107
00108
00109
00110 int Blackboard::subscribe(ImNotifiable *client, int category, int scopeModuleId)
00111 {
00112 if(coreDebug) {
00113 Enter_Method("subscribe(%s, %i)", categoryName(category), scopeModuleId);
00114 } else {
00115 Enter_Method_Silent();
00116 }
00117
00118
00119 SubscriberVector& clients = clientVector[category];
00120 SubscriberVector::const_iterator it;
00121 for(it = clients.begin(); it != clients.end(); ++it) {
00122 if((*it).client == client) {
00123 std::string cname("unkown");
00124 cModule *cm = dynamic_cast<cModule *>(client);
00125 if(cm) cname = cm->getFullPath();
00126 error("BlackBoard::subscribe called twice for item %s, by client %s. \nThis probably means that a class from which you derived yours has \nalready subscribed to this item. This may result in conflicts, please check.\n ", categoryName(category), cname.c_str());
00127 break;
00128 }
00129 }
00130
00131 if (it == clients.end()) {
00132 clients.push_back(Subscriber(client, scopeModuleId));
00133 }
00134 return category;
00135 }
00136
00137 int Blackboard::subscribe(ImNotifiable *client, const BBItem *category, int scopeModuleId)
00138 {
00139 if(coreDebug) {
00140 Enter_Method("subscribe(%s, %i)", category?category->getClassName() : "n/a",
00141 scopeModuleId);
00142 } else {
00143 Enter_Method_Silent();
00144 }
00145 CategoryDescriptions::size_type it = 0;
00146 bool isNewEntry;
00147
00148 if(category) {
00149 it = findAndCreateDescription(&isNewEntry, category);
00150 if(isNewEntry) fillParentVector(category, static_cast<int>(it));
00151 subscribe(client, static_cast<int>(it), scopeModuleId);
00152 }
00153 else {
00154 error("BlackBoard::subscribe called without category item");
00155 }
00156 return static_cast<int>(it);
00157 }
00158
00159 void Blackboard::unsubscribe(ImNotifiable *client, int category)
00160 {
00161 if(coreDebug) {
00162 Enter_Method("unsubscribe(%s)", categoryName(category));
00163 } else {
00164 Enter_Method_Silent();
00165 }
00166
00167 SubscriberVector& clients = clientVector[category];
00168
00169
00170 SubscriberVector::iterator it;
00171
00172 for(it = clients.begin(); it != clients.end(); ++it)
00173 {
00174
00175 if((*it).client == client)
00176 {
00177
00178 clients.erase(it);
00179 break;
00180 }
00181 }
00182 }
00183
00184 void Blackboard::publishBBItem(int category, const BBItem *details, int scopeModuleId)
00185 {
00186 if(coreDebug) {
00187 Enter_Method("publish(%s, %s, %i)", categoryName(category),
00188 details?details->info().c_str() : "n/a", scopeModuleId);
00189 } else {
00190 Enter_Method_Silent();
00191 }
00192
00193 int pCat;
00194 if(clientVector.size() > 0) {
00195 SubscriberVector::const_iterator j;
00196 for (j=clientVector[category].begin(); j!=clientVector[category].end(); ++j)
00197 {
00198 if(((*j).scopeModuleId == -1) || ((*j).scopeModuleId == scopeModuleId))
00199 {
00200 (*j).client->receiveBBItem(category, details, scopeModuleId);
00201 }
00202 }
00203 pCat = parentVector[category];
00204 if(pCat >= 0) publishBBItem(pCat, details, scopeModuleId);
00205 }
00206 }
00207
00208 int Blackboard::getCategory(const BBItem *details)
00209 {
00210 if(coreDebug) {
00211 Enter_Method("getCategory(%s)", details?details->getClassName():"n/a");
00212 } else {
00213 Enter_Method_Silent();
00214 }
00215 int category = -1;
00216 bool isNewEntry;
00217
00218 if(details) {
00219 category = findAndCreateDescription(&isNewEntry, details);
00220 if(isNewEntry) fillParentVector(details, category);
00221 } else {
00222 error("BlackBoard::getCategory called without category item");
00223 }
00224 return category;
00225 }
00226
00227
00228