private static void addActivities(
     Set<TransitionTarget> visited,
     List<TransitionTarget> targets,
     IActivity activity,
     TransitionOptions options,
     boolean forward,
     Stack<TransitionStep> steps) {
   ModelElementList<ITransition> transitions =
       forward ? activity.getOutTransitions() : activity.getInTransitions();
   JoinSplitType jsType = forward ? activity.getSplitType() : activity.getJoinType();
   if (JoinSplitType.And == jsType && transitions.size() > 1) {
     IActivity target =
         consume(
             activity,
             asList(transitions),
             CollectionUtils.<ITransition>newHashSet(),
             forward,
             options.areLoopsAllowed());
     if (target != null) {
       addActivity(visited, targets, target, options, forward, steps);
     }
   } else {
     for (ITransition transition : transitions) {
       IActivity target = forward ? transition.getToActivity() : transition.getFromActivity();
       jsType = forward ? target.getJoinType() : target.getSplitType();
       if (JoinSplitType.And != jsType) {
         addActivity(visited, targets, target, options, forward, steps);
       }
     }
   }
 }
  private static IActivity consume(
      IActivity startActivity,
      LinkedList<ITransition> unconsumed,
      HashSet<ITransition> visited,
      boolean forward,
      boolean supportsLoops) {
    int unchanged = 0;
    while (!unconsumed.isEmpty()) {
      ITransition transition = unconsumed.element();
      IActivity target = forward ? transition.getToActivity() : transition.getFromActivity();

      if (startActivity == target) {
        // unsupported loop
        break;
      }

      JoinSplitType inJsType = forward ? target.getJoinType() : target.getSplitType();
      if (JoinSplitType.And == inJsType) {
        List<ITransition> pending = CollectionUtils.newList();
        ModelElementList<ITransition> transitions =
            forward ? target.getInTransitions() : target.getOutTransitions();
        for (ITransition incoming : transitions) {
          if (unconsumed.remove(incoming)) {
            pending.add(incoming);
          }
        }
        if (pending.size() == transitions.size()) // all incoming transitions consumed
        {
          if (unconsumed.isEmpty()) {
            return target;
          }
        } else {
          if (!unconsumed
              .isEmpty()) // unable to consume all transitions, but there are more branches, put
          // them all back to the end
          {
            unconsumed.addAll(pending);
            unchanged++;
          }
          if (unchanged == unconsumed.size()) {
            return null;
          }
          continue;
        }
      } else {
        unconsumed.remove(transition);
      }
      unchanged = 0;

      ModelElementList<ITransition> transitions =
          forward ? target.getOutTransitions() : target.getInTransitions();
      if (transitions.isEmpty()) {
        return null;
      }

      JoinSplitType outJsType = forward ? target.getSplitType() : target.getJoinType();
      if (JoinSplitType.Xor == outJsType && transitions.size() > 1) {
        return consumeXor(startActivity, unconsumed, visited, forward, supportsLoops, transitions);
      } else {
        for (ITransition out : transitions) {
          if (visited.contains(out)) // loop
          {
            if (!supportsLoops) {
              return null;
            }
          } else {
            visited.add(out);
            unconsumed.add(out);
          }
        }
      }
    }
    return null;
  }