diff --git a/jsprit-core/src/main/java/jsprit/core/problem/job/Delivery.java b/jsprit-core/src/main/java/jsprit/core/problem/job/Delivery.java index f3c29a2a..187952df 100644 --- a/jsprit-core/src/main/java/jsprit/core/problem/job/Delivery.java +++ b/jsprit-core/src/main/java/jsprit/core/problem/job/Delivery.java @@ -32,6 +32,7 @@ public class Delivery extends Service{ * @param id * @param size * @return builder + * @throws IllegalArgumentException if size < 0 or id is null */ public static Builder newInstance(String id, int size){ return new Builder(id,size); @@ -42,6 +43,7 @@ public class Delivery extends Service{ * * @param id * @param size + * @throws IllegalArgumentException if size < 0 or id is null */ Builder(String id, int size) { super(id, size); @@ -50,7 +52,7 @@ public class Delivery extends Service{ * Builds Delivery. * * @return delivery - * @throw {@link IllegalStateException} if neither locationId nor coord is set + * @throw IllegalStateException if neither locationId nor coord is set */ public Delivery build(){ if(locationId == null) { diff --git a/jsprit-core/src/main/java/jsprit/core/problem/job/Pickup.java b/jsprit-core/src/main/java/jsprit/core/problem/job/Pickup.java index f14ec34d..4fbed1a3 100644 --- a/jsprit-core/src/main/java/jsprit/core/problem/job/Pickup.java +++ b/jsprit-core/src/main/java/jsprit/core/problem/job/Pickup.java @@ -32,6 +32,7 @@ public class Pickup extends Service { * @param id * @param size * @return builder + * @throws IllegalArgumentException if size < 0 or id is null */ public static Builder newInstance(String id, int size){ return new Builder(id,size); @@ -42,6 +43,7 @@ public class Pickup extends Service { * * @param id * @param size + * @throws IllegalArgumentException if size < 0 or id is null */ Builder(String id, int size) { super(id, size); @@ -53,7 +55,7 @@ public class Pickup extends Service { *
Pickup type is "pickup" * * @return pickup - * @throw {@link IllegalStateException} if neither locationId nor coordinate has been set + * @throw IllegalStateException if neither locationId nor coordinate has been set */ public Pickup build(){ if(locationId == null) { diff --git a/jsprit-core/src/main/java/jsprit/core/problem/job/Service.java b/jsprit-core/src/main/java/jsprit/core/problem/job/Service.java index 439db4ca..a29fa874 100644 --- a/jsprit-core/src/main/java/jsprit/core/problem/job/Service.java +++ b/jsprit-core/src/main/java/jsprit/core/problem/job/Service.java @@ -46,6 +46,7 @@ public class Service implements Job { * @param id of service * @param size of capacity-demand * @return builder + * @throws IllegalArgumentException if size < 0 or id is null */ public static Builder newInstance(String id, int size){ return new Builder(id,size); @@ -70,9 +71,11 @@ public class Service implements Job { * * @param id * @param size + * @throws IllegalArgumentException if size < 0 or id is null */ Builder(String id, int size) { if(size < 0) throw new IllegalArgumentException("size must be greater than or equal to zero"); + if(id == null) throw new IllegalArgumentException("id must not be null"); this.id = id; this.demand = size; } diff --git a/jsprit-core/src/main/java/jsprit/core/problem/job/Shipment.java b/jsprit-core/src/main/java/jsprit/core/problem/job/Shipment.java index 6168aa98..79f2de82 100644 --- a/jsprit-core/src/main/java/jsprit/core/problem/job/Shipment.java +++ b/jsprit-core/src/main/java/jsprit/core/problem/job/Shipment.java @@ -3,8 +3,31 @@ package jsprit.core.problem.job; import jsprit.core.problem.solution.route.activity.TimeWindow; import jsprit.core.util.Coordinate; +/** + * Shipment is an implementation of Job and consists of a pickup and a delivery of something. + * + *
It distinguishes itself from {@link Service} as two locations are involved a pickup where usually + * something is loaded to the transport unit and a delivery where something is unloaded. + * + *
By default serviceTimes of both pickup and delivery is 0.0 and timeWindows of both is [0.0, Double.MAX_VALUE], + * + *
A shipment can be built with a builder. You can get an instance of the builder by coding Shipment.Builder.newInstance(...).
+ * This way you can specify the shipment. Once you build the shipment, it is immutable, i.e. fields/attributes cannot be changed anymore and
+ * you can only 'get' the specified values.
+ *
+ *
Note that two shipments are equal if they have the same id. + * + * @author schroeder + * + */ public class Shipment implements Job{ + /** + * Builder that builds the shipment. + * + * @author schroeder + * + */ public static class Builder { private int demand; @@ -27,56 +50,153 @@ public class Shipment implements Job{ private TimeWindow pickupTimeWindow = TimeWindow.newInstance(0.0, Double.MAX_VALUE);; + /** + * Returns a new instance of this builder. + * + * @param id + * @param size + * @return builder + * @throws IllegalArgumentException if size < 0 or id is null + */ public static Builder newInstance(String id, int size){ return new Builder(id,size); } + /** + * Constructs the builder + * + * @param id + * @param size + * @throws IllegalArgumentException if size < 0 or id is null + */ Builder(String id, int size) { if(size < 0) throw new IllegalArgumentException("size must be greater than or equal to zero"); + if(id == null) throw new IllegalArgumentException("id must not be null"); this.id = id; this.demand = size; } + /** + * Sets pickup-location. + * + * @param pickupLocation + * @return builder + * @throws IllegalArgumentException if location is null + */ public Builder setPickupLocation(String pickupLocation){ + if(pickupLocation == null) throw new IllegalArgumentException("location must not be null"); this.pickupLocation = pickupLocation; return this; } + /** + * Sets pickup-coordinate. + * + * @param pickupCoord + * @return builder + * @throws IllegalArgumentException if pickupCoord is null + */ public Builder setPickupCoord(Coordinate pickupCoord){ + if(pickupCoord == null) throw new IllegalArgumentException("coord must not be null"); this.pickupCoord = pickupCoord; return this; } + /** + * Sets pickupServiceTime. + * + *
ServiceTime is intended to be the time the implied activity takes at the pickup-location. + * + * @param serviceTime + * @return builder + * @throws IllegalArgumentException if servicTime < 0.0 + */ public Builder setPickupServiceTime(double serviceTime){ + if(serviceTime < 0.0) throw new IllegalArgumentException("serviceTime must not be < 0.0"); this.pickupServiceTime = serviceTime; return this; } + /** + * Sets the timeWindow for the pickup, i.e. the time-period in which a pickup operation is + * allowed to start. + * + *
By default timeWindow is [0.0, Double.MAX_VALUE} + * + * @param timeWindow + * @return builder + * @throws IllegalArgumentException if timeWindow is null + */ public Builder setPickupTimeWindow(TimeWindow timeWindow){ + if(timeWindow == null) throw new IllegalArgumentException("timeWindow cannot be null"); this.pickupTimeWindow = timeWindow; return this; } + /** + * Sets the delivery-location. + * + * @param deliveryLocation + * @return builder + * @throws IllegalArgumentException if location is null + */ public Builder setDeliveryLocation(String deliveryLocation){ + if(deliveryLocation == null) throw new IllegalArgumentException("delivery location must not be null"); this.deliveryLocation = deliveryLocation; return this; } + /** + * Sets delivery-coord. + * + * @param deliveryCoord + * @return builder + * @throws IllegalArgumentException if coord is null; + */ public Builder setDeliveryCoord(Coordinate deliveryCoord){ + if(deliveryCoord == null) throw new IllegalArgumentException("coord must not be null"); this.deliveryCoord = deliveryCoord; return this; } + /** + * Sets the delivery service-time. + * + *
ServiceTime is intended to be the time the implied activity takes at the delivery-location. + * + * @param deliveryServiceTime + * @return builder + * @throws IllegalArgumentException if serviceTime < 0.0 + */ public Builder setDeliveryServiceTime(double deliveryServiceTime){ + if(deliveryServiceTime < 0.0) throw new IllegalArgumentException("deliveryServiceTime must not be < 0.0"); this.deliveryServiceTime = deliveryServiceTime; return this; } + /** + * Sets the timeWindow for the delivery, i.e. the time-period in which a delivery operation is + * allowed to start. + * + *
By default timeWindow is [0.0, Double.MAX_VALUE} + * + * @param timeWindow + * @return builder + * @throws IllegalArgumentException if timeWindow is null + */ public Builder setDeliveryTimeWindow(TimeWindow timeWindow){ + if(timeWindow == null) throw new IllegalArgumentException("delivery time-window must not be null"); this.deliveryTimeWindow = timeWindow; return this; } + /** + * Builds the shipment. + * + * @return shipment + * @throws IllegalStateException if neither pickup-location nor pickup-coord is set or if neither delivery-location nor delivery-coord + * is set + */ public Shipment build(){ if(pickupLocation == null) { if(pickupCoord == null) throw new IllegalStateException("either locationId or a coordinate must be given. But is not."); @@ -90,26 +210,31 @@ public class Shipment implements Job{ } } - private int demand; + private final int demand; - private String id; + private final String id; - private String pickupLocation; + private final String pickupLocation; - private Coordinate pickupCoord; + private final Coordinate pickupCoord; - private double pickupServiceTime; + private final double pickupServiceTime; - private String deliveryLocation; + private final String deliveryLocation; - private Coordinate deliveryCoord; + private final Coordinate deliveryCoord; - private double deliveryServiceTime; + private final double deliveryServiceTime; - private TimeWindow deliveryTimeWindow; + private final TimeWindow deliveryTimeWindow; - private TimeWindow pickupTimeWindow; + private final TimeWindow pickupTimeWindow; + /** + * Constructs the shipment. + * + * @param builder + */ Shipment(Builder builder){ this.id = builder.id; this.demand = builder.demand; @@ -133,34 +258,76 @@ public class Shipment implements Job{ return demand; } + /** + * Returns the pickup-location. + * + * @return pickup-location + */ public String getPickupLocation() { return pickupLocation; } + /** + * Returns the pickup-coordinate. + * + * @return coordinate of the pickup + */ public Coordinate getPickupCoord() { return pickupCoord; } + /** + * Returns the pickup service-time. + * + *
By default service-time is 0.0. + * + * @return service-time + */ public double getPickupServiceTime() { return pickupServiceTime; } + /** + * Returns delivery-location. + * + * @return delivery-location + */ public String getDeliveryLocation() { return deliveryLocation; } + /** + * Returns coordinate of the delivery. + * + * @return coordinate of delivery + */ public Coordinate getDeliveryCoord() { return deliveryCoord; } + /** + * Returns service-time of delivery. + * + * @return service-time of delivery + */ public double getDeliveryServiceTime() { return deliveryServiceTime; } + /** + * Returns the time-window of delivery. + * + * @return time-window of delivery + */ public TimeWindow getDeliveryTimeWindow() { return deliveryTimeWindow; } + /** + * Returns the time-window of pickup. + * + * @return time-window of pickup + */ public TimeWindow getPickupTimeWindow() { return pickupTimeWindow; } @@ -173,6 +340,11 @@ public class Shipment implements Job{ return result; } + /** + * Two shipments are equal if they have the same id. + * + * @return true if shipments are equal (have the same id) + */ @Override public boolean equals(Object obj) { if (this == obj) diff --git a/jsprit-core/src/test/java/jsprit/core/problem/job/ServiceTest.java b/jsprit-core/src/test/java/jsprit/core/problem/job/ServiceTest.java index 3a1c82f0..05c5d753 100644 --- a/jsprit-core/src/test/java/jsprit/core/problem/job/ServiceTest.java +++ b/jsprit-core/src/test/java/jsprit/core/problem/job/ServiceTest.java @@ -16,7 +16,7 @@ ******************************************************************************/ package jsprit.core.problem.job; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; diff --git a/jsprit-core/src/test/java/jsprit/core/problem/job/ShipmentTest.java b/jsprit-core/src/test/java/jsprit/core/problem/job/ShipmentTest.java index 9fff73b9..1ff658c9 100644 --- a/jsprit-core/src/test/java/jsprit/core/problem/job/ShipmentTest.java +++ b/jsprit-core/src/test/java/jsprit/core/problem/job/ShipmentTest.java @@ -1,8 +1,8 @@ package jsprit.core.problem.job; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; -import jsprit.core.problem.job.Shipment; import jsprit.core.problem.solution.route.activity.TimeWindow; import jsprit.core.util.Coordinate; @@ -38,20 +38,159 @@ public class ShipmentTest { assertEquals(10,one.getCapacityDemand()); } + @Test(expected=IllegalArgumentException.class) + public void whenShipmentIsBuiltWithNegativeDemand_itShouldThrowException(){ + @SuppressWarnings("unused") + Shipment one = Shipment.Builder.newInstance("s", -10).setPickupLocation("foo").setDeliveryLocation("foofoo").build(); + } + + @Test(expected=IllegalArgumentException.class) + public void whenIdIsNull_itShouldThrowException(){ + @SuppressWarnings("unused") + Shipment one = Shipment.Builder.newInstance(null, 10).setPickupLocation("foo").setDeliveryLocation("foofoo").build(); + } + @Test - public void whenShipmentIsDefined_itsFieldsShouldBeDefinedCorrectly(){ - Shipment one = Shipment.Builder.newInstance("s", 10).setPickupLocation("foo").setPickupCoord(Coordinate.newInstance(0, 0)).setPickupServiceTime(1.0) - .setPickupTimeWindow(TimeWindow.newInstance(0.0, 1.0)) - .setDeliveryLocation("foofoo").setDeliveryServiceTime(20).setDeliveryCoord(Coordinate.newInstance(1, 1)). - setDeliveryTimeWindow(TimeWindow.newInstance(1.0, 2.0)).build(); - assertEquals("s",one.getId()); - assertEquals(10,one.getCapacityDemand()); - assertEquals("foo",one.getPickupLocation()); - assertEquals(0,one.getPickupCoord().getX(),0.01); - assertEquals(1.0,one.getPickupServiceTime(),0.01); - assertEquals("foofoo",one.getDeliveryLocation()); - assertEquals(20.0,one.getDeliveryServiceTime(),0.01); - assertEquals(1.0,one.getDeliveryCoord().getX(),0.01); - assertEquals(1.0,one.getDeliveryTimeWindow().getStart(),0.01); + public void whenCallingForANewBuilderInstance_itShouldReturnBuilderCorrectly(){ + Shipment.Builder builder = Shipment.Builder.newInstance("s", 0); + assertNotNull(builder); + } + + @Test(expected=IllegalStateException.class) + public void whenNeitherPickupLocationIdNorPickupCoord_itThrowsException(){ + @SuppressWarnings("unused") + Shipment s = Shipment.Builder.newInstance("s", 0).setDeliveryLocation("delLoc").build(); + } + + @Test(expected=IllegalStateException.class) + public void whenNeitherDeliveryLocationIdNorDeliveryCoord_itThrowsException(){ + @SuppressWarnings("unused") + Shipment s = Shipment.Builder.newInstance("s", 0).setPickupLocation("pickLoc").build(); + } + + @Test + public void whenPickupLocationIdIsSet_itShouldBeDoneCorrectly(){ + Shipment s = Shipment.Builder.newInstance("s", 0).setDeliveryLocation("delLoc").setPickupLocation("pickLoc").build(); + assertEquals("pickLoc",s.getPickupLocation()); + } + + @Test(expected=IllegalArgumentException.class) + public void whenPickupLocationIsNull_itThrowsException(){ + @SuppressWarnings("unused") + Shipment.Builder builder = Shipment.Builder.newInstance("s", 0).setPickupLocation(null); + } + + @Test + public void whenPickupCoordIsSet_itShouldBeDoneCorrectly(){ + Shipment s = Shipment.Builder.newInstance("s", 0).setDeliveryLocation("delLoc").setPickupLocation("pickLoc").setPickupCoord(Coordinate.newInstance(1, 2)).build(); + assertEquals(1.0,s.getPickupCoord().getX(),0.01); + assertEquals(2.0,s.getPickupCoord().getY(),0.01); + } + + @Test(expected=IllegalArgumentException.class) + public void whenPickupCoordIsNull_itThrowsException(){ + @SuppressWarnings("unused") + Shipment.Builder builder = Shipment.Builder.newInstance("s", 0).setPickupCoord(null); + } + + @Test + public void whenDeliveryLocationIdIsSet_itShouldBeDoneCorrectly(){ + Shipment s = Shipment.Builder.newInstance("s", 0).setDeliveryLocation("delLoc").setPickupLocation("pickLoc").build(); + assertEquals("delLoc",s.getDeliveryLocation()); + } + + @Test(expected=IllegalArgumentException.class) + public void whenDeliveryLocationIsNull_itThrowsException(){ + @SuppressWarnings("unused") + Shipment.Builder builder = Shipment.Builder.newInstance("s", 0).setDeliveryLocation(null); + } + + @Test + public void whenDeliveryCoordIsSet_itShouldBeDoneCorrectly(){ + Shipment s = Shipment.Builder.newInstance("s", 0).setDeliveryLocation("delLoc").setPickupLocation("pickLoc").setDeliveryCoord(Coordinate.newInstance(1, 2)).build(); + assertEquals(1.0,s.getDeliveryCoord().getX(),0.01); + assertEquals(2.0,s.getDeliveryCoord().getY(),0.01); + } + + @Test(expected=IllegalArgumentException.class) + public void whenDeliveryCoordIsNull_itThrowsException(){ + @SuppressWarnings("unused") + Shipment.Builder builder = Shipment.Builder.newInstance("s", 0).setDeliveryCoord(null); + } + + @Test + public void whenPickupServiceTimeIsNotSet_itShouldBeZero(){ + Shipment s = Shipment.Builder.newInstance("s", 0).setDeliveryLocation("delLoc").setPickupLocation("pickLoc").build(); + assertEquals(0.0,s.getPickupServiceTime(),0.01); + } + + @Test + public void whenDeliveryServiceTimeIsNotSet_itShouldBeZero(){ + Shipment s = Shipment.Builder.newInstance("s", 0).setDeliveryLocation("delLoc").setPickupLocation("pickLoc").build(); + assertEquals(0.0,s.getDeliveryServiceTime(),0.01); + } + + @Test + public void whenPickupServiceTimeIsSet_itShouldBeDoneCorrectly(){ + Shipment s = Shipment.Builder.newInstance("s", 0).setPickupServiceTime(2.0).setDeliveryLocation("delLoc").setPickupLocation("pickLoc").build(); + assertEquals(2.0,s.getPickupServiceTime(),0.01); + } + + @Test(expected=IllegalArgumentException.class) + public void whenPickupServiceIsSmallerThanZero_itShouldThrowException(){ + @SuppressWarnings("unused") + Shipment s = Shipment.Builder.newInstance("s", 0).setPickupServiceTime(-2.0).setDeliveryLocation("delLoc").setPickupLocation("pickLoc").build(); + } + + @Test + public void whenDeliveryServiceTimeIsSet_itShouldBeDoneCorrectly(){ + Shipment s = Shipment.Builder.newInstance("s", 0).setDeliveryServiceTime(2.0).setDeliveryLocation("delLoc").setPickupLocation("pickLoc").build(); + assertEquals(2.0,s.getDeliveryServiceTime(),0.01); + } + + @Test(expected=IllegalArgumentException.class) + public void whenDeliveryServiceIsSmallerThanZero_itShouldThrowException(){ + @SuppressWarnings("unused") + Shipment s = Shipment.Builder.newInstance("s", 0).setDeliveryServiceTime(-2.0).setDeliveryLocation("delLoc").setPickupLocation("pickLoc").build(); + } + + @Test + public void whenPickupTimeWindowIsNotSet_itShouldBeTheDefaultOne(){ + Shipment s = Shipment.Builder.newInstance("s", 0).setDeliveryLocation("delLoc").setPickupLocation("pickLoc").build(); + assertEquals(0.0,s.getPickupTimeWindow().getStart(),0.01); + assertEquals(Double.MAX_VALUE,s.getPickupTimeWindow().getEnd(),0.01); + } + + @Test(expected=IllegalArgumentException.class) + public void whenPickupTimeWindowIsNull_itShouldThrowException(){ + @SuppressWarnings("unused") + Shipment s = Shipment.Builder.newInstance("s", 0).setPickupTimeWindow(null).setDeliveryLocation("delLoc").setPickupLocation("pickLoc").build(); + } + + @Test + public void whenPickupTimeWindowIsSet_itShouldBeDoneCorrectly(){ + Shipment s = Shipment.Builder.newInstance("s", 0).setPickupTimeWindow(TimeWindow.newInstance(1, 2)).setDeliveryLocation("delLoc").setPickupLocation("pickLoc").build(); + assertEquals(1.0,s.getPickupTimeWindow().getStart(),0.01); + assertEquals(2.0,s.getPickupTimeWindow().getEnd(),0.01); + } + + @Test + public void whenDeliveryTimeWindowIsNotSet_itShouldBeTheDefaultOne(){ + Shipment s = Shipment.Builder.newInstance("s", 0).setDeliveryLocation("delLoc").setPickupLocation("pickLoc").build(); + assertEquals(0.0,s.getDeliveryTimeWindow().getStart(),0.01); + assertEquals(Double.MAX_VALUE,s.getDeliveryTimeWindow().getEnd(),0.01); + } + + @Test(expected=IllegalArgumentException.class) + public void whenDeliveryTimeWindowIsNull_itShouldThrowException(){ + @SuppressWarnings("unused") + Shipment s = Shipment.Builder.newInstance("s", 0).setDeliveryTimeWindow(null).setDeliveryLocation("delLoc").setPickupLocation("pickLoc").build(); + } + + @Test + public void whenDeliveryTimeWindowIsSet_itShouldBeDoneCorrectly(){ + Shipment s = Shipment.Builder.newInstance("s", 0).setDeliveryTimeWindow(TimeWindow.newInstance(1, 2)).setDeliveryLocation("delLoc").setPickupLocation("pickLoc").build(); + assertEquals(1.0,s.getDeliveryTimeWindow().getStart(),0.01); + assertEquals(2.0,s.getDeliveryTimeWindow().getEnd(),0.01); } }