o 'not' operator on conditions

o transitions from multiple origin states
 o register scripts as application



git-svn-id: http://svn.berlios.de/svnroot/repos/sems/trunk@1245 8eb893ce-cfd4-0310-b710-fb5ebe64c474
sayer/1.4-spce2.6
Stefan Sayer 18 years ago
parent 2fa73d5167
commit 67c1ffed32

@ -172,6 +172,22 @@ int DSMFactory::onLoad()
return -1;
}
}
string RegisterDiags = cfg.getParameter("register_apps");
vector<string> register_names = explode(RegisterDiags, ",");
for (vector<string>::iterator it=
register_names.begin(); it != register_names.end(); it++) {
if (diags.hasDiagram(*it)) {
bool res = AmPlugIn::instance()->registerFactory4App(*it,this);
if(res)
INFO("DSM state machine registered: %s.\n",
it->c_str());
} else {
ERROR("trying to register application '%s' which is not loaded.\n",
it->c_str());
return -1;
}
}
InboundStartDiag = cfg.getParameter("inbound_start_diag");
if (InboundStartDiag.empty()) {
@ -200,21 +216,35 @@ void DSMFactory::prepareSession(DSMDialog* s) {
AmSession* DSMFactory::onInvite(const AmSipRequest& req)
{
if (InboundStartDiag.empty()) {
ERROR("no inbound calls allowed\n");
throw AmSession::Exception(488, "Not Acceptable Here");
string start_diag;
if (req.cmd == MOD_NAME) {
if (InboundStartDiag.empty()) {
ERROR("no inbound calls allowed\n");
throw AmSession::Exception(488, "Not Acceptable Here");
}
start_diag = InboundStartDiag;
} else {
start_diag = req.cmd;
}
DSMDialog* s = new DSMDialog(prompts, diags, InboundStartDiag, NULL);
DSMDialog* s = new DSMDialog(prompts, diags, start_diag, NULL);
prepareSession(s);
return s;
}
AmSession* DSMFactory::onInvite(const AmSipRequest& req,
AmArg& session_params)
AmArg& session_params)
{
if (OutboundStartDiag.empty()) {
ERROR("no outbound calls allowed\n");
string start_diag;
if (req.cmd == MOD_NAME) {
if (OutboundStartDiag.empty()) {
ERROR("no outbound calls allowed\n");
throw AmSession::Exception(488, "Not Acceptable Here");
}
} else {
start_diag = req.cmd;
}
UACAuthCred* cred = NULL;
@ -224,7 +254,7 @@ AmSession* DSMFactory::onInvite(const AmSipRequest& req,
cred = dynamic_cast<UACAuthCred*>(cred_obj);
}
DSMDialog* s = new DSMDialog(prompts, diags, OutboundStartDiag, cred);
DSMDialog* s = new DSMDialog(prompts, diags, start_diag, cred);
prepareSession(s);
if (NULL == cred) {

@ -112,13 +112,21 @@ DSMAction* DSMChartReader::actionFromToken(const string& str) {
return core_mod.getAction(str);
}
DSMCondition* DSMChartReader::conditionFromToken(const string& str) {
DSMCondition* DSMChartReader::conditionFromToken(const string& str, bool invert) {
for (vector<DSMModule*>::iterator it=
mods.begin(); it!= mods.end(); it++) {
DSMCondition* c=(*it)->getCondition(str);
if (c) return c;
if (c) {
c->invert = invert;
return c;
}
}
return core_mod.getCondition(str);
DSMCondition* c = core_mod.getCondition(str);
if (c)
c->invert = invert;
return c;
}
void splitCmd(const string& from_str,
@ -332,8 +340,15 @@ bool DSMChartReader::decode(DSMStateDiagram* e, const string& chart,
}
continue;
}
if (token == "not") {
cl->invert_next = !cl->invert_next;
continue;
}
// DBG("new condition: '%s'\n", token.c_str());
DSMCondition* c = conditionFromToken(token);
DSMCondition* c = conditionFromToken(token, cl->invert_next);
cl->invert_next = false;
if (!c)
return false;

@ -69,8 +69,9 @@ class ActionList : public DSMElement {
};
struct DSMConditionList : public DSMElement {
DSMConditionList() { }
DSMConditionList() : invert_next(false) { }
vector<DSMCondition*> conditions;
bool invert_next;
};
class DSMChartReader {
@ -80,7 +81,7 @@ class DSMChartReader {
string getToken(string str, size_t& pos);
DSMAction* actionFromToken(const string& str);
DSMCondition* conditionFromToken(const string& str);
DSMCondition* conditionFromToken(const string& str, bool invert);
bool importModule(const string& mod_cmd, const string& mod_path);
vector<DSMModule*> mods;

@ -69,6 +69,15 @@ bool DSMStateDiagramCollection::loadFile(const string& filename, const string& n
return true;
}
bool DSMStateDiagramCollection::hasDiagram(const string& name) {
for (vector<DSMStateDiagram>::iterator it=
diags.begin(); it != diags.end(); it++)
if (it->getName() == name)
return true;
return false;
}
void DSMStateDiagramCollection::addToEngine(DSMStateEngine* e) {
DBG("adding %zd diags to engine\n", diags.size());
for (vector <DSMStateDiagram>::iterator it =

@ -45,6 +45,7 @@ class DSMStateDiagramCollection
bool loadFile(const string& filename, const string& name, const string& mod_path);
void addToEngine(DSMStateEngine* e);
bool hasDiagram(const string& name);
};
#endif

@ -28,6 +28,7 @@
#include "DSMStateEngine.h"
#include "DSMModule.h"
#include "AmUtils.h"
#include "AmSession.h"
#include "log.h"
@ -63,25 +64,53 @@ void DSMStateDiagram::addState(const State& state, bool is_initial) {
}
bool DSMStateDiagram::addTransition(const DSMTransition& trans) {
DBG("adding Transition '%s' %s -()-> %s\n",
DBG("adding Transition '%s' %s -(...)-> %s\n",
trans.name.c_str(), trans.from_state.c_str(), trans.to_state.c_str());
for (vector<DSMCondition*>::const_iterator it=
trans.precond.begin(); it != trans.precond.end(); it++) {
DBG(" DSMCondition '%s'\n", (*it)->name.c_str());
DBG(" DSMCondition %s'%s'\n",
(*it)->invert?"not ":"", (*it)->name.c_str());
}
for (vector<DSMAction*>::const_iterator it=
trans.actions.begin(); it != trans.actions.end(); it++) {
DBG(" Action '%s'\n", (*it)->name.c_str());
}
State* source_st = getState(trans.from_state);
if (!source_st) {
ERROR("state '%s' for transition '%s' not found\n",
trans.from_state.c_str(), trans.name.c_str());
return false;
vector<string> from_states;
if (trans.from_state.find_first_of("(") != string::npos) {
string states = trans.from_state;
if (states.length() && states[0] == '(')
states = states.substr(1);
if (states.length() && states[states.length()-1] == ')')
states = states.substr(0, states.length()-1);
from_states = explode(states, ",");
for (vector<string>::iterator it=from_states.begin();
it != from_states.end(); it++) {
if (it->length() && (*it)[0] == ' ')
*it = it->substr(1);
if (it->length() && (*it)[it->length()-1] == ' ')
*it = it->substr(0, it->length()-1);
}
} else {
from_states.push_back(trans.from_state);
}
source_st->transitions.push_back(trans);
for (vector<string>::iterator it=
from_states.begin(); it != from_states.end(); it++) {
State* source_st = getState(*it);
if (!source_st) {
ERROR("state '%s' for transition '%s' not found\n",
it->c_str(), trans.name.c_str());
return false;
}
source_st->transitions.push_back(trans);
}
return true;
}
@ -183,6 +212,13 @@ bool DSMStateEngine::init(AmSession* sess, const string& startDiagram,
return true;
}
bool DSMCondition::_match(AmSession* sess,
DSMCondition::EventType event,
map<string,string>* event_params) {
// or xor
return invert?(!match(sess,event,event_params)):match(sess,event,event_params);
}
bool DSMCondition::match(AmSession* sess,
DSMCondition::EventType event,
map<string,string>* event_params) {
@ -220,7 +256,7 @@ void DSMStateEngine::runEvent(AmSession* sess,
vector<DSMCondition*>::iterator con=tr->precond.begin();
while (con!=tr->precond.end()) {
if (!(*con)->match(sess, event, event_params))
if (!(*con)->_match(sess, event, event_params))
break;
con++;
}

@ -73,12 +73,17 @@ class DSMCondition
PlaylistSeparator
};
DSMCondition() { }
bool invert;
DSMCondition() : invert(false) { }
virtual ~DSMCondition() { }
EventType type;
map<string, string> params;
bool _match(AmSession* sess, DSMCondition::EventType event,
map<string,string>* event_params);
virtual bool match(AmSession* sess, DSMCondition::EventType event,
map<string,string>* event_params);
};

@ -15,7 +15,9 @@ import(mod_name);
} ]
;
transition name s1 - [ { condition; condition; ... } ] [/ { action; action; ...} ] -> s2;
transition name s1 - [ { [not] condition; [not] condition; ... } ] [/ { action; action; ...} ] -> s2;
or
transition name (s1a, s1b[, s1c, ...]) - [ { [not] condition; [not] condition; ... } ] [/ { action; action; ...} ] -> s2;
=============================
#paramname uses the event parameter 'paramname' (from current event)
@ -41,8 +43,8 @@ actions:
setPromptSet(name)
if more prompt sets are loaded
set($var, value)
e.g. set($var, "text"); set($var, $var2); set($var, #key)
set($var=value)
e.g. set($var="text"); set($var=$var2); set($var=#key)
append($var, value)
e.g. append($var, "text"); append($var, #key);
append($var, @select); append($var, $var2);

@ -2,10 +2,13 @@
o checking of FSM consitency (e.g. target state names)
o better error reporting in script compilation (e.g. line number)
o better error handling (exceptions)
o 'not' operator on conditions
x 'not' operator on conditions
o 'or' operator
x provide session init function for modules
o embed python interpreter in module ?
-> py( ... python code ... ) condition and action
o correct en/decode DI args (e.g. arrays)
o replace DSMSession::map<string, string> var with map<string, AmArg>
x register scripts as app
o mod_mysql
o session creation from module

@ -3,6 +3,10 @@
diag_path=/usr/local/lib/sems/dsm/
load_diags=inbound_call,outbound_call
# register these diagrams as 'application' in SEMS
# so it can be used in application= in sems.conf
#register_apps=inbound_cann,outbound_call
# for import(mod_name)
mod_path=/usr/local/lib/sems/dsm/

Loading…
Cancel
Save