ScenarioManager.cc

Go to the documentation of this file.
00001 //
00002 // Copyright (C) 2005 Andras Varga
00003 //
00004 // This program is free software; you can redistribute it and/or
00005 // modify it under the terms of the GNU Lesser General Public License
00006 // as published by the Free Software Foundation; either version 2
00007 // of the License, or (at your option) any later version.
00008 //
00009 // This program is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 // GNU Lesser General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU Lesser General Public License
00015 // along with this program; if not, see <http://www.gnu.org/licenses/>.
00016 //
00017 
00018 #include "ScenarioManager.h"
00019 
00020 Define_Module(ScenarioManager);
00021 
00022 
00023 void ScenarioManager::initialize()
00024 {
00025     cXMLElement *script = par("script");
00026 
00027     numChanges = numDone = 0;
00028     WATCH(numChanges);
00029     WATCH(numDone);
00030 
00031     for (cXMLElement *node=script->getFirstChild(); node; node = node->getNextSibling())
00032     {
00033         // check attr t is present
00034         const char *tAttr = node->getAttribute("t");
00035         if (!tAttr)
00036             error("attribute 't' missing at %s", node->getSourceLocation());
00037 
00038         // schedule self-message
00039         simtime_t t = STR_SIMTIME(tAttr);
00040         cMessage *msg = new cMessage("scenario-event");
00041         msg->setContextPointer(node);
00042         scheduleAt(t, msg);
00043 
00044         // count it
00045         numChanges++;
00046     }
00047 
00048     updateDisplayString();
00049 }
00050 
00051 void ScenarioManager::handleMessage(cMessage *msg)
00052 {
00053     cXMLElement *node = (cXMLElement *) msg->getContextPointer();
00054     delete msg;
00055 
00056     processCommand(node);
00057 
00058     numDone++;
00059     updateDisplayString();
00060 }
00061 
00062 void ScenarioManager::processCommand(cXMLElement *node)
00063 {
00064     const char *tag = node->getTagName();
00065     EV << "processing <" << tag << "> command...\n";
00066 
00067     if (!strcmp(tag,"at"))
00068         processAtCommand(node);
00069     else if (!strcmp(tag,"set-param"))
00070         processSetParamCommand(node);
00071     else if (!strcmp(tag,"set-channel-attr"))
00072         processSetChannelAttrCommand(node);
00073     // else if (!strcmp(tag,"create-module"))
00074     //    processCreateModuleCommand(node);
00075     // else if (!strcmp(tag,"connect"))
00076     //    processConnectCommand(node);
00077     else
00078         processModuleSpecificCommand(node);
00079 }
00080 
00081 // helper function
00082 static bool parseIndexedName(const char *s, std::string& name, int& index)
00083 {
00084     const char *b;
00085     if ((b=strchr(s,'['))==NULL || s[strlen(s)-1]!=']')
00086     {
00087         name = s;
00088         index = -1;
00089         return false;
00090     }
00091     else
00092     {
00093         name.assign(s, b-s);
00094         index = atoi(b+1);
00095         return true;
00096     }
00097 }
00098 
00099 const char *ScenarioManager::getRequiredAttribute(cXMLElement *node, const char *attr)
00100 {
00101     const char *s = node->getAttribute(attr);
00102     if (!s)
00103         error("required attribute %s of <%s> missing at %s",
00104               attr, node->getTagName(), node->getSourceLocation());
00105     return s;
00106 }
00107 
00108 cModule *ScenarioManager::getRequiredModule(cXMLElement *node, const char *attr)
00109 {
00110     const char *moduleAttr = getRequiredAttribute(node, attr);
00111     cModule *mod = simulation.getModuleByPath(moduleAttr);
00112     if (!mod)
00113         error("module '%s' not found at %s", moduleAttr, node->getSourceLocation());
00114     return mod;
00115 }
00116 
00117 cGate *ScenarioManager::getRequiredGate(cXMLElement *node, const char *modAttr, const char *gateAttr)
00118 {
00119     cModule *mod = getRequiredModule(node, modAttr);
00120     const char *gateStr = getRequiredAttribute(node, gateAttr);
00121     std::string gname;
00122     int gindex;
00123     cGate *g = parseIndexedName(gateStr, gname, gindex) ? mod->gate(gname.c_str(), gindex) : mod->gate(gname.c_str());
00124     if (!g)
00125         error("module '%s' has no gate '%s' at %s", mod->getFullPath().c_str(), gateStr, node->getSourceLocation());
00126     return g;
00127 }
00128 
00129 void ScenarioManager::processAtCommand(cXMLElement *node)
00130 {
00131     for (cXMLElement *child=node->getFirstChild(); child; child=child->getNextSibling())
00132         processCommand(child);
00133 }
00134 
00135 void ScenarioManager::processModuleSpecificCommand(cXMLElement *node)
00136 {
00137     // find which module we'll need to invoke
00138     cModule *mod = getRequiredModule(node, "module");
00139 
00140     // see if it supports the IScriptable interface
00141     IScriptable *scriptable = dynamic_cast<IScriptable *>(mod);
00142     if (!scriptable)
00143         error("<%s> not understood: it is not a built-in command of %s, and module class %s "
00144               "is not scriptable (does not subclass from IScriptable) at %s",
00145               node->getTagName(), getClassName(), mod->getClassName(), node->getSourceLocation());
00146 
00147     // ok, trust it to process this command
00148     scriptable->processCommand(*node);
00149 }
00150 
00151 void ScenarioManager::processSetParamCommand(cXMLElement *node)
00152 {
00153     // process <set-param> command
00154     cModule *mod = getRequiredModule(node, "module");
00155     const char *parAttr = getRequiredAttribute(node, "par");
00156     const char *valueAttr = getRequiredAttribute(node, "value");
00157 
00158     EV << "Setting " << mod->getFullPath() << "." << parAttr << " = " << valueAttr << "\n";
00159     bubble((std::string("setting: ")+mod->getFullPath()+"."+parAttr+" = "+valueAttr).c_str());
00160 
00161     // set the parameter to the given value
00162     cPar& param = mod->par(parAttr);
00163     param.parse(valueAttr);
00164 }
00165 
00166 void ScenarioManager::processSetChannelAttrCommand(cXMLElement *node)
00167 {
00168     // process <set-channel-attr> command
00169     cGate *g = getRequiredGate(node, "src-module", "src-gate");
00170     const char *attrAttr = getRequiredAttribute(node, "attr");
00171     const char *valueAttr = getRequiredAttribute(node, "value");
00172 
00173     EV << "Setting channel attribute: " << attrAttr << " = " << valueAttr
00174        << " of gate " << g->getFullPath() << "\n";
00175     bubble((std::string("setting channel attr: ")+attrAttr+" = "+valueAttr).c_str());
00176 
00177     // make sure gate is connected at all
00178     if (!g->getNextGate())
00179         error("gate '%s' is not connected at %s", g->getFullPath().c_str(), node->getSourceLocation());
00180 
00181     // find channel (or add one?)
00182     cChannel *chan = g->getChannel();
00183     if (!chan)
00184         error("connection starting at gate '%s' has no attributes at %s", g->getFullPath().c_str(), node->getSourceLocation());
00185 
00186     // set the parameter to the given value
00187     if (!chan->hasPar(attrAttr))
00188         ; //FIXME remove this "if"
00189     cPar& param = chan->par(attrAttr);
00190     param.parse(valueAttr);
00191 }
00192 
00193 void ScenarioManager::processCreateModuleCommand(cXMLElement *node)
00194 {
00195     // FIXME finish and test
00196 }
00197 
00198 void ScenarioManager::processDeleteModuleCommand(cXMLElement *node)
00199 {
00200     // FIXME finish and test
00201 }
00202 
00203 void ScenarioManager::processConnectCommand(cXMLElement *node)
00204 {
00205     // FIXME finish and test
00206 }
00207 
00208 void ScenarioManager::processDisconnectCommand(cXMLElement *node)
00209 {
00210     // FIXME finish and test
00211 }
00212 
00213 void ScenarioManager::updateDisplayString()
00214 {
00215     char buf[80];
00216     sprintf(buf, "total %d changes, %d left", numChanges, numChanges-numDone);
00217     getDisplayString().setTagArg("t", 0, buf);
00218 }
00219