Skip to content

Commit

Permalink
feat: Add topojson graph export rebase (#1926)
Browse files Browse the repository at this point in the history
  • Loading branch information
takb authored Dec 16, 2024
2 parents 81638e4 + 69b0efb commit d21f124
Show file tree
Hide file tree
Showing 19 changed files with 909 additions and 133 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ RELEASING:
## [unreleased]

### Added
- TopoJSON graph export ([#1926](https://github.com/GIScience/openrouteservice/pull/1926))

### Changed

Expand Down
3 changes: 2 additions & 1 deletion ors-api/src/main/java/org/heigit/ors/api/APIEnums.java
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,8 @@ public String toString() {

@Schema(name = "Export response type", description = "Format of the export response.")
public enum ExportResponseType {
JSON("json");
JSON("json"),
TOPOJSON("topojson");

private final String value;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import org.heigit.ors.api.errors.CommonResponseEntityExceptionHandler;
import org.heigit.ors.api.requests.export.ExportApiRequest;
import org.heigit.ors.api.responses.export.json.JsonExportResponse;
import org.heigit.ors.api.responses.export.topojson.TopoJsonExportResponse;
import org.heigit.ors.api.services.ExportService;
import org.heigit.ors.common.EncoderNameEnum;
import org.heigit.ors.exceptions.*;
Expand Down Expand Up @@ -73,13 +74,6 @@ public String getPostMapping(@RequestBody ExportApiRequest request) throws Missi
throw new MissingParameterException(ExportErrorCodes.MISSING_PARAMETER, "profile");
}

// Matches any response type that has not been defined
@PostMapping(value = "/{profile}/*")
@Operation(hidden = true)
public void getInvalidResponseType() throws StatusCodeException {
throw new StatusCodeException(HttpServletResponse.SC_NOT_ACCEPTABLE, ExportErrorCodes.UNSUPPORTED_EXPORT_FORMAT, "This response format is not supported");
}

// Functional request methods
@PostMapping(value = "/{profile}")
@Operation(
Expand All @@ -104,7 +98,7 @@ public JsonExportResponse getDefault(@Parameter(description = "Specifies the rou

@PostMapping(value = "/{profile}/json", produces = {"application/json;charset=UTF-8"})
@Operation(
description = "Returns a list of points, edges and weights within a given bounding box for a selected profile JSON.",
description = "Returns a list of points, edges and weights within a given bounding box for a selected profile as JSON.",
summary = "Export Service JSON"
)
@ApiResponse(
Expand All @@ -127,6 +121,38 @@ public JsonExportResponse getJsonExport(
return new JsonExportResponse(result);
}

@PostMapping(value = "/{profile}/topojson", produces = {"application/json;charset=UTF-8"})
@Operation(
description = "Returns a list of edges, edge properties, and their topology within a given bounding box for a selected profile.",
summary = "Export Service TopoJSON"
)
@ApiResponse(
responseCode = "200",
description = "TopoJSON Response.",
content = {@Content(
mediaType = "application/json",
schema = @Schema(implementation = TopoJsonExportResponse.class)
)
})
public TopoJsonExportResponse getTopoJsonExport(
@Parameter(description = "Specifies the profile.", required = true, example = "driving-car") @PathVariable String profile,
@Parameter(description = "The request payload", required = true) @RequestBody ExportApiRequest request) throws StatusCodeException {
request.setProfile(getProfileEnum(profile));
request.setProfileName(profile);
request.setResponseType(APIEnums.ExportResponseType.TOPOJSON);

ExportResult result = exportService.generateExportFromRequest(request);

return TopoJsonExportResponse.fromExportResult(result);
}

// Matches any response type that has not been defined
@PostMapping(value = "/{profile}/{responseType}")
@Operation(hidden = true)
public void getInvalidResponseType(@PathVariable String profile, @PathVariable String responseType) throws StatusCodeException {
throw new StatusCodeException(HttpServletResponse.SC_NOT_ACCEPTABLE, ExportErrorCodes.UNSUPPORTED_EXPORT_FORMAT, "The response format %s is not supported".formatted(responseType));
}

@ExceptionHandler(MissingServletRequestParameterException.class)
public ResponseEntity<Object> handleMissingParams(final MissingServletRequestParameterException e) {
return errorHandler.handleStatusCodeException(new MissingParameterException(ExportErrorCodes.MISSING_PARAMETER, e.getParameterName()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
public class APIRequest {
public static final String PARAM_ID = "id";
public static final String PARAM_PROFILE = "profile";
public static final String PARAM_PROFILE_NAME = "profile_name";

@Schema(name = PARAM_ID, description = "Arbitrary identification string of the request reflected in the meta information.",
example = "my_request")
Expand All @@ -19,7 +20,7 @@ public class APIRequest {
@Schema(name = PARAM_PROFILE, hidden = true)
protected APIEnums.Profile profile;


@Schema(name = PARAM_PROFILE_NAME, hidden = true)
protected String profileName;

public boolean hasId() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import org.heigit.ors.api.requests.common.APIRequest;
import org.heigit.ors.api.APIEnums;
import org.heigit.ors.api.requests.common.APIRequest;

import java.util.List;

Expand All @@ -17,8 +17,8 @@ public class ExportApiRequest extends APIRequest {
public static final String PARAM_BBOX = "bbox";
public static final String PARAM_PROFILE = "profile";
public static final String PARAM_FORMAT = "format";

public static final String PARAM_DEBUG = "debug";
public static final String PARAM_GEOMETRY = "geometry";
public static final String PARAM_ADDITIONAL_INFO = "additional_info";

@Schema(name = PARAM_ID, description = "Arbitrary identification string of the request reflected in the meta information.",
example = "export_request")
Expand All @@ -40,9 +40,13 @@ public class ExportApiRequest extends APIRequest {
@JsonProperty(PARAM_FORMAT)
private APIEnums.ExportResponseType responseType = APIEnums.ExportResponseType.JSON;

@Schema(name = PARAM_DEBUG, hidden = true)
@JsonProperty(PARAM_DEBUG)
private boolean debug;
@Schema(name = PARAM_GEOMETRY, description = "Whether to return the exact geometry of the graph or a simplified (beeline) representation.", example = "true", defaultValue = "true")
@JsonProperty(PARAM_GEOMETRY)
private boolean geometry = true;

@Schema(name = PARAM_ADDITIONAL_INFO, hidden = true)
@JsonProperty(PARAM_ADDITIONAL_INFO)
private boolean additionalInfo;

@JsonCreator
public ExportApiRequest(@JsonProperty(value = PARAM_BBOX, required = true) List<List<Double>> bbox) {
Expand All @@ -62,8 +66,8 @@ public void setId(String id) {
this.hasId = true;
}

public boolean debug() {
return debug;
public boolean additionalInfo() {
return additionalInfo;
}

public List<List<Double>> getBbox() {
Expand All @@ -86,4 +90,11 @@ public void setResponseType(APIEnums.ExportResponseType responseType) {
this.responseType = responseType;
}

public APIEnums.ExportResponseType getResponseType() {
return responseType;
}

public boolean getGeometry() {
return geometry;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public JsonExportResponse(ExportResult exportResult) {
nodesCount = nodes.stream().count();

edges = new ArrayList<>();
for (Map.Entry<Pair<Integer, Integer>, Double> edgeWeight : exportResult.getEdgeWeigths().entrySet()) {
for (Map.Entry<Pair<Integer, Integer>, Double> edgeWeight : exportResult.getEdgeWeights().entrySet()) {
edges.add(new JsonEdge(edgeWeight));
}
edgesCount = edges.stream().count();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package org.heigit.ors.api.responses.export.topojson;

import com.fasterxml.jackson.annotation.JsonValue;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;

import java.io.Serializable;
import java.util.List;

@Builder
@Getter
@Setter
public class Arc implements Serializable {
private List<List<Double>> coordinates;

@JsonValue
public List<List<Double>> getCoordinates() {
return coordinates;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package org.heigit.ors.api.responses.export.topojson;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import lombok.Builder;
import lombok.Getter;

import java.io.Serializable;
import java.util.List;

@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({"type", "properties", "arcs"})
@Getter
@Builder
public class Geometry implements Serializable {
@JsonProperty("type")
private String type;
@JsonProperty("properties")
private transient Properties properties;
@JsonProperty("arcs")
private List<Integer> arcs;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package org.heigit.ors.api.responses.export.topojson;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import lombok.Builder;
import lombok.Getter;

import java.io.Serializable;
import java.util.List;

@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({"type", "geometries"})
@Getter
@Builder
public class Network implements Serializable {
@JsonProperty("type")
private String type;
@JsonProperty("geometries")
private List<Geometry> geometries;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.heigit.ors.api.responses.export.topojson;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Builder;
import lombok.Getter;

import java.io.Serializable;

@JsonInclude(JsonInclude.Include.NON_NULL)
@Getter
@Builder
public class Objects implements Serializable {
@JsonProperty("network")
private Network network;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package org.heigit.ors.api.responses.export.topojson;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Builder;
import lombok.Getter;

import java.io.Serializable;
import java.util.List;

@JsonInclude(JsonInclude.Include.NON_NULL)
@Getter
@Builder
public class Properties implements Serializable {
@JsonProperty("weight")
private Double weight;
@JsonProperty("osm_id")
private Long osmId;
@JsonProperty("both_directions")
private Boolean bothDirections;
@JsonProperty("speed")
private Double speed;
@JsonProperty("speed_reverse")
private Double speedReverse;
@JsonProperty("ors_ids")
private List<Integer> orsIds;
@JsonProperty("ors_nodes")
private List<Integer> orsNodes;
@JsonProperty("distances")
private List<Double> distances;
}
Loading

0 comments on commit d21f124

Please sign in to comment.