class CustomizedPathsAPI extends API {

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

    private static List<WeightedEdgeStep> step(HugeGraph graph,
                                               PathRequest request) {
        int stepSize = request.steps.size();
        List<WeightedEdgeStep> steps = new ArrayList<>(stepSize);
        for (Step step : request.steps) {
            steps.add(step.jsonToStep(graph));
        }
        return steps;
    }

    @POST
    @Timed
    @Consumes(APPLICATION_JSON)
    @Produces(APPLICATION_JSON_WITH_CHARSET)
    public String post(@Context GraphManager manager,
                       @PathParam("graph") String graph,
                       PathRequest request) {<FILL_FUNCTION_BODY>}

    private enum SortBy {
        INCR,
        DECR,
        NONE
    }

    private static class PathRequest {

        @JsonProperty("sources")
        public Vertices sources;
        @JsonProperty("steps")
        public List<Step> steps;
        @JsonProperty("sort_by")
        public SortBy sortBy;
        @JsonProperty("capacity")
        public long capacity = Long.parseLong(DEFAULT_CAPACITY);
        @JsonProperty("limit")
        public int limit = Integer.parseInt(DEFAULT_PATHS_LIMIT);
        @JsonProperty("with_vertex")
        public boolean withVertex = false;

        @JsonProperty("with_edge")
        public boolean withEdge = false;

        @Override
        public String toString() {
            return String.format("PathRequest{sourceVertex=%s,steps=%s," +
                                 "sortBy=%s,capacity=%s,limit=%s," +
                                 "withVertex=%s,withEdge=%s}", this.sources, this.steps,
                                 this.sortBy, this.capacity, this.limit,
                                 this.withVertex, this.withEdge);
        }
    }

    private static class Step {

        @JsonProperty("direction")
        public Directions direction;
        @JsonProperty("labels")
        public List<String> labels;
        @JsonProperty("properties")
        public Map<String, Object> properties;
        @JsonAlias("degree")
        @JsonProperty("max_degree")
        public long maxDegree = Long.parseLong(DEFAULT_MAX_DEGREE);
        @JsonProperty("skip_degree")
        public long skipDegree = 0L;
        @JsonProperty("weight_by")
        public String weightBy;
        @JsonProperty("default_weight")
        public double defaultWeight = Double.parseDouble(DEFAULT_WEIGHT);
        @JsonProperty("sample")
        public long sample = Long.parseLong(DEFAULT_SAMPLE);

        @Override
        public String toString() {
            return String.format("Step{direction=%s,labels=%s,properties=%s," +
                                 "maxDegree=%s,skipDegree=%s," +
                                 "weightBy=%s,defaultWeight=%s,sample=%s}",
                                 this.direction, this.labels, this.properties,
                                 this.maxDegree, this.skipDegree,
                                 this.weightBy, this.defaultWeight,
                                 this.sample);
        }

        private WeightedEdgeStep jsonToStep(HugeGraph g) {
            return new WeightedEdgeStep(g, this.direction, this.labels,
                                        this.properties, this.maxDegree,
                                        this.skipDegree, this.weightBy,
                                        this.defaultWeight, this.sample);
        }
    }
}

        E.checkArgumentNotNull(request, "The path request body can't be null");
        E.checkArgumentNotNull(request.sources,
                               "The sources of path request can't be null");
        E.checkArgument(request.steps != null && !request.steps.isEmpty(),
                        "The steps of path request can't be empty");
        if (request.sortBy == null) {
            request.sortBy = SortBy.NONE;
        }

        LOG.debug("Graph [{}] get customized paths from source vertex '{}', " +
                  "with steps '{}', sort by '{}', capacity '{}', limit '{}', " +
                  "with_vertex '{}' and with_edge '{}'", graph, request.sources, request.steps,
                  request.sortBy, request.capacity, request.limit,
                  request.withVertex, request.withEdge);

        ApiMeasurer measure = new ApiMeasurer();

        HugeGraph g = graph(manager, graph);
        Iterator<Vertex> sources = request.sources.vertices(g);
        List<WeightedEdgeStep> steps = step(g, request);
        boolean sorted = request.sortBy != SortBy.NONE;

        CustomizePathsTraverser traverser = new CustomizePathsTraverser(g);
        List<HugeTraverser.Path> paths;
        paths = traverser.customizedPaths(sources, steps, sorted,
                                          request.capacity, request.limit);
        measure.addIterCount(traverser.vertexIterCounter.get(),
                             traverser.edgeIterCounter.get());

        if (sorted) {
            boolean incr = request.sortBy == SortBy.INCR;
            paths = CustomizePathsTraverser.topNPath(paths, incr,
                                                     request.limit);
        }

        Iterator<?> iterVertex;
        Set<Id> vertexIds = new HashSet<>();
        for (HugeTraverser.Path path : paths) {
            vertexIds.addAll(path.vertices());
        }
        if (request.withVertex && !vertexIds.isEmpty()) {
            iterVertex = g.vertices(vertexIds.toArray());
            measure.addIterCount(vertexIds.size(), 0L);
        } else {
            iterVertex = vertexIds.iterator();
        }

        Iterator<?> iterEdge;
        Set<Edge> edges = traverser.edgeResults().getEdges(paths);
        if (request.withEdge && !edges.isEmpty()) {
            iterEdge = edges.iterator();
        } else {
            iterEdge = HugeTraverser.EdgeRecord.getEdgeIds(edges).iterator();
        }

        return manager.serializer(g, measure.measures())
                      .writePaths("paths", paths, false,
                                  iterVertex, iterEdge);
    
<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