From ed1361482ecd3793cb3d68d6fee7e96e0d44e986 Mon Sep 17 00:00:00 2001 From: oblonski <4sschroeder@gmail.com> Date: Wed, 5 Nov 2014 06:32:28 +0100 Subject: [PATCH] add json stuff --- .../jsprit/core/problem/io/JsonConstants.java | 5 + .../jsprit/core/problem/io/VrpJsonReader.java | 117 ++++++++++++------ 2 files changed, 86 insertions(+), 36 deletions(-) diff --git a/jsprit-core/src/main/java/jsprit/core/problem/io/JsonConstants.java b/jsprit-core/src/main/java/jsprit/core/problem/io/JsonConstants.java index 973954bf..645a688f 100644 --- a/jsprit-core/src/main/java/jsprit/core/problem/io/JsonConstants.java +++ b/jsprit-core/src/main/java/jsprit/core/problem/io/JsonConstants.java @@ -66,6 +66,11 @@ public class JsonConstants { public static final String TIME_WINDOW = "time_window"; + public static final String TYPE = "type"; + + public static final String PICKUP = "pickup"; + + public static final String DELIVERY = "delivery"; } public static class Vehicle { diff --git a/jsprit-core/src/main/java/jsprit/core/problem/io/VrpJsonReader.java b/jsprit-core/src/main/java/jsprit/core/problem/io/VrpJsonReader.java index 96cae570..1fc8abbe 100644 --- a/jsprit-core/src/main/java/jsprit/core/problem/io/VrpJsonReader.java +++ b/jsprit-core/src/main/java/jsprit/core/problem/io/VrpJsonReader.java @@ -21,7 +21,9 @@ package jsprit.core.problem.io; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import jsprit.core.problem.VehicleRoutingProblem; +import jsprit.core.problem.job.Delivery; import jsprit.core.problem.job.Job; +import jsprit.core.problem.job.Pickup; import jsprit.core.problem.job.Service; import jsprit.core.problem.solution.route.activity.TimeWindow; import jsprit.core.problem.vehicle.Vehicle; @@ -37,7 +39,7 @@ import java.util.Iterator; import java.util.Map; /** - * Created by schroeder on 04.11.14. + * Reads vehicle routing problem from json file. */ public class VrpJsonReader { @@ -49,6 +51,13 @@ public class VrpJsonReader { this.vrpBuilder = vrpBuilder; } + /** + * Reads json file. + * + * @param jsonFile to be read + * @throws java.lang.IllegalStateException if there is a service without id and proper location spec OR + * if there is a vehicle without id and proper location spec OR if there is a vehicle type without id + */ public void read(String jsonFile){ JsonNode root = buildTree_and_getRoot(jsonFile); setFleetSize(root); @@ -69,15 +78,26 @@ public class VrpJsonReader { return node; } + /** + * @param root node + * @throws java.lang.IllegalStateException if service id is missing OR neither location id nor location coordinate are set + */ private void parse_services(JsonNode root) { JsonNode services = root.path(JsonConstants.SERVICES); for(JsonNode serviceNode : services){ + //type + JsonNode typeNode = serviceNode.path(JsonConstants.Job.TYPE); + //service id JsonNode jobIdNode = serviceNode.path(JsonConstants.Job.ID); - if(jobIdNode.isMissingNode()){ - throw new IllegalStateException("service-id is missing"); - } - Service.Builder serviceBuilder = Service.Builder.newInstance(jobIdNode.asText()); + if(jobIdNode.isMissingNode()) throw new IllegalStateException("service-id is missing"); + Service.Builder serviceBuilder; + if(typeNode.isMissingNode()) serviceBuilder = Service.Builder.newInstance(jobIdNode.asText()); + else if(typeNode.asText().equals(JsonConstants.Job.PICKUP)) serviceBuilder = Pickup.Builder.newInstance(jobIdNode.asText()); + else if(typeNode.asText().equals(JsonConstants.Job.DELIVERY)) serviceBuilder = Delivery.Builder.newInstance(jobIdNode.asText()); + else throw new IllegalStateException("type of service ("+typeNode.asText()+") is not supported"); + + //service address JsonNode addressIdNode = serviceNode.path(JsonConstants.Job.ADDRESS).path(JsonConstants.Address.ID); boolean either_locationId_or_coord = false; if(!addressIdNode.isMissingNode()){ @@ -85,24 +105,26 @@ public class VrpJsonReader { either_locationId_or_coord = true; } { - Double lon = serviceNode.path(JsonConstants.Job.ADDRESS).path(JsonConstants.Address.LON).asDouble(); - Double lat = serviceNode.path(JsonConstants.Job.ADDRESS).path(JsonConstants.Address.LAT).asDouble(); - if (lon != null && lat != null) { - serviceBuilder.setCoord(Coordinate.newInstance(lon, lat)); + JsonNode lonNode = serviceNode.path(JsonConstants.Job.ADDRESS).path(JsonConstants.Address.LON); + JsonNode latNode = serviceNode.path(JsonConstants.Job.ADDRESS).path(JsonConstants.Address.LAT); + if (!lonNode.isMissingNode() && !latNode.isMissingNode()) { + serviceBuilder.setCoord(Coordinate.newInstance(lonNode.asDouble(), latNode.asDouble())); either_locationId_or_coord = true; } } if(!either_locationId_or_coord) throw new IllegalStateException("location missing. either locationId or locationCoordinate is required"); - - serviceBuilder.setName(serviceNode.path(JsonConstants.Job.NAME).asText()); + //service name + JsonNode nameNode = serviceNode.path(JsonConstants.Job.NAME); + if(!nameNode.isMissingNode()) serviceBuilder.setName(nameNode.asText()); + //service duration serviceBuilder.setServiceTime(serviceNode.path(JsonConstants.Job.SERVICE_DURATION).asDouble()); - - Double tw_start = serviceNode.path(JsonConstants.Job.TIME_WINDOW).path(JsonConstants.TimeWindow.START).asDouble(); - Double tw_end = serviceNode.path(JsonConstants.Job.TIME_WINDOW).path(JsonConstants.TimeWindow.END).asDouble(); - if(tw_start != null && tw_end != null){ - serviceBuilder.setTimeWindow(TimeWindow.newInstance(tw_start,tw_end)); + //service tw + JsonNode start_tw_node = serviceNode.path(JsonConstants.Job.TIME_WINDOW).path(JsonConstants.TimeWindow.START); + JsonNode end_tw_node = serviceNode.path(JsonConstants.Job.TIME_WINDOW).path(JsonConstants.TimeWindow.END); + if(!start_tw_node.isMissingNode() && !end_tw_node.isMissingNode()){ + serviceBuilder.setTimeWindow(TimeWindow.newInstance(start_tw_node.asDouble(),end_tw_node.asDouble())); } - + //service size JsonNode sizeNode = serviceNode.path(JsonConstants.Job.SIZE); int size_index = 0; for(JsonNode sizeValNode : sizeNode){ @@ -110,46 +132,64 @@ public class VrpJsonReader { serviceBuilder.addSizeDimension(size_index,size_value); size_index++; } - + //service skills JsonNode reqSkills = serviceNode.path(JsonConstants.Job.SKILLS); for(JsonNode skillNode : reqSkills){ serviceBuilder.addRequiredSkill(skillNode.asText()); } - + //add service vrpBuilder.addJob(serviceBuilder.build()); } } + /** + * @param root node + * @throws java.lang.IllegalStateException if vehicle id is missing OR if neither start location id nor start location + * coordinate are set + */ private void parse_vehicles(JsonNode root) { JsonNode vehicles = root.path(JsonConstants.VEHICLES); - for(JsonNode vehicleNode : vehicles){ -// JsonNode vehicleNode = vehicle_iterator.next(); - VehicleImpl.Builder vehicleBuilder = VehicleImpl.Builder.newInstance(vehicleNode.path(JsonConstants.Vehicle.ID).asText()); + //vehicle id + JsonNode vehicle_id_node = vehicleNode.path(JsonConstants.Vehicle.ID); + if(vehicle_id_node.isMissingNode()) throw new IllegalStateException("vehicle id missing"); + VehicleImpl.Builder vehicleBuilder = VehicleImpl.Builder.newInstance(vehicle_id_node.asText()); + //vehicle type VehicleType type = vehicle_type_map.get(vehicleNode.path(JsonConstants.Vehicle.TYPE_ID).asText()); vehicleBuilder.setType(type); - + //earliest start JsonNode earliestStartNode = vehicleNode.path(JsonConstants.Vehicle.EARLIEST_START); if(!earliestStartNode.isMissingNode()) vehicleBuilder.setEarliestStart(earliestStartNode.asDouble()); - + //latest end JsonNode latestEndNode = vehicleNode.path(JsonConstants.Vehicle.LATEST_END); if(!latestEndNode.isMissingNode()) vehicleBuilder.setLatestArrival(latestEndNode.asDouble()); - - String startLocationId = vehicleNode.path(JsonConstants.Vehicle.START_ADDRESS).path(JsonConstants.Address.ID).asText(); - vehicleBuilder.setStartLocationId(startLocationId); - JsonNode endAddressId = vehicleNode.path(JsonConstants.Vehicle.END_ADDRESS).path(JsonConstants.Address.ID); - if(!endAddressId.isMissingNode()){ - if(!startLocationId.equals(endAddressId.asText())){ - vehicleBuilder.setEndLocationId(endAddressId.asText()); - } + //start + //location id + boolean either_id_or_coord = false; + JsonNode startAddressId = vehicleNode.path(JsonConstants.Vehicle.START_ADDRESS).path(JsonConstants.Address.ID); + if(!startAddressId.isMissingNode()){ + vehicleBuilder.setStartLocationId(startAddressId.asText()); + either_id_or_coord = true; } + //location coordinate { JsonNode lonNode = vehicleNode.path(JsonConstants.Vehicle.START_ADDRESS).path(JsonConstants.Address.LON); JsonNode latNode = vehicleNode.path(JsonConstants.Vehicle.START_ADDRESS).path(JsonConstants.Address.LAT); if (!lonNode.isMissingNode() && !latNode.isMissingNode()) { vehicleBuilder.setStartLocationCoordinate(Coordinate.newInstance(lonNode.asDouble(), latNode.asDouble())); + either_id_or_coord = true; } } + if(!either_id_or_coord) throw new IllegalStateException("start location of vehicle missing. either id or coordinate required"); + //end + //location id + JsonNode endAddressId = vehicleNode.path(JsonConstants.Vehicle.END_ADDRESS).path(JsonConstants.Address.ID); + if(!endAddressId.isMissingNode()){ + if(!startAddressId.asText().equals(endAddressId.asText())){ + vehicleBuilder.setEndLocationId(endAddressId.asText()); + } + } + //location coordinate { JsonNode lonNode = vehicleNode.path(JsonConstants.Vehicle.END_ADDRESS).path(JsonConstants.Address.LON); JsonNode latNode = vehicleNode.path(JsonConstants.Vehicle.END_ADDRESS).path(JsonConstants.Address.LAT); @@ -157,23 +197,28 @@ public class VrpJsonReader { vehicleBuilder.setEndLocationCoordinate(Coordinate.newInstance(lonNode.asDouble(), latNode.asDouble())); } } - + //skills JsonNode skillsNode = vehicleNode.path(JsonConstants.Vehicle.SKILLS); for(JsonNode skillNode : skillsNode){ String skill = skillNode.asText(); vehicleBuilder.addSkill(skill); } - VehicleImpl vehicle = vehicleBuilder.build(); - vrpBuilder.addVehicle(vehicle); + vrpBuilder.addVehicle(vehicleBuilder.build()); } } + /** + * @param root node + * @throws java.lang.IllegalStateException if type id is missing + */ private void parse_and_map_vehicle_types(JsonNode root) { JsonNode types = root.path(JsonConstants.VEHICLE_TYPES); for(JsonNode typeNode : types){ - VehicleTypeImpl.Builder typeBuilder = VehicleTypeImpl.Builder.newInstance(typeNode.path(JsonConstants.Vehicle.Type.ID).asText()); + JsonNode typeIdNode = typeNode.path(JsonConstants.Vehicle.Type.ID); + if(typeIdNode.isMissingNode()) throw new IllegalStateException("type id missing"); + VehicleTypeImpl.Builder typeBuilder = VehicleTypeImpl.Builder.newInstance(typeIdNode.asText()); typeBuilder.setFixedCost(typeNode.path(JsonConstants.Vehicle.Type.FIXED_COSTS).asDouble()); typeBuilder.setCostPerDistance(typeNode.path(JsonConstants.Vehicle.Type.DISTANCE).asDouble()); typeBuilder.setCostPerTime(typeNode.path(JsonConstants.Vehicle.Type.TIME).asDouble());