Exemple #1
0
        public static void Verify(Diagram diagram)
        {
            ADNodesList adNodesList = new ADNodesList();
            XmiParser   parser      = new XmiParser(adNodesList);

            ADMistakeFactory.diagram = diagram;

            bool hasJoinOrFork = false;

            parser.Parse(diagram, ref hasJoinOrFork);
            // находим предшествующие\последующие элементы для каждого объекта
            if (!diagram.Mistakes.Any(x => x.Seriousness == MistakesTypes.FATAL))
            {
                adNodesList.connect();
            }
            else
            {
                return;
            }
            // adNodesList.print();

            // осуществляем проверку без использования графа
            ADModelVerifier verificationWithoutGraph = new ADModelVerifier(new LexicalAnalizator());

            verificationWithoutGraph.setDiagramElements(adNodesList);
            verificationWithoutGraph.check();

            // осуществляем проверку с использованием графа
            if (hasJoinOrFork && !diagram.Mistakes.Any(x => x.Seriousness == MistakesTypes.FATAL))
            {
                GraphVerifier graphVerifier = new GraphVerifier();
                graphVerifier.check(adNodesList);
            }
        }
 public void setDiagramElements(ADNodesList diagramElements)
 {
     this.diagramElements = diagramElements;
 }
 public XmiParser(ADNodesList adNodesList)
 {
     this.adNodesList = adNodesList;
 }
Exemple #4
0
        public void check(ADNodesList adList)
        {
            Queue <List <Token> > leaves      = new Queue <List <Token> >();                          // необработанные маски
            HashSet <string>      masksInUsed = new HashSet <string>(adList.getPetriElementsCount()); // использованные маски

            // ищем начальное состояние
            ADNodesList.ADNode initNode = adList.findInitial();
            var finalNode          = adList.findFinal();
            var indexesOfFinalNode = finalNode.Select(x => ((DiagramElement)x.getValue()).petriId).ToList();

            // создаем маску и добавляем ее в необработанные
            List <Token> maskTmp = createEmptyMask(adList.getPetriElementsCount());

            setNewPaleToken(maskTmp, ((DiagramElement)initNode.getValue()).petriId);

            leaves.Enqueue(maskTmp);
            masksInUsed.Add(maskToString(maskTmp));   // добавляем в множество использованных

            bool canReachFinal = false;

            List <List <Token> > stepResultMasks = new List <List <Token> >();       // содержит маски, кот могут получиться на каждом шаге
            string originMaskString = "";

            // главный цикл прохода по всем элементам, участвующих в проверке
            while (leaves.Count > 0)
            {
                List <Token> originMask = leaves.Dequeue();  // берем первую маску
                originMaskString = maskToString(originMask);
                stepResultMasks.Clear();
                List <Token> stepMask = copyMask(originMask); // маска, которую будем изменять по мере деактивации токенов
                stepResultMasks.Add(copyMask(stepMask));      // Если список масок не изменится, то будет тупик, тк текущая маска уже добавлена в использованные

                int i = 0;
                // Console.WriteLine("Or: " + maskToString(originMask));

                // проходим по всем элементам маски, находим активированные
                // и проверяем, можно ли активировать следующий элемент
                for (int stepProhod = 0; stepProhod < 2; stepProhod++)       // сначала проходим по условным, затем по остальным эл-м
                {
                    i = 0;
                    while (i < stepMask.Count)
                    {
                        if (stepProhod == 0 && adList.getNodeByPetriIndex(i).getValue().getType() != ElementType.DECISION)
                        {
                            i++;
                            continue;   // интересуют только эл-ты, содержащие токены на данном шаге
                        }
                        if (stepProhod == 0 && adList.getNodeByPetriIndex(i).getValue().getType() == ElementType.DECISION && stepMask[i].type != TOKEN)
                        {
                            i++;
                            continue;   // интересуют только эл-ты, содержащие токены на данном шаге
                        }
                        if (stepProhod == 1 && stepMask[i].type != TOKEN)
                        {
                            i++;
                            continue;   // интересуют только эл-ты, содержащие токены на данном шаге
                        }
                        // нашли активный элемент
                        ADNodesList.ADNode curNode = adList.getNodeByPetriIndex(i);     //индекс в списке совпадает с петри ид эл-та
                        int        curNodeIndex    = ((DiagramElement)curNode.getValue()).petriId;
                        List <int> colorsCurToken  = new List <int>(stepMask[curNodeIndex].colors);

                        // особо обрабатываем ситуации, когда элемент имеет несколько выходных переходов
                        if (curNode.nextSize() > 1)
                        {
                            // если эл-т разветвитель, то последующее состояние единственно, однако надо установить несколько токенов за раз
                            if (curNode.getValue().getType() == ElementType.FORK)
                            {
                                colorsCurToken.Add(generateRandomColor());

                                // активируем все следующие элементы
                                for (int j = 0; j < curNode.nextSize(); j++)
                                {
                                    // сразу после форка не может быть join'a, поэтому все эл-ты будут активированы
                                    int indexOfNewToken = ((DiagramElement)curNode.getNext(j).getValue()).petriId;
                                    // проверка, что эл-т не был раннее активирован
                                    if (wasAlreadyActive(indexOfNewToken, stepResultMasks, curNode.getNext(j)))
                                    {
                                        return;
                                    }
                                    // изменяем существующие результирующие маски
                                    updateStepMasks(((DiagramElement)curNode.getValue()).petriId, indexOfNewToken, stepResultMasks, colorsCurToken);
                                }
                                setNewEmptyToken(stepMask, curNodeIndex);
                            }
                            // если это условный оператор, то он порождает несколько возможных последующих состояний
                            else
                            {
                                List <List <Token> > decisionMasks = new List <List <Token> >();   // содержит все возможные маски вариантов перемещения токена
                                bool tokenWasRemoved = false;
                                // активируем следующие элементы по одному
                                for (int j = 0; j < curNode.nextSize(); j++)
                                {
                                    int indexOfNewToken = ((DiagramElement)curNode.getNext(j).getValue()).petriId;      // индекс активируемого эл-та
                                                                                                                        // проверка, что эл-т не был раннее активирован
                                    if (wasAlreadyActive(indexOfNewToken, stepResultMasks, curNode.getNext(j)))
                                    {
                                        return;
                                    }
                                    // Join обрабатывается с помощью reverse проверки
                                    if ((curNode.getNext(j).getValue()).getType() == ElementType.JOIN)
                                    {
                                        List <List <Token> > temp   = copyMasks(stepResultMasks);
                                        List <Token>         result = activateJoin(curNode.getNext(j), stepMask, temp, colorsCurToken);
                                        if (result != null)
                                        {
                                            stepMask = result;
                                            decisionMasks.AddRange(temp);
                                            tokenWasRemoved = true;
                                        }
                                    }
                                    else
                                    {
                                        // в каждой существующей результирующей маске меняем токен и сохраняем в промежуточный список
                                        // в итоге получится новый список, содержащий несколько вариантов результирующих масок,
                                        // в каждом из которых создан новый токен в зависимости от активированного следующего эл-та
                                        foreach (List <Token> resultMask in stepResultMasks)
                                        {
                                            List <Token> temp = copyMask(resultMask);
                                            setToken(temp, indexOfNewToken, NEW_TOKEN, colorsCurToken); // добавляем новый токен

                                            setNewEmptyToken(temp, curNodeIndex);                       // удаляем токен текущего эл-та
                                            decisionMasks.Add(temp);
                                            tokenWasRemoved = true;
                                        }
                                    }
                                }
                                // изменяем маску шага и список результирующих масок, если токен был удален
                                if (tokenWasRemoved)
                                {
                                    setNewEmptyToken(stepMask, ((DiagramElement)curNode.getValue()).petriId);
                                    // меняем результирующую маску
                                    stepResultMasks = decisionMasks;
                                }
                            }
                        }
                        else           // если выходной переход один
                        {
                            int indexOfNewToken = ((DiagramElement)curNode.getNext(0).getValue()).petriId;
                            // проверка, что эл-т не был раннее активирован
                            if (wasAlreadyActive(indexOfNewToken, stepResultMasks, curNode.getNext(0)))
                            {
                                return;
                            }
                            // если следующий Join
                            if ((curNode.getNext(0).getValue()).getType() == ElementType.JOIN)
                            {
                                List <Token> result = activateJoin(curNode.getNext(0), stepMask, stepResultMasks, colorsCurToken);
                                if (result != null)
                                {
                                    stepMask = result;
                                }
                            }
                            else
                            {
                                updateStepMasks(((DiagramElement)curNode.getValue()).petriId, indexOfNewToken, stepResultMasks, colorsCurToken);
                                setNewEmptyToken(stepMask, curNodeIndex);
                            }
                        }
                        i++;
                    }
                }
                // в результирующих масках заменяем NEW_Token на TOKEN
                foreach (List <Token> stepResultMask in stepResultMasks)
                {
                    stepResultMask.ForEach(x => x.type = x.type == NEW_TOKEN ? TOKEN : x.type);
                    //Console.WriteLine("Re: " + maskToString(stepResultMask));
                    if (originMaskString == maskToString(stepResultMask))
                    {
                        ADMistakeFactory.createMistake(MistakesSeriousness.mistakes[MISTAKES.DEAD_ROAD], MistakeAdapter.toString(MISTAKES.DEAD_ROAD), ALL_MISTAKES.DEAD_ROAD);
                        //Console.WriteLine("Again?: "+originMaskString);
                        return;
                    }
                }
                // проверяем, что новой маски нет во множестве обработанных и добавляем в необработанные в таком случае
                foreach (List <Token> resultMask in stepResultMasks)
                {
                    if (!findInMasksInUsed(masksInUsed, resultMask))
                    {
                        int indexOfFinalNode = -1;

                        // проверяем, не достигли ли конечной маркировки (существует путь позволяющий добраться хоть до какого-н finalNode)
                        foreach (var ind in indexesOfFinalNode)
                        {
                            if (resultMask[ind].type == TOKEN)
                            {
                                indexOfFinalNode = ind;
                                break;
                            }
                        }
                        if (indexOfFinalNode != -1)
                        {
                            canReachFinal = true;
                            if (resultMask[indexOfFinalNode].peekLastColor() != NO_COLOR)
                            {
                                ADMistakeFactory.createMistake(MistakesSeriousness.mistakes[MISTAKES.FINAL_COLOR_TOKEN], MistakeAdapter.toString(MISTAKES.FINAL_COLOR_TOKEN), ALL_MISTAKES.FINAL_COLOR_TOKEN);
                                return;
                            }
                            //Проверка, что не осталось токенов
                            int tokenCount = 0;
                            for (int j = 0; j < resultMask.Count && tokenCount <= 1; j++)
                            {
                                if (resultMask[j].type == TOKEN)
                                {
                                    tokenCount++;
                                }
                            }
                            if (tokenCount > 1)
                            {
                                ADMistakeFactory.createMistake(MistakesSeriousness.mistakes[MISTAKES.MANY_TOKENS_IN_END], MistakeAdapter.toString(MISTAKES.MANY_TOKENS_IN_END), ALL_MISTAKES.MANY_TOKENS_IN_END);
                                return;
                            }
                        }
                        else
                        {
                            leaves.Enqueue(copyMask(resultMask));
                        }
                        masksInUsed.Add(maskToString(resultMask));      // добавляем полученную маску в множество обработанных
                    }
                }
            }

            // проверяем, что конечное состояние было достигнуто
            if (!canReachFinal)
            {
                ADMistakeFactory.createMistake(MistakesSeriousness.mistakes[MISTAKES.COULD_NOT_REACH_FINAL], MistakeAdapter.toString(MISTAKES.COULD_NOT_REACH_FINAL), ALL_MISTAKES.COULD_NOT_REACH_FINAL);
            }
        }