/**
   * Delete execution
   *
   * @param execution Execution id
   */
  @Path("/executions/{executionId}")
  @DELETE
  @NoCache
  public void removeExecution(@PathParam("executionId") String execution) {
    auth.requireManage();

    AuthenticationExecutionModel model = realm.getAuthenticationExecutionById(execution);
    if (model == null) {
      session.getTransaction().setRollbackOnly();
      throw new NotFoundException("Illegal execution");
    }
    AuthenticationFlowModel parentFlow = getParentFlow(model);
    if (parentFlow.isBuiltIn()) {
      throw new BadRequestException("It is illegal to remove execution from a built in flow");
    }

    if (model.getFlowId() != null) {
      AuthenticationFlowModel nonTopLevelFlow = realm.getAuthenticationFlowById(model.getFlowId());
      realm.removeAuthenticationFlow(nonTopLevelFlow);
    }

    realm.removeAuthenticatorExecution(model);

    adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).success();
  }
  /**
   * Raise execution's priority
   *
   * @param execution Execution id
   */
  @Path("/executions/{executionId}/raise-priority")
  @POST
  @NoCache
  public void raisePriority(@PathParam("executionId") String execution) {
    auth.requireManage();

    AuthenticationExecutionModel model = realm.getAuthenticationExecutionById(execution);
    if (model == null) {
      session.getTransaction().setRollbackOnly();
      throw new NotFoundException("Illegal execution");
    }
    AuthenticationFlowModel parentFlow = getParentFlow(model);
    if (parentFlow.isBuiltIn()) {
      throw new BadRequestException("It is illegal to modify execution in a built in flow");
    }
    List<AuthenticationExecutionModel> executions = getSortedExecutions(parentFlow);
    AuthenticationExecutionModel previous = null;
    for (AuthenticationExecutionModel exe : executions) {
      if (exe.getId().equals(model.getId())) {
        break;
      }
      previous = exe;
    }
    if (previous == null) return;
    int tmp = previous.getPriority();
    previous.setPriority(model.getPriority());
    realm.updateAuthenticatorExecution(previous);
    model.setPriority(tmp);
    realm.updateAuthenticatorExecution(model);

    adminEvent.operation(OperationType.UPDATE).resourcePath(uriInfo).success();
  }
  /**
   * Lower execution's priority
   *
   * @param execution Execution id
   */
  @Path("/executions/{executionId}/lower-priority")
  @POST
  @NoCache
  public void lowerPriority(@PathParam("executionId") String execution) {
    auth.requireManage();

    AuthenticationExecutionModel model = realm.getAuthenticationExecutionById(execution);
    if (model == null) {
      session.getTransaction().setRollbackOnly();
      throw new NotFoundException("Illegal execution");
    }
    AuthenticationFlowModel parentFlow = getParentFlow(model);
    if (parentFlow.isBuiltIn()) {
      throw new BadRequestException("It is illegal to modify execution in a built in flow");
    }
    List<AuthenticationExecutionModel> executions = getSortedExecutions(parentFlow);
    int i = 0;
    for (i = 0; i < executions.size(); i++) {
      if (executions.get(i).getId().equals(model.getId())) {
        break;
      }
    }
    if (i + 1 >= executions.size()) return;
    AuthenticationExecutionModel next = executions.get(i + 1);
    int tmp = model.getPriority();
    model.setPriority(next.getPriority());
    realm.updateAuthenticatorExecution(model);
    next.setPriority(tmp);
    realm.updateAuthenticatorExecution(next);

    adminEvent.operation(OperationType.UPDATE).resourcePath(uriInfo).success();
  }
  /**
   * Update authentication executions of a flow
   *
   * @param flowAlias Flow alias
   * @param rep
   */
  @Path("/flows/{flowAlias}/executions")
  @PUT
  @NoCache
  @Consumes(MediaType.APPLICATION_JSON)
  public void updateExecutions(
      @PathParam("flowAlias") String flowAlias, AuthenticationExecutionInfoRepresentation rep) {
    auth.requireManage();

    AuthenticationFlowModel flow = realm.getFlowByAlias(flowAlias);
    if (flow == null) {
      logger.debug("flow not found: " + flowAlias);
      throw new NotFoundException("flow not found");
    }

    AuthenticationExecutionModel model = realm.getAuthenticationExecutionById(rep.getId());
    if (model == null) {
      session.getTransaction().setRollbackOnly();
      throw new NotFoundException("Illegal execution");
    }
    if (!model.getRequirement().name().equals(rep.getRequirement())) {
      model.setRequirement(AuthenticationExecutionModel.Requirement.valueOf(rep.getRequirement()));
      realm.updateAuthenticatorExecution(model);
      adminEvent
          .operation(OperationType.UPDATE)
          .resourcePath(uriInfo)
          .representation(rep)
          .success();
    }
  }
  /**
   * Update execution with new configuration
   *
   * @param execution Execution id
   * @param json JSON with new configuration
   * @return
   */
  @Path("/executions/{executionId}/config")
  @POST
  @NoCache
  @Consumes(MediaType.APPLICATION_JSON)
  public Response newExecutionConfig(
      @PathParam("executionId") String execution, AuthenticatorConfigRepresentation json) {
    auth.requireManage();

    AuthenticationExecutionModel model = realm.getAuthenticationExecutionById(execution);
    if (model == null) {
      session.getTransaction().setRollbackOnly();
      throw new NotFoundException("Illegal execution");
    }
    AuthenticatorConfigModel config = RepresentationToModel.toModel(json);
    config = realm.addAuthenticatorConfig(config);
    model.setAuthenticatorConfig(config.getId());
    realm.updateAuthenticatorExecution(model);

    json.setId(config.getId());
    adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo).representation(json).success();
    return Response.created(uriInfo.getAbsolutePathBuilder().path(config.getId()).build()).build();
  }