private static IActivity consumeXor(
     IActivity startActivity,
     LinkedList<ITransition> unconsumed,
     HashSet<ITransition> visited,
     boolean forward,
     boolean supportsLoops,
     ModelElementList<ITransition> transitions) {
   IActivity result = null;
   for (ITransition out : transitions) {
     if (visited.contains(out)) // loop
     {
       if (!supportsLoops) {
         return null;
       }
     } else {
       LinkedList<ITransition> unconsumedClone = (LinkedList<ITransition>) unconsumed.clone();
       HashSet<ITransition> visitedClone = (HashSet<ITransition>) visited.clone();
       visitedClone.add(out);
       unconsumedClone.add(out);
       IActivity next =
           consume(startActivity, unconsumedClone, visitedClone, forward, supportsLoops);
       if (next == null) {
         return null;
       } else if (result == null) {
         result = next;
       } else if (result != next) {
         return null;
       }
     }
   }
   return result;
 }
 private static LinkedList<ITransition> asList(ModelElementList<ITransition> transitions) {
   LinkedList<ITransition> unconsumed = CollectionUtils.newLinkedList();
   for (ITransition transition : transitions) {
     unconsumed.add(transition);
   }
   return unconsumed;
 }
  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;
  }