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);
}
Exemple #2
0
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();
}
Exemple #3
0
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";
}