public boolean isLegalConfiguration()

in src/main/java/org/apache/commons/scxml2/semantics/SCXMLSemanticsImpl.java [763:813]


    public boolean isLegalConfiguration(final Set<EnterableState> states, final ErrorReporter errRep) {
        /*
         * For every active state we add 1 to the count of its parent. Each
         * Parallel should reach count equal to the number of its children and
         * contribute by 1 to its parent. Each State should reach count exactly
         * 1. SCXML elemnt (top) should reach count exactly 1. We essentially
         * summarize up the hierarchy tree starting with a given set of
         * states = active configuration.
         */
        boolean legalConfig = true; // let's be optimists
        final Map<EnterableState, Set<EnterableState>> counts = new HashMap<>();
        final Set<EnterableState> scxmlCount = new HashSet<>();
        for (EnterableState es : states) {
            EnterableState parent;
            while ((parent = es.getParent()) != null) {
                final Set<EnterableState> cnt = counts.computeIfAbsent(parent, k -> new HashSet<>());
                cnt.add(es);
                es = parent;
            }
            //top-level contribution
            scxmlCount.add(es);
        }
        if (scxmlCount.size() > 1) {
            errRep.onError(ErrorConstants.ILLEGAL_CONFIG, "Multiple top-level OR states active!", scxmlCount);
            legalConfig = false;
        }
        else {
            //Validate child counts:
            for (final Map.Entry<EnterableState, Set<EnterableState>> entry : counts.entrySet()) {
                final EnterableState es = entry.getKey();
                final Set<EnterableState> count = entry.getValue();
                if (es instanceof Parallel) {
                    final Parallel p = (Parallel) es;
                    if (count.size() < p.getChildren().size()) {
                        errRep.onError(ErrorConstants.ILLEGAL_CONFIG, "Not all AND states active for parallel " + p.getId(), entry);
                        legalConfig = false;
                    }
                } else {
                    if (count.size() > 1) {
                        errRep.onError(ErrorConstants.ILLEGAL_CONFIG, "Multiple OR states active for state " + es.getId(), entry);
                        legalConfig = false;
                    }
                }
                count.clear(); //cleanup
            }
        }
        //cleanup
        scxmlCount.clear();
        counts.clear();
        return legalConfig;
    }