@Override
  public Collection<KaleoTaskAssignment> calculateTaskAssignments(
      KaleoTaskAssignment kaleoTaskAssignment, ExecutionContext executionContext)
      throws PortalException {

    KaleoInstanceToken kaleoInstanceToken = executionContext.getKaleoInstanceToken();

    Group group = null;

    long groupId = kaleoInstanceToken.getGroupId();

    if (groupId != WorkflowConstants.DEFAULT_GROUP_ID) {
      group = _groupLocalService.getGroup(groupId);

      if (group.isLayout()) {
        group = _groupLocalService.getGroup(group.getParentGroupId());
      }
    }

    List<KaleoTaskAssignment> calculatedKaleoTaskAssignments = new ArrayList<>();

    if (isValidAssignment(kaleoTaskAssignment, group)) {
      calculatedKaleoTaskAssignments.add(kaleoTaskAssignment);
    }

    return calculatedKaleoTaskAssignments;
  }
  @Override
  protected void doExecute(
      KaleoNode currentKaleoNode,
      ExecutionContext executionContext,
      List<PathElement> remainingPathElements)
      throws PortalException, SystemException {

    KaleoInstanceToken kaleoInstanceToken = executionContext.getKaleoInstanceToken();

    KaleoInstanceToken parentKaleoInstanceToken = kaleoInstanceToken.getParentKaleoInstanceToken();

    if (parentKaleoInstanceToken.hasIncompleteChildrenKaleoInstanceToken()) {

      return;
    }

    parentKaleoInstanceToken =
        kaleoInstanceTokenLocalService.updateKaleoInstanceToken(
            parentKaleoInstanceToken.getKaleoInstanceTokenId(), currentKaleoNode.getKaleoNodeId());

    KaleoTransition kaleoTransition = currentKaleoNode.getDefaultKaleoTransition();

    ExecutionContext newExecutionContext =
        new ExecutionContext(
            parentKaleoInstanceToken,
            executionContext.getWorkflowContext(),
            executionContext.getServiceContext());

    PathElement pathElement =
        new PathElement(
            currentKaleoNode, kaleoTransition.getTargetKaleoNode(), newExecutionContext);

    remainingPathElements.add(pathElement);
  }
  @Override
  protected boolean doEnter(KaleoNode currentKaleoNode, ExecutionContext executionContext)
      throws PortalException, SystemException {

    KaleoInstanceToken kaleoInstanceToken = executionContext.getKaleoInstanceToken();

    kaleoInstanceTokenLocalService.completeKaleoInstanceToken(
        kaleoInstanceToken.getKaleoInstanceTokenId());

    return true;
  }
  protected void doExecute(
      KaleoNode currentKaleoNode,
      ExecutionContext executionContext,
      List<PathElement> remainingPathElements)
      throws PortalException, SystemException {

    List<KaleoTransition> kaleoTransitions = currentKaleoNode.getKaleoTransitions();

    Map<String, KaleoInstanceToken> childKaleoInstanceTokens =
        new HashMap<String, KaleoInstanceToken>();

    for (KaleoTransition kaleoTransition : kaleoTransitions) {
      KaleoInstanceToken parentKaleoInstanceToken = executionContext.getKaleoInstanceToken();

      KaleoInstanceToken childKaleoInstanceToken =
          kaleoInstanceTokenLocalService.addKaleoInstanceToken(
              parentKaleoInstanceToken.getKaleoInstanceTokenId(),
              executionContext.getWorkflowContext(),
              executionContext.getServiceContext());

      childKaleoInstanceTokens.put(kaleoTransition.getName(), childKaleoInstanceToken);
    }

    for (KaleoTransition kaleoTransition : kaleoTransitions) {
      KaleoInstanceToken childKaleoInstanceToken =
          childKaleoInstanceTokens.get(kaleoTransition.getName());

      ExecutionContext forkedExecutionContext =
          new ExecutionContext(
              childKaleoInstanceToken,
              executionContext.getWorkflowContext(),
              executionContext.getServiceContext());

      PathElement pathElement =
          new PathElement(
              currentKaleoNode, kaleoTransition.getTargetKaleoNode(), forkedExecutionContext);

      remainingPathElements.add(pathElement);
    }
  }