class RaftAPI extends API {

    private static final Logger LOG = Log.logger(RaftAPI.class);

    @GET
    @Timed
    @Path("list_peers")
    @Consumes(APPLICATION_JSON)
    @Produces(APPLICATION_JSON_WITH_CHARSET)
    @RolesAllowed({"admin"})
    public Map<String, List<String>> listPeers(@Context GraphManager manager,
                                               @PathParam("graph") String graph,
                                               @QueryParam("group")
                                               @DefaultValue("default")
                                               String group) {
        LOG.debug("Graph [{}] prepare to get leader", graph);

        HugeGraph g = graph(manager, graph);
        RaftGroupManager raftManager = raftGroupManager(g, group, "list_peers");
        List<String> peers = raftManager.listPeers();
        return ImmutableMap.of(raftManager.group(), peers);
    }

    @GET
    @Timed
    @Path("get_leader")
    @Consumes(APPLICATION_JSON)
    @Produces(APPLICATION_JSON_WITH_CHARSET)
    @RolesAllowed({"admin"})
    public Map<String, String> getLeader(@Context GraphManager manager,
                                         @PathParam("graph") String graph,
                                         @QueryParam("group")
                                         @DefaultValue("default")
                                         String group) {
        LOG.debug("Graph [{}] prepare to get leader", graph);

        HugeGraph g = graph(manager, graph);
        RaftGroupManager raftManager = raftGroupManager(g, group, "get_leader");
        String leaderId = raftManager.getLeader();
        return ImmutableMap.of(raftManager.group(), leaderId);
    }

    @POST
    @Timed
    @Status(Status.OK)
    @Path("transfer_leader")
    @Consumes(APPLICATION_JSON)
    @Produces(APPLICATION_JSON_WITH_CHARSET)
    @RolesAllowed({"admin"})
    public Map<String, String> transferLeader(@Context GraphManager manager,
                                              @PathParam("graph") String graph,
                                              @QueryParam("group")
                                              @DefaultValue("default")
                                              String group,
                                              @QueryParam("endpoint")
                                              String endpoint) {
        LOG.debug("Graph [{}] prepare to transfer leader to: {}",
                  graph, endpoint);

        HugeGraph g = graph(manager, graph);
        RaftGroupManager raftManager = raftGroupManager(g, group,
                                                        "transfer_leader");
        String leaderId = raftManager.transferLeaderTo(endpoint);
        return ImmutableMap.of(raftManager.group(), leaderId);
    }

    @POST
    @Timed
    @Status(Status.OK)
    @Path("set_leader")
    @Consumes(APPLICATION_JSON)
    @Produces(APPLICATION_JSON_WITH_CHARSET)
    @RolesAllowed({"admin"})
    public Map<String, String> setLeader(@Context GraphManager manager,
                                         @PathParam("graph") String graph,
                                         @QueryParam("group")
                                         @DefaultValue("default")
                                         String group,
                                         @QueryParam("endpoint")
                                         String endpoint) {<FILL_FUNCTION_BODY>}

    @POST
    @Timed
    @Status(Status.OK)
    @Path("add_peer")
    @Consumes(APPLICATION_JSON)
    @Produces(APPLICATION_JSON_WITH_CHARSET)
    @RolesAllowed({"admin"})
    @RedirectFilter.RedirectMasterRole
    public Map<String, Id> addPeer(@Context GraphManager manager,
                                   @PathParam("graph") String graph,
                                   @QueryParam("group") @DefaultValue("default")
                                   String group,
                                   @QueryParam("endpoint") String endpoint) {
        LOG.debug("Graph [{}] prepare to add peer: {}", graph, endpoint);

        HugeGraph g = graph(manager, graph);
        RaftGroupManager raftManager = raftGroupManager(g, group, "add_peer");

        JobBuilder<String> builder = JobBuilder.of(g);
        String name = String.format("raft-group-[%s]-add-peer-[%s]-at-[%s]",
                                    raftManager.group(), endpoint,
                                    DateUtil.now());
        Map<String, String> inputs = new HashMap<>();
        inputs.put("endpoint", endpoint);
        builder.name(name)
               .input(JsonUtil.toJson(inputs))
               .job(new RaftAddPeerJob());
        return ImmutableMap.of("task_id", builder.schedule().id());
    }

    @POST
    @Timed
    @Status(Status.OK)
    @Path("remove_peer")
    @Consumes(APPLICATION_JSON)
    @Produces(APPLICATION_JSON_WITH_CHARSET)
    @RolesAllowed({"admin"})
    @RedirectFilter.RedirectMasterRole
    public Map<String, Id> removePeer(@Context GraphManager manager,
                                      @PathParam("graph") String graph,
                                      @QueryParam("group")
                                      @DefaultValue("default") String group,
                                      @QueryParam("endpoint") String endpoint) {
        LOG.debug("Graph [{}] prepare to remove peer: {}", graph, endpoint);

        HugeGraph g = graph(manager, graph);
        RaftGroupManager raftManager = raftGroupManager(g, group,
                                                        "remove_peer");
        JobBuilder<String> builder = JobBuilder.of(g);
        String name = String.format("raft-group-[%s]-remove-peer-[%s]-at-[%s]",
                                    raftManager.group(), endpoint,
                                    DateUtil.now());
        Map<String, String> inputs = new HashMap<>();
        inputs.put("endpoint", endpoint);
        builder.name(name)
               .input(JsonUtil.toJson(inputs))
               .job(new RaftRemovePeerJob());
        return ImmutableMap.of("task_id", builder.schedule().id());
    }

    private static RaftGroupManager raftGroupManager(HugeGraph graph,
                                                     String group,
                                                     String operation) {
        RaftGroupManager raftManager = graph.raftGroupManager();
        if (raftManager == null) {
            throw new HugeException("Allowed %s operation only when " +
                                    "working on raft mode", operation);
        }
        return raftManager;
    }
}

        LOG.debug("Graph [{}] prepare to set leader to: {}",
                  graph, endpoint);

        HugeGraph g = graph(manager, graph);
        RaftGroupManager raftManager = raftGroupManager(g, group, "set_leader");
        String leaderId = raftManager.setLeader(endpoint);
        return ImmutableMap.of(raftManager.group(), leaderId);
    
<methods>public non-sealed void <init>() ,public static boolean checkAndParseAction(java.lang.String) ,public static R commit(org.apache.hugegraph.HugeGraph, Callable<R>) ,public static void commit(org.apache.hugegraph.HugeGraph, java.lang.Runnable) ,public static org.apache.hugegraph.HugeGraph graph(org.apache.hugegraph.core.GraphManager, java.lang.String) ,public static org.apache.hugegraph.HugeGraph graph4admin(org.apache.hugegraph.core.GraphManager, java.lang.String) ,public static java.lang.Object[] properties(Map<java.lang.String,java.lang.Object>) <variables>public static final java.lang.String ACTION_APPEND,public static final java.lang.String ACTION_CLEAR,public static final java.lang.String ACTION_ELIMINATE,public static final java.lang.String APPLICATION_JSON,public static final java.lang.String APPLICATION_JSON_WITH_CHARSET,public static final java.lang.String APPLICATION_TEXT_WITH_CHARSET,public static final java.lang.String CHARSET,private static final Meter EXPECTED_ERROR_METER,private static final Meter ILLEGAL_ARG_ERROR_METER,public static final java.lang.String JSON,protected static final Logger LOG,private static final Meter SUCCEED_METER,public static final java.lang.String TEXT_PLAIN,private static final Meter UNKNOWN_ERROR_METER