void UmlInitialPseudoState::generate(UmlClass * machine, UmlClass * anystate, UmlState * state) { // checking state->hasInitial(); const QVector<UmlItem*> ch = children(); if (ch.count() != 1) { UmlCom::trace("Error : 'initial' pseudo state must have one and only one transition<br>"); throw 0; } UmlTransition * tr = (UmlTransition *) ch[0]; if (tr->target()->parent() != parent()) { UmlCom::trace("Error : transition from 'initial' must goes to a sub [pseudo] state of the state '" + state->name() + "'<br>"); throw 0; } if (!tr->cppGuard().isEmpty()) { UmlCom::trace("Error : transition from 'initial' must have no guard<br>"); throw 0; } tr->generate(machine, anystate, state); }
void UmlTransition::solveThem() { Q3ValueList<Transition>::Iterator iter; for (iter = All.begin(); iter != All.end(); ++iter) { Transition & transition = *iter; QMap<WrapperStr, UmlItem *>::Iterator isrc = UmlItem::All.find(transition.source); QMap<WrapperStr, UmlItem *>::Iterator itgt = UmlItem::All.find(transition.target); if ((isrc == UmlItem::All.end()) /*&& ((isrc = Outgoings.find(transition.id)) == Outgoings.end())*/) { if (!FileIn::isBypassedId(transition.source)) UmlCom::trace("transition '" + transition.id + "' : unknown source reference '" + transition.source + "'<br>"); } else if ((itgt == UmlItem::All.end()) /*&& ((itgt = Incomings.find(transition.id)) == Incomings.end())*/) { if (!FileIn::isBypassedId(transition.target)) UmlCom::trace("transition '" + transition.id + "' : unknown target reference '" + transition.target + "'<br>"); } else { UmlTransition * t = UmlTransition::create(*isrc, *itgt); if (t == 0) UmlCom::trace("cannot create transition '" + transition.id + "'<br>"); else { UmlItem::All.insert(transition.id, t); if (! transition.name.isEmpty()) t->set_Name(transition.name); if (! transition.effect.isEmpty()) t->set_Activity(transition.effect); if (! transition.trigger.isEmpty()) t->set_Trigger(transition.trigger); else if (! transition.triggerRef.isEmpty()) { WrapperStr trig = Trigger::get(transition.triggerRef); if (!trig.isNull()) t->set_Trigger(trig); else if (!FileIn::isBypassedId(transition.triggerRef)) UmlCom::trace("transition '" + transition.id + "' : unknown trigger reference '" + transition.triggerRef + "'<br>"); } if (! transition.guard.isEmpty()) t->set_Guard(transition.guard); if (*isrc == *itgt) t->set_IsExternal(transition.kind == "external"); t->unload(FALSE, FALSE); } } } All.clear(); }
void UmlTransition::generate(Q3PtrList<UmlTransition> trs, UmlClass * machine, UmlClass * anystate, UmlState * state, Q3CString & body, Q3CString indent, bool completion) { UmlTransition * tr; bool guard = FALSE; for (tr = trs.first(); tr != 0; tr = trs.next()) { body += indent; if (!tr->cppGuard().isEmpty()) { // manage guard body += ((tr == trs.getFirst()) ? "if (" : "else if (") + tr->cppGuard() + ") {\n"; guard = TRUE; } else // no gard : it is the last transition, may be the first body += ((tr == trs.getFirst()) ? "{\n" : "else {\n"); // the target state UmlItem * tg = tr->target(); bool self_external = (state == tg) && tr->isExternal(); while (tg->kind() != aState) tg = tg->parent(); // the parent common to the current and the target state UmlState * common = state; if (self_external) { // execute exit behavior if (!state->cppExitBehavior().isEmpty()) body += indent + " _doexit(stm);\n"; } else { bool fromExit = // the exit behavior is made entering in the exit point (tr->parent()->kind() == anExitPointPseudoState); // compute common parent and manage exit behavior if (tr->target()->kind() != aTerminatePseudoState) { while (!((UmlState *) tg)->inside(common)) { if (!fromExit && !common->cppExitBehavior().isEmpty()) body += indent + " stm" + common->path() + "._doexit(stm);\n"; fromExit = FALSE; switch (common->parent()->kind()) { case aState: common = (UmlState *) common->parent(); break; case aRegion: common = (UmlState *) common->parent()->parent(); break; default: UmlCom::trace("Error : transition from '" + state->name() + "' goes outside the state machine"); throw 0; } } } } // manage transition activity if (!tr->cppActivity().isEmpty()) body += "#ifdef VERBOSE_STATE_MACHINE\n" + indent + " puts(\"DEBUG : execute activity of transition " + tr->name() + "\");\n#endif\n" + tr->cppActivity(); // manage entry behavior if (self_external) { if (state->needCreate()) body += indent + " create(stm);\n"; } else if (tr->target()->kind() != aTerminatePseudoState) { if (tg != common) { Q3CString enter; UmlState * tg_parent; // the enter behavior of the target state will be managed // generating a call to create for (tg_parent = (UmlState *) tg->parent(); tg_parent != common; tg_parent = (UmlState *) tg_parent->parent()) if (!tg_parent->cppEntryBehavior().isEmpty()) enter.insert(0, (const char *)(indent + " stm" + tg_parent->path() + "._doentry(stm);\n")); //[rageek] ambiguous if (!enter.isEmpty()) body += enter; } // set the current state if needed if (tg != state) body += indent + " stm._set_currentState(stm" + ((UmlState *) tg)->path() + ");\n#ifdef VERBOSE_STATE_MACHINE\n" + indent + " puts(\"DEBUG : current state is now " + ((UmlState *) tg)->prettyPath() + "\");\n#endif\n"; } // do the transition if (tr->target()->kind() == aState) { if ((tg != state) && ((UmlState *) tg)->needCreate()) body += indent + " stm" + ((UmlState *) tg)->path() + ".create(stm);\n"; } else tr->target()->generate(machine, anystate, ((UmlState *) tg), body, indent + " "); if (completion) body += indent + " return (bool) 1;\n"; body += indent + "}\n"; } if (completion && guard) body += indent + "return (bool) 0;\n"; }