From 6575b6d48eddbdd5a8386f37c9663862ddae40c6 Mon Sep 17 00:00:00 2001 From: Stefan Schroeder <4sschroeder@gmail.com> Date: Mon, 20 Jan 2014 18:05:07 +0100 Subject: [PATCH] add and test endLocationMethods to Vehicle and VehicleImpl Breaks code if Vehicle is implemented by another class than VehicleImpl --- .../jsprit/core/problem/vehicle/Vehicle.java | 21 +++- .../core/problem/vehicle/VehicleImpl.java | 114 +++++++++++++++++- .../core/problem/vehicle/VehicleImplTest.java | 102 ++++++++++++++++ 3 files changed, 235 insertions(+), 2 deletions(-) diff --git a/jsprit-core/src/main/java/jsprit/core/problem/vehicle/Vehicle.java b/jsprit-core/src/main/java/jsprit/core/problem/vehicle/Vehicle.java index ba24cd92..bf1feb68 100644 --- a/jsprit-core/src/main/java/jsprit/core/problem/vehicle/Vehicle.java +++ b/jsprit-core/src/main/java/jsprit/core/problem/vehicle/Vehicle.java @@ -86,5 +86,24 @@ public interface Vehicle { * @return true if isReturnToDepot */ public abstract boolean isReturnToDepot(); - + + /** + * Returns the start-locationId of this vehicle. + */ + public abstract String getStartLocationId(); + + /** + * Returns the start-locationCoord of this vehicle. + */ + public abstract Coordinate getStartLocationCoordinate(); + + /** + * Returns the end-locationId of this vehicle. + */ + public abstract String getEndLocationId(); + + /** + * Returns the end-locationCoord of this vehicle. + */ + public abstract Coordinate getEndLocationCoordinate(); } diff --git a/jsprit-core/src/main/java/jsprit/core/problem/vehicle/VehicleImpl.java b/jsprit-core/src/main/java/jsprit/core/problem/vehicle/VehicleImpl.java index 3f40b3f1..f79ec790 100644 --- a/jsprit-core/src/main/java/jsprit/core/problem/vehicle/VehicleImpl.java +++ b/jsprit-core/src/main/java/jsprit/core/problem/vehicle/VehicleImpl.java @@ -79,6 +79,12 @@ public class VehicleImpl implements Vehicle { private double earliestStart = 0.0; private double latestArrival = Double.MAX_VALUE; + private String startLocationId; + private Coordinate startLocationCoord; + + private String endLocationId; + private Coordinate endLocationCoord; + private boolean returnToDepot = true; private VehicleType type = VehicleTypeImpl.Builder.newInstance("default", 0).build(); @@ -109,6 +115,12 @@ public class VehicleImpl implements Vehicle { /** * Sets the flag whether the vehicle must return to depot or not. * + *

If returnToDepot is true, the vehicle must return to specified end-location. If you + * omit specifying the end-location, vehicle returns to start-location (that must to be set). If + * you specify it, it returns to specified end-location. + * + *

If returnToDepot is false, the end-location of the vehicle is endogenous. + * * @param returnToDepot * @return this builder */ @@ -127,6 +139,7 @@ public class VehicleImpl implements Vehicle { */ public Builder setLocationId(String id){ this.locationId = id; + this.startLocationId = id; return this; } @@ -140,6 +153,61 @@ public class VehicleImpl implements Vehicle { */ public Builder setLocationCoord(Coordinate coord){ this.locationCoord = coord; + this.startLocationCoord = coord; + return this; + } + + /** + * Sets the start-location of this vehicle. + * + * @param startLocationId + * @return this builder + * @throws IllegalArgumentException if startLocationId is null + */ + public Builder setStartLocationId(String startLocationId){ + if(startLocationId == null) throw new IllegalArgumentException("startLocationId cannot be null"); + this.startLocationId = startLocationId; + this.locationId = startLocationId; + return this; + } + + /** + * Sets the start-coordinate of this vehicle. + * + * @param coord + * @return this builder + * @throws IllegalArgumentException if start-coordinate is null + */ + public Builder setStartLocationCoordinate(Coordinate coord){ + if(coord == null) throw new IllegalArgumentException("start-coordinate must not be null"); + this.startLocationCoord = coord; + this.locationCoord = coord; + return this; + } + + /** + * Sets the end-locationId of this vehicle. + * + * @param endLocationId + * @return this builder + * @throws IllegalArgumentException if endLocation is null + */ + public Builder setEndLocationId(String endLocationId){ + if(endLocationId == null) throw new IllegalArgumentException("end-locationId must not be null"); + this.endLocationId = endLocationId; + return this; + } + + /** + * Sets the end-coordinate of this vehicle. + * + * @param coord + * @return this builder + * @throws IllegalArgumentException if coord is null + */ + public Builder setEndLocationCoordinate(Coordinate coord){ + if(coord == null) throw new IllegalArgumentException("end-coordinate must not be null"); + this.endLocationCoord = coord; return this; } @@ -175,9 +243,21 @@ public class VehicleImpl implements Vehicle { * @throw IllegalStateException if both locationId and locationCoord is not set */ public VehicleImpl build(){ - if(locationId == null && locationCoord != null) locationId = locationCoord.toString(); + if(locationId == null && locationCoord != null) { + locationId = locationCoord.toString(); + startLocationId = locationCoord.toString(); + } if(locationId == null && locationCoord == null) throw new IllegalStateException("locationId and locationCoord is missing."); if(locationCoord == null) log.warn("locationCoord for vehicle " + id + " is missing."); + if(endLocationCoord != null && returnToDepot == false) throw new IllegalStateException("this must not be. you specified both endLocationCoord and open-routes. this is contradictory.
" + + "if you set endLocation, returnToDepot must be true. if returnToDepot is false, endLocationCoord must not be specified."); + if(endLocationId != null && returnToDepot == false) throw new IllegalStateException("this must not be. you specified both endLocationId and open-routes. this is contradictory.
" + + "if you set endLocation, returnToDepot must be true. if returnToDepot is false, endLocationCoord must not be specified."); + if(endLocationId == null && endLocationCoord != null) endLocationId = endLocationCoord.toString(); + if(endLocationId == null && endLocationCoord == null) { + endLocationId = startLocationId; + endLocationCoord = startLocationCoord; + } return new VehicleImpl(this); } @@ -216,6 +296,14 @@ public class VehicleImpl implements Vehicle { private final boolean returnToDepot; + private final Coordinate endLocationCoord; + + private final String endLocationId; + + private final Coordinate startLocationCoord; + + private final String startLocationId; + private VehicleImpl(Builder builder){ id = builder.id; type = builder.type; @@ -224,6 +312,10 @@ public class VehicleImpl implements Vehicle { earliestDeparture = builder.earliestStart; latestArrival = builder.latestArrival; returnToDepot = builder.returnToDepot; + startLocationId = builder.startLocationId; + startLocationCoord = builder.startLocationCoord; + endLocationId = builder.endLocationId; + endLocationCoord = builder.endLocationCoord; } /** @@ -273,5 +365,25 @@ public class VehicleImpl implements Vehicle { public boolean isReturnToDepot() { return returnToDepot; } + + @Override + public String getStartLocationId() { + return this.startLocationId; + } + + @Override + public Coordinate getStartLocationCoordinate() { + return this.startLocationCoord; + } + + @Override + public String getEndLocationId() { + return this.endLocationId; + } + + @Override + public Coordinate getEndLocationCoordinate() { + return this.endLocationCoord; + } } diff --git a/jsprit-core/src/test/java/jsprit/core/problem/vehicle/VehicleImplTest.java b/jsprit-core/src/test/java/jsprit/core/problem/vehicle/VehicleImplTest.java index 5f3fa4cd..6fd2fb2b 100644 --- a/jsprit-core/src/test/java/jsprit/core/problem/vehicle/VehicleImplTest.java +++ b/jsprit-core/src/test/java/jsprit/core/problem/vehicle/VehicleImplTest.java @@ -98,5 +98,107 @@ public class VehicleImplTest { assertEquals("noVehicle",v.getId()); } + @Test + public void whenStartLocationIsSet_itIsDoneCorrectly(){ + Vehicle v = VehicleImpl.Builder.newInstance("v").setStartLocationId("startLoc").build(); + assertEquals("startLoc", v.getLocationId()); + assertEquals("startLoc", v.getStartLocationId()); + } + + @Test(expected=IllegalArgumentException.class) + public void whenStartLocationIsNull_itThrowsException(){ + @SuppressWarnings("unused") + Vehicle v = VehicleImpl.Builder.newInstance("v").setStartLocationId(null).build(); + } + + @Test + public void whenStartLocationCoordIsSet_itIsDoneCorrectly(){ + Vehicle v = VehicleImpl.Builder.newInstance("v").setStartLocationCoordinate(Coordinate.newInstance(1, 2)).build(); + assertEquals(1.0, v.getStartLocationCoordinate().getX(),0.01); + assertEquals(2.0, v.getStartLocationCoordinate().getY(),0.01); + + assertEquals(1.0, v.getCoord().getX(),0.01); + assertEquals(2.0, v.getCoord().getY(),0.01); + } + + @Test(expected=IllegalArgumentException.class) + public void whenStartLocationCoordIsNull_itThrowsException(){ + @SuppressWarnings("unused") + Vehicle v = VehicleImpl.Builder.newInstance("v").setStartLocationCoordinate(null).build(); + } + + @Test + public void whenEndLocationIsSet_itIsDoneCorrectly(){ + Vehicle v = VehicleImpl.Builder.newInstance("v").setStartLocationId("startLoc").setEndLocationId("endLoc").build(); + assertEquals("startLoc", v.getStartLocationId()); + assertEquals("endLoc", v.getEndLocationId()); + } + + @Test(expected=IllegalArgumentException.class) + public void whenEndLocationIsNull_itThrowsException(){ + @SuppressWarnings("unused") + Vehicle v = VehicleImpl.Builder.newInstance("v").setEndLocationId(null).build(); + } + + @Test + public void whenEndLocationCoordIsSet_itIsDoneCorrectly(){ + Vehicle v = VehicleImpl.Builder.newInstance("v").setStartLocationId("startLoc").setEndLocationCoordinate(Coordinate.newInstance(1, 2)).build(); + assertEquals(1.0, v.getEndLocationCoordinate().getX(),0.01); + assertEquals(2.0, v.getEndLocationCoordinate().getY(),0.01); + } + + @Test(expected=IllegalArgumentException.class) + public void whenEndLocationCoordIsNull_itThrowsException(){ + @SuppressWarnings("unused") + Vehicle v = VehicleImpl.Builder.newInstance("v").setEndLocationCoordinate(null).build(); + } + + @Test + public void whenNeitherEndLocationIdNorEndLocationCoordAreSet_endLocationIdMustBeEqualToStartLocationId(){ + Vehicle v = VehicleImpl.Builder.newInstance("v").setStartLocationId("startLoc").build(); + assertEquals("startLoc", v.getEndLocationId()); + } + + @Test + public void whenNeitherEndLocationIdNorEndLocationCoordAreSet_endLocationCoordMustBeEqualToStartLocationCoord(){ + Vehicle v = VehicleImpl.Builder.newInstance("v").setStartLocationId("startLoc").build(); + assertEquals(v.getEndLocationCoordinate(), v.getStartLocationCoordinate()); + } + + @Test + public void whenNeitherEndLocationIdNorEndLocationCoordAreSet_endLocationCoordMustBeEqualToStartLocationCoordV2(){ + Vehicle v = VehicleImpl.Builder.newInstance("v").setStartLocationCoordinate(Coordinate.newInstance(1.0, 2.0)).build(); + assertEquals(v.getEndLocationCoordinate(), v.getStartLocationCoordinate()); + } + + @Test + public void whenEndLocationCoordinateIsSetButNoId_idMustBeCoordToString(){ + Vehicle v = VehicleImpl.Builder.newInstance("v").setStartLocationCoordinate(Coordinate.newInstance(1.0, 2.0)).setEndLocationCoordinate(Coordinate.newInstance(3.0, 4.0)).build(); + assertEquals(v.getEndLocationCoordinate().toString(), v.getEndLocationId()); + } + + @Test(expected=IllegalStateException.class) + public void whenEndLocationIdIsSpecifiedANDReturnToDepotIsFalse_itShouldThrowException(){ + @SuppressWarnings("unused") + Vehicle v = VehicleImpl.Builder.newInstance("v").setStartLocationCoordinate(Coordinate.newInstance(1.0, 2.0)).setEndLocationId("endLoc").setReturnToDepot(false).build(); + } + + @Test(expected=IllegalStateException.class) + public void whenEndLocationCoordIsSpecifiedANDReturnToDepotIsFalse_itShouldThrowException(){ + @SuppressWarnings("unused") + Vehicle v = VehicleImpl.Builder.newInstance("v").setStartLocationCoordinate(Coordinate.newInstance(1.0, 2.0)).setEndLocationCoordinate(Coordinate.newInstance(3, 4)).setReturnToDepot(false).build(); + } + + @Test + public void whenEndLocationCoordIsNotSpecifiedANDReturnToDepotIsFalse_endLocationCoordMustBeStartLocationCoord(){ + Vehicle v = VehicleImpl.Builder.newInstance("v").setStartLocationCoordinate(Coordinate.newInstance(1.0, 2.0)).setReturnToDepot(false).build(); + assertEquals(v.getStartLocationCoordinate(),v.getEndLocationCoordinate()); + } + + @Test + public void whenEndLocationIdIsNotSpecifiedANDReturnToDepotIsFalse_endLocationIdMustBeStartLocationId(){ + Vehicle v = VehicleImpl.Builder.newInstance("v").setStartLocationCoordinate(Coordinate.newInstance(1.0, 2.0)).setReturnToDepot(false).build(); + assertEquals(v.getStartLocationCoordinate().toString(),v.getEndLocationId()); + } }