@Check(CheckType.FAST)
  public void checkUnusedExit(final Exit exit) {
    if (exit.getParentRegion().getComposite() instanceof org.yakindu.sct.model.sgraph.State
        && exit.getOutgoingTransitions().isEmpty()) {
      org.yakindu.sct.model.sgraph.State state =
          (org.yakindu.sct.model.sgraph.State) exit.getParentRegion().getComposite();

      if (!STextValidationModelUtils.isDefault(exit)) {
        boolean hasOutgoingTransition = false;
        Iterator<Transition> transitionIt = state.getOutgoingTransitions().iterator();
        while (transitionIt.hasNext() && !hasOutgoingTransition) {
          Transition transition = transitionIt.next();
          hasOutgoingTransition =
              STextValidationModelUtils.isDefaultExitTransition(transition)
                  ? true
                  : STextValidationModelUtils.isNamedExitTransition(transition, exit.getName());
        }
        if (!hasOutgoingTransition) {
          error(EXIT_UNUSED, exit, null, -1);
        }
      } else {
        boolean hasOutgoingTransition = false;
        Iterator<Transition> transitionIt = state.getOutgoingTransitions().iterator();
        while (transitionIt.hasNext() && !hasOutgoingTransition) {
          hasOutgoingTransition =
              STextValidationModelUtils.isDefaultExitTransition(transitionIt.next());
        }
        if (!hasOutgoingTransition) {
          error(EXIT_DEFAULT_UNUSED, exit, null, -1);
        }
      }
    }
  }
  @Check(CheckType.FAST)
  public void checkUnboundEntryPoints(final org.yakindu.sct.model.sgraph.State state) {
    if (state.isComposite()) {
      final List<Transition>[] transitions =
          STextValidationModelUtils.getEntrySpecSortedTransitions(state.getIncomingTransitions());
      Map<Region, List<Entry>> regions = null;

      // first list contains Transitions without entry spec
      if (!transitions[0].isEmpty()) {
        regions = STextValidationModelUtils.getRegionsWithoutDefaultEntry(state.getRegions());
        if (!regions.isEmpty()) {
          for (Transition transition : transitions[0]) {
            error(TRANSITION_UNBOUND_DEFAULT_ENTRY_POINT, transition, null, -1);
          }
          for (Region region : regions.keySet()) {
            error(REGION_UNBOUND_DEFAULT_ENTRY_POINT, region, null, -1);
          }
        }
      }

      // second list contains Transitions with entry spec
      if (!transitions[1].isEmpty()) {
        if (regions == null) {
          regions = STextValidationModelUtils.getRegionsWithoutDefaultEntry(state.getRegions());
        }
        for (Transition transition : transitions[1]) {
          boolean hasTargetEntry = true;
          for (ReactionProperty property : transition.getProperties()) {
            if (property instanceof EntryPointSpec) {
              EntryPointSpec spec = (EntryPointSpec) property;
              String specName = "'" + spec.getEntrypoint() + "'";
              for (Region region : regions.keySet()) {
                boolean hasEntry = false;
                for (Entry entry : regions.get(region)) {
                  if (entry.getName().equals(spec.getEntrypoint())) {
                    hasEntry = true;
                    break;
                  }
                }
                if (!hasEntry) {
                  error(REGION_UNBOUND_NAMED_ENTRY_POINT + specName, region, null, -1);
                  hasTargetEntry = false;
                }
              }
              if (!hasTargetEntry) {
                error(TRANSITION_UNBOUND_NAMED_ENTRY_POINT + specName, transition, null, -1);
              }
            }
          }
        }
      }
    }
  }
  @Check(CheckType.FAST)
  public void checkTransitionPropertySpec(final Transition transition) {
    for (ReactionProperty property : transition.getProperties()) {
      if (property instanceof EntryPointSpec) {
        if (transition.getTarget() instanceof org.yakindu.sct.model.sgraph.State) {
          org.yakindu.sct.model.sgraph.State state =
              (org.yakindu.sct.model.sgraph.State) transition.getTarget();
          if (!state.isComposite()) {
            warning(TRANSITION_ENTRY_SPEC_NOT_COMPOSITE, transition, null, -1);
          }
        }
      } else if (property instanceof ExitPointSpec) {
        final ExitPointSpec exitPointSpec = (ExitPointSpec) property;
        if (transition.getSource() instanceof org.yakindu.sct.model.sgraph.State) {
          org.yakindu.sct.model.sgraph.State state =
              (org.yakindu.sct.model.sgraph.State) transition.getSource();
          if (!state.isComposite()) {
            warning(TRANSITION_EXIT_SPEC_NOT_COMPOSITE, transition, null, -1);
          } else {
            // Validate an exit point is continued on one transition
            // only.
            for (Transition t : state.getOutgoingTransitions()) {
              if (transition != t
                  && STextValidationModelUtils.isNamedExitTransition(
                      t, exitPointSpec.getExitpoint())) {
                warning(TRANSITION_EXIT_SPEC_ON_MULTIPLE_SIBLINGS, transition, null, -1);
              }
            }

            // Validate the state has minimally one named exit
            // region

            boolean hasExit = false;
            Iterator<Region> regionIter = state.getRegions().iterator();
            while (regionIter.hasNext() && !hasExit) {

              Iterator<Exit> exitIter =
                  STextValidationModelUtils.getExits(regionIter.next().eContents()).iterator();
              while (exitIter.hasNext() && !hasExit) {
                Exit exit = exitIter.next();
                hasExit = exitPointSpec.getExitpoint().equals(exit.getName());
              }
            }
            if (!hasExit) {
              error(TRANSITION_NOT_EXISTING_NAMED_EXIT_POINT, transition, null, -1);
            }
          }
        }
      }
    }
  }
  @Check(CheckType.FAST)
  public void checkUnusedEntry(final Entry entry) {
    if (entry.getParentRegion().getComposite() instanceof org.yakindu.sct.model.sgraph.State
        && entry.getIncomingTransitions().isEmpty()) {
      org.yakindu.sct.model.sgraph.State state =
          (org.yakindu.sct.model.sgraph.State) entry.getParentRegion().getComposite();

      if (!STextValidationModelUtils.isDefault(entry)) {

        boolean hasIncomingTransition = false;
        Iterator<Transition> transitionIt = state.getIncomingTransitions().iterator();

        while (transitionIt.hasNext() && !hasIncomingTransition) {

          Iterator<ReactionProperty> propertyIt = transitionIt.next().getProperties().iterator();

          while (propertyIt.hasNext() && !hasIncomingTransition) {

            ReactionProperty property = propertyIt.next();

            if (property instanceof EntryPointSpec) {

              hasIncomingTransition =
                  entry.getName().equals(((EntryPointSpec) property).getEntrypoint());
            }
          }
        }
        if (!hasIncomingTransition) {
          warning(ENTRY_UNUSED, entry, null, -1);
        }
      }
    }
  }
  @Check(CheckType.FAST)
  public void transitionsWithNoTrigger(Transition trans) {
    if (trans.getSource() instanceof Entry
        || trans.getSource() instanceof Choice
        || trans.getSource() instanceof Synchronization) {
      return;
    }
    if (trans.getSource() instanceof org.yakindu.sct.model.sgraph.State) {
      org.yakindu.sct.model.sgraph.State state =
          (org.yakindu.sct.model.sgraph.State) trans.getSource();
      if (state.isComposite()) {
        for (Region r : state.getRegions()) {
          for (Vertex v : r.getVertices()) {
            if (v instanceof Exit) {
              return;
            }
          }
        }
      }
    }

    if (!STextValidationModelUtils.getExitPointSpecs(trans.getProperties()).isEmpty()) {
      return;
    }

    if (trans.getTrigger() == null) {
      warning(ISSUE_TRANSITION_WITHOUT_TRIGGER, trans, null, -1);
    }
  }
 @Check(CheckType.FAST)
 public void checkExitPointSpecWithTrigger(Transition t) {
   if (!STextValidationModelUtils.getExitPointSpecs(t.getProperties()).isEmpty()
       && t.getTrigger() != null
       && t.getSource() instanceof org.yakindu.sct.model.sgraph.State) {
     error(EXITPOINTSPEC_WITH_TRIGGER, t, null, -1);
   }
 }