/**
   * Copy existing authentication flow under a new name
   *
   * <p>The new name is given as 'newName' attribute of the passed JSON object
   *
   * @param flowAlias Name of the existing authentication flow
   * @param data JSON containing 'newName' attribute
   */
  @Path("/flows/{flowAlias}/copy")
  @POST
  @NoCache
  @Consumes(MediaType.APPLICATION_JSON)
  public Response copy(@PathParam("flowAlias") String flowAlias, Map<String, String> data) {
    auth.requireManage();

    String newName = data.get("newName");
    if (realm.getFlowByAlias(newName) != null) {
      return Response.status(Response.Status.CONFLICT).build();
    }

    AuthenticationFlowModel flow = realm.getFlowByAlias(flowAlias);
    if (flow == null) {
      logger.debug("flow not found: " + flowAlias);
      return Response.status(NOT_FOUND).build();
    }
    AuthenticationFlowModel copy = new AuthenticationFlowModel();
    copy.setAlias(newName);
    copy.setDescription(flow.getDescription());
    copy.setProviderId(flow.getProviderId());
    copy.setBuiltIn(false);
    copy.setTopLevel(flow.isTopLevel());
    copy = realm.addAuthenticationFlow(copy);
    copy(newName, flow, copy);

    data.put("id", copy.getId());
    adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo).representation(data).success();

    return Response.status(201).build();
  }
 protected void copy(String newName, AuthenticationFlowModel from, AuthenticationFlowModel to) {
   for (AuthenticationExecutionModel execution : realm.getAuthenticationExecutions(from.getId())) {
     if (execution.isAuthenticatorFlow()) {
       AuthenticationFlowModel subFlow = realm.getAuthenticationFlowById(execution.getFlowId());
       AuthenticationFlowModel copy = new AuthenticationFlowModel();
       copy.setAlias(newName + " " + subFlow.getAlias());
       copy.setDescription(subFlow.getDescription());
       copy.setProviderId(subFlow.getProviderId());
       copy.setBuiltIn(false);
       copy.setTopLevel(false);
       copy = realm.addAuthenticationFlow(copy);
       execution.setFlowId(copy.getId());
       copy(newName, subFlow, copy);
     }
     execution.setId(null);
     execution.setParentFlow(to.getId());
     realm.addAuthenticatorExecution(execution);
   }
 }
  /**
   * Add new flow with new execution to existing flow
   *
   * @param flowAlias Alias of parent authentication flow
   * @param data New authentication flow / execution JSON data containing 'alias', 'type',
   *     'provider', and 'description' attributes
   */
  @Path("/flows/{flowAlias}/executions/flow")
  @POST
  @NoCache
  @Consumes(MediaType.APPLICATION_JSON)
  public void addExecutionFlow(@PathParam("flowAlias") String flowAlias, Map<String, String> data) {
    auth.requireManage();

    AuthenticationFlowModel parentFlow = realm.getFlowByAlias(flowAlias);
    if (parentFlow == null) {
      throw new BadRequestException("Parent flow doesn't exists");
    }
    String alias = data.get("alias");
    String type = data.get("type");
    String provider = data.get("provider");
    String description = data.get("description");

    AuthenticationFlowModel newFlow = realm.getFlowByAlias(alias);
    if (newFlow != null) {
      throw new BadRequestException("New flow alias name already exists");
    }
    newFlow = new AuthenticationFlowModel();
    newFlow.setAlias(alias);
    newFlow.setDescription(description);
    newFlow.setProviderId(type);
    newFlow = realm.addAuthenticationFlow(newFlow);
    AuthenticationExecutionModel execution = new AuthenticationExecutionModel();
    execution.setParentFlow(parentFlow.getId());
    execution.setFlowId(newFlow.getId());
    execution.setRequirement(AuthenticationExecutionModel.Requirement.DISABLED);
    execution.setAuthenticatorFlow(true);
    execution.setAuthenticator(provider);
    execution.setPriority(getNextPriority(parentFlow));
    execution = realm.addAuthenticatorExecution(execution);

    data.put("id", execution.getId());
    adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo).representation(data).success();
  }