Ver código fonte

Made persistence configuration less intrusive by going with defaults everywhere, making it easier on the eyes. Empty default constructors are pushed to the bottom of the class.

Introduced CarrierId and embedded the DeliveryHistory in Cargo, aligning the persistence with the model as described in the DDD book.

Location.NULL changed name to Location.UNKNOWN.
peter_backlund 18 anos atrás
pai
commit
cd7e3969e7

+ 11
- 15
dddsample/src/main/java/se/citerus/dddsample/domain/Cargo.java Ver arquivo

@@ -5,7 +5,9 @@ import org.apache.commons.lang.builder.HashCodeBuilder;
5 5
 import org.apache.commons.lang.builder.ReflectionToStringBuilder;
6 6
 import org.apache.commons.lang.builder.ToStringStyle;
7 7
 
8
-import javax.persistence.*;
8
+import javax.persistence.EmbeddedId;
9
+import javax.persistence.Entity;
10
+import javax.persistence.ManyToOne;
9 11
 
10 12
 
11 13
 /**
@@ -13,27 +15,19 @@ import javax.persistence.*;
13 15
  * of convenience operation for finding current destination etc.
14 16
  */
15 17
 @Entity
16
-@Table(name = "cargo")
17 18
 public class Cargo {
18 19
 
19 20
   @EmbeddedId
20 21
   private TrackingId trackingId;
21 22
 
22
-  @ManyToOne(fetch = FetchType.EAGER)
23
-  @JoinColumn(name = "origin_location_fk")
23
+  @ManyToOne
24 24
   private Location origin;
25
-
26
-  @ManyToOne(fetch = FetchType.EAGER)
27
-  @JoinColumn(name = "final_destination_location_fk")
25
+  
26
+  @ManyToOne
28 27
   private Location finalDestination;
29 28
 
30
-  @OneToOne(fetch = FetchType.LAZY)
31
-  @JoinColumn(name = "delivery_history_fk")
32 29
   private DeliveryHistory history;
33 30
 
34
-  // Needed by Hibernate
35
-  Cargo() {}
36
-
37 31
   public Cargo(TrackingId trackingId, Location origin, Location finalDestination) {
38 32
     this.trackingId = trackingId;
39 33
     this.origin = origin;
@@ -55,11 +49,11 @@ public class Cargo {
55 49
   }
56 50
 
57 51
   public Location getCurrentLocation() {
58
-    HandlingEvent lastEvent = history.last();
52
+    HandlingEvent lastEvent = history.lastEvent();
59 53
     
60 54
     // If we have no last event, we have not even received the package. Return unknown location
61 55
     if (lastEvent == null) {
62
-      return Location.NULL;
56
+      return Location.UNKNOWN;
63 57
     }
64 58
    
65 59
     Location location = lastEvent.getLocation();
@@ -67,7 +61,7 @@ public class Cargo {
67 61
     // If the last handling event has no idea of where the cargo is due to lack of CarrierMovement (like for CLAIM or RECEIVE events)
68 62
     // location must be calculated based on event type and origin or final destination
69 63
     // TODO: Maybe we need to refactor HandlingEvent.
70
-    if (location == Location.NULL){
64
+    if (location == Location.UNKNOWN){
71 65
       location = (lastEvent.getType() == HandlingEvent.Type.CLAIM) ? finalDestination : origin;
72 66
     }
73 67
       
@@ -116,5 +110,7 @@ public class Cargo {
116 110
     .toHashCode();
117 111
   }
118 112
   
113
+  // Needed by Hibernate
114
+  Cargo() {}
119 115
   
120 116
 }

+ 35
- 0
dddsample/src/main/java/se/citerus/dddsample/domain/CarrierId.java Ver arquivo

@@ -0,0 +1,35 @@
1
+package se.citerus.dddsample.domain;
2
+
3
+import org.apache.commons.lang.builder.EqualsBuilder;
4
+import org.apache.commons.lang.builder.HashCodeBuilder;
5
+
6
+import javax.persistence.Embeddable;
7
+import java.io.Serializable;
8
+
9
+/**
10
+ * Identifies a particular carrier (vehicle).
11
+ */
12
+@Embeddable
13
+public class CarrierId implements Serializable {
14
+
15
+  private String id;
16
+
17
+  public CarrierId(String id) {
18
+    this.id = id;
19
+  }
20
+
21
+  public String getId() {
22
+    return id;
23
+  }
24
+
25
+  @Override
26
+  public boolean equals(Object obj) {
27
+    return EqualsBuilder.reflectionEquals(this, obj);
28
+  }
29
+
30
+  @Override
31
+  public int hashCode() {
32
+    return HashCodeBuilder.reflectionHashCode(this);
33
+  }
34
+
35
+}

+ 19
- 11
dddsample/src/main/java/se/citerus/dddsample/domain/CarrierMovement.java Ver arquivo

@@ -1,27 +1,32 @@
1 1
 package se.citerus.dddsample.domain;
2 2
 
3
-import javax.persistence.*;
3
+import javax.persistence.EmbeddedId;
4
+import javax.persistence.Entity;
5
+import javax.persistence.ManyToOne;
6
+
4 7
 
5 8
 @Entity
6
-@Table(name = "carrier_movement")
7 9
 public class CarrierMovement {
8 10
 
9
-  @Id
10
-  private Long id;
11
+  @EmbeddedId
12
+  private CarrierId carrierId;
11 13
 
12
-  @ManyToOne(fetch = FetchType.EAGER)
13
-  @JoinColumn(name = "from_location_fk")
14
-  private final Location from;
14
+  @ManyToOne
15
+  private Location from;
15 16
 
16
-  @ManyToOne(fetch = FetchType.EAGER)
17
-  @JoinColumn(name = "to_location_fk")
18
-  private final Location to;
17
+  @ManyToOne
18
+  private Location to;
19 19
 
20
-  public CarrierMovement(Location from, Location to) {
20
+  public CarrierMovement(CarrierId carrierId, Location from, Location to) {
21
+    this.carrierId = carrierId;
21 22
     this.from = from;
22 23
     this.to = to;
23 24
   }
24 25
 
26
+  public CarrierId carrierId() {
27
+    return carrierId;
28
+  }
29
+
25 30
   public Location from() {
26 31
     return from;
27 32
   }
@@ -30,4 +35,7 @@ public class CarrierMovement {
30 35
     return to;
31 36
   }
32 37
 
38
+  // Needed by Hibernate
39
+  CarrierMovement() {}
40
+
33 41
 }

+ 29
- 21
dddsample/src/main/java/se/citerus/dddsample/domain/DeliveryHistory.java Ver arquivo

@@ -2,31 +2,30 @@ package se.citerus.dddsample.domain;
2 2
 
3 3
 import org.apache.commons.lang.builder.ReflectionToStringBuilder;
4 4
 import org.apache.commons.lang.builder.ToStringStyle;
5
-import org.hibernate.annotations.Sort;
6
-import org.hibernate.annotations.SortType;
7 5
 
8
-import javax.persistence.*;
9
-import java.util.SortedSet;
10
-import java.util.TreeSet;
6
+import javax.persistence.Embeddable;
7
+import javax.persistence.OneToMany;
8
+import java.util.*;
11 9
 
12 10
 /**
13 11
  * A wrapper class that holds a sorted set of HandlingEvents. The set can not contain events with the same timestamp.
14 12
  * 
15 13
  */
16
-@Entity
17
-@Table(name = "delivery_history")
14
+@Embeddable
18 15
 public class DeliveryHistory {
19 16
 
20
-  @Id
21
-  private Long id;
17
+  @OneToMany
18
+  private final Set<HandlingEvent> events = new HashSet<HandlingEvent>();
22 19
 
23
-  @OneToMany(fetch = FetchType.EAGER)
24
-  @JoinColumn(name = "delivery_history_fk")
25
-  @Sort(type = SortType.NATURAL)
26
-  private final SortedSet<HandlingEvent> events = new TreeSet<HandlingEvent>();
20
+  private static final HandlingEventByTimeComparator HANDLING_EVENT_COMPARATOR = new HandlingEventByTimeComparator();
27 21
 
28
-  public SortedSet<HandlingEvent> getEvents() {
29
-    return events;
22
+  /**
23
+   * @return An <b>unmodifiable</b> list of handling events, ordered by the time the events occured.
24
+   */
25
+  public List<HandlingEvent> eventsOrderedByTime() {
26
+    List<HandlingEvent> eventList = new ArrayList<HandlingEvent>(events);
27
+    Collections.sort(eventList, HANDLING_EVENT_COMPARATOR);
28
+    return Collections.unmodifiableList(eventList);
30 29
   }
31 30
 
32 31
   /**
@@ -35,18 +34,27 @@ public class DeliveryHistory {
35 34
    * @throws IllegalArgumentException if an event is not unique. Uniquness are evaluated by checking that compareTo() not returns 0.
36 35
    * @param event
37 36
    */
38
-  public void addEvent(HandlingEvent event) {
39
-    if (!events.add(event)){
40
-      throw new IllegalArgumentException("HandlingEvent are not evaluated to be unique");
41
-    }
37
+  public void addEvent(HandlingEvent... event) {
38
+      events.addAll(Arrays.asList(event));
42 39
   }
43 40
 
44
-  public HandlingEvent last() {
45
-    return events.isEmpty() ? null : events.last();
41
+  public HandlingEvent lastEvent() {
42
+    if (events.isEmpty()) {
43
+      return null;
44
+    } else {
45
+      List<HandlingEvent> orderedEvents = eventsOrderedByTime();
46
+      return orderedEvents.get(orderedEvents.size() - 1);
47
+    }
46 48
   }
47 49
 
48 50
   @Override
49 51
   public String toString() {
50 52
     return ReflectionToStringBuilder.toString(this, ToStringStyle.MULTI_LINE_STYLE);
51 53
   }
54
+
55
+  private static class HandlingEventByTimeComparator implements Comparator<HandlingEvent> {
56
+    public int compare(HandlingEvent o1, HandlingEvent o2) {
57
+      return o1.getTime().compareTo(o2.getTime());
58
+    }
59
+  }
52 60
 }

+ 15
- 20
dddsample/src/main/java/se/citerus/dddsample/domain/HandlingEvent.java Ver arquivo

@@ -17,21 +17,17 @@ import java.util.Set;
17 17
  * 
18 18
  */
19 19
 @Entity
20
-@Table(name = "handling_events")
21
-public class HandlingEvent implements Comparable<HandlingEvent> {
20
+public class HandlingEvent {
22 21
 
23 22
   @Id
24 23
   private Long id;
25 24
 
26
-  @Enumerated(value = EnumType.STRING)
27
-  @Column(name = "type")
25
+  @Enumerated
28 26
   private Type type;
29 27
 
30
-  @ManyToOne(fetch = FetchType.EAGER)
31
-  @JoinColumn(name = "carrier_movement_fk")
28
+  @ManyToOne
32 29
   private CarrierMovement carrierMovement;
33 30
   
34
-  @Column(name = "time")
35 31
   private Date time;
36 32
 
37 33
   @Transient /*TODO: Change to many-to-many if we decide on that approach*/
@@ -44,8 +40,9 @@ public class HandlingEvent implements Comparable<HandlingEvent> {
44 40
   // Exclude the id field from equals() and hashcode()
45 41
   private static final String[] excludedFields = {"id"};
46 42
 
47
-  // Needed by Hibernate
48
-  HandlingEvent() {}
43
+  public HandlingEvent(Date time, Type type) {
44
+    this(time, type, null);
45
+  }
49 46
 
50 47
   public HandlingEvent(Date time, Type type, CarrierMovement carrierMovement) {
51 48
     this.time = time;
@@ -70,8 +67,8 @@ public class HandlingEvent implements Comparable<HandlingEvent> {
70 67
    * Returns the Location of the Cargo. The location is calculated based on the following rules:
71 68
    * <br>For
72 69
    * <ul>
73
-   * <li> RECEIVE events: Location.NULL is returned. This basically means that the cargo is at its origin but not yet loaded on a CarrierMovment
74
-   * <li> CLAIM events: Location.NULL is returned. This means that the cargo is at its final destination and has been unloaded and claimed by the customer.
70
+   * <li> RECEIVE events: Location.UNKNOWN is returned. This basically means that the cargo is at its origin but not yet loaded on a CarrierMovment
71
+   * <li> CLAIM events: Location.UNKNOWN is returned. This means that the cargo is at its final destination and has been unloaded and claimed by the customer.
75 72
    * <li> LOAD events: The from Location is returned.
76 73
    * <li> UNLOAD events: The to Location is returned.
77 74
    * </ul> 
@@ -79,7 +76,7 @@ public class HandlingEvent implements Comparable<HandlingEvent> {
79 76
    * @return The Location
80 77
    */
81 78
   public Location getLocation() {
82
-    Location location = Location.NULL;
79
+    Location location = Location.UNKNOWN;
83 80
     
84 81
     //My gosh! A switch statement....
85 82
     switch (type) {
@@ -103,7 +100,7 @@ public class HandlingEvent implements Comparable<HandlingEvent> {
103 100
   /**
104 101
    * Register a set of Cargos
105 102
    * 
106
-   * @param cargos
103
+   * @param cargosToRegister
107 104
    */
108 105
   public void register(Set<Cargo> cargosToRegister) {
109 106
     this.cargos.addAll(cargosToRegister);
@@ -112,8 +109,7 @@ public class HandlingEvent implements Comparable<HandlingEvent> {
112 109
   public Set<Cargo> getRegisterdCargos(){
113 110
     return cargos;
114 111
   }
115
-  
116
-  
112
+
117 113
   @Override
118 114
   public boolean equals(Object obj) {
119 115
     return EqualsBuilder.reflectionEquals(this, obj, excludedFields);
@@ -121,15 +117,14 @@ public class HandlingEvent implements Comparable<HandlingEvent> {
121 117
 
122 118
   @Override
123 119
   public int hashCode() {
124
-    return HashCodeBuilder.reflectionHashCode(this);
125
-  }
126
-
127
-  public int compareTo(HandlingEvent o) {
128
-    return time.compareTo(o.getTime());
120
+    return HashCodeBuilder.reflectionHashCode(this, excludedFields);
129 121
   }
130 122
 
131 123
   public static Type parseType(String type) {
132 124
     return Type.valueOf(type);
133 125
   }
134 126
 
127
+  // Needed by Hibernate
128
+  HandlingEvent() {}
129
+
135 130
 }

+ 6
- 10
dddsample/src/main/java/se/citerus/dddsample/domain/Location.java Ver arquivo

@@ -3,31 +3,24 @@ package se.citerus.dddsample.domain;
3 3
 import org.apache.commons.lang.builder.EqualsBuilder;
4 4
 import org.apache.commons.lang.builder.HashCodeBuilder;
5 5
 
6
-import javax.persistence.Column;
7 6
 import javax.persistence.Entity;
8 7
 import javax.persistence.Id;
9
-import javax.persistence.Table;
10 8
 
11 9
 @Entity
12
-@Table(name = "locations")
13 10
 public class Location {
14 11
   /**
15
-   * The NULL Location object
12
+   * Special Location object that marks an unknown location.
16 13
    */
17
-  public static final Location NULL = new Location("Unknown");
14
+  public static final Location UNKNOWN = new Location("Unknown");
18 15
 
19 16
   @Id
20 17
   private Long id;
21 18
 
22
-  @Column(name = "unlocode")
23 19
   private String unlocode;
24 20
 
25 21
   // Exclude the id field from equals() and hashcode()
26 22
   private static final String[] excludedFields = {"id"};
27 23
 
28
-  // Needed by Hibernate
29
-  Location() {}
30
-
31 24
   public Location(String unlocode) {
32 25
     this.unlocode = unlocode;
33 26
   }
@@ -38,7 +31,7 @@ public class Location {
38 31
 
39 32
   @Override
40 33
   public boolean equals(Object obj) {
41
-    if (this == NULL || obj == NULL) {
34
+    if (this == UNKNOWN || obj == UNKNOWN) {
42 35
       return this == obj;
43 36
     }
44 37
     return EqualsBuilder.reflectionEquals(this, obj, excludedFields);
@@ -54,4 +47,7 @@ public class Location {
54 47
     return unlocode;
55 48
   }
56 49
 
50
+  // Needed by Hibernate
51
+  Location() {}
52
+
57 53
 }

+ 0
- 4
dddsample/src/main/java/se/citerus/dddsample/domain/TrackingId.java Ver arquivo

@@ -3,7 +3,6 @@ package se.citerus.dddsample.domain;
3 3
 import org.apache.commons.lang.builder.EqualsBuilder;
4 4
 import org.apache.commons.lang.builder.HashCodeBuilder;
5 5
 
6
-import javax.persistence.Column;
7 6
 import javax.persistence.Embeddable;
8 7
 import java.io.Serializable;
9 8
 
@@ -17,11 +16,8 @@ public class TrackingId implements Serializable {
17 16
 
18 17
   private static final long serialVersionUID = 6273117599327914522L;
19 18
 
20
-  @Column(name = "tracking_id")
21 19
   private String id;
22 20
 
23
-  TrackingId() {}
24
-
25 21
   public TrackingId(String id) {
26 22
     this.id = id;
27 23
   }

+ 13
- 7
dddsample/src/main/java/se/citerus/dddsample/repository/CarrierRepositoryInMem.java Ver arquivo

@@ -1,10 +1,11 @@
1 1
 package se.citerus.dddsample.repository;
2 2
 
3
-import java.util.HashMap;
4
-
3
+import se.citerus.dddsample.domain.CarrierId;
5 4
 import se.citerus.dddsample.domain.CarrierMovement;
6 5
 import se.citerus.dddsample.domain.Location;
7 6
 
7
+import java.util.HashMap;
8
+
8 9
 public class CarrierRepositoryInMem implements CarrierRepository {
9 10
   private HashMap<String, CarrierMovement> carriers;
10 11
 
@@ -14,11 +15,16 @@ public class CarrierRepositoryInMem implements CarrierRepository {
14 15
   }
15 16
 
16 17
   private void setup() {
17
-    final CarrierMovement stockholmToHamburg = new CarrierMovement(new Location("SESTO"), new Location("DEHAM"));
18
-    final CarrierMovement hamburgToHongKong = new CarrierMovement(new Location("DEHAM"), new Location("CNHKG"));
19
-    final CarrierMovement melbourneToTokyo = new CarrierMovement(new Location("AUMEL"), new Location("JPTOK"));
20
-    final CarrierMovement tokyoToLosAngeles = new CarrierMovement(new Location("JPTOK"), new Location("USLA"));
21
-    final CarrierMovement stockholmToHelsinki = new CarrierMovement(new Location("SESTO"), new Location("FIHEL"));
18
+    final CarrierMovement stockholmToHamburg = new CarrierMovement(
19
+            new CarrierId("CAR_001"), new Location("SESTO"), new Location("DEHAM"));
20
+    final CarrierMovement hamburgToHongKong = new CarrierMovement(
21
+            new CarrierId("CAR_002"), new Location("DEHAM"), new Location("CNHKG"));
22
+    final CarrierMovement melbourneToTokyo = new CarrierMovement(
23
+            new CarrierId("CAR_003"), new Location("AUMEL"), new Location("JPTOK"));
24
+    final CarrierMovement tokyoToLosAngeles = new CarrierMovement(
25
+            new CarrierId("CAR_004"), new Location("JPTOK"), new Location("USLA"));
26
+    final CarrierMovement stockholmToHelsinki = new CarrierMovement(
27
+            new CarrierId("CAR_005"), new Location("SESTO"), new Location("FIHEL"));
22 28
     
23 29
     carriers.put("SESTO_DEHAM", stockholmToHamburg);
24 30
     carriers.put("DEHAM_CNHKG", hamburgToHongKong);

+ 8
- 11
dddsample/src/main/java/se/citerus/dddsample/repository/HandlingEventRepositoryInMem.java Ver arquivo

@@ -1,5 +1,10 @@
1 1
 package se.citerus.dddsample.repository;
2 2
 
3
+import org.apache.commons.logging.Log;
4
+import org.apache.commons.logging.LogFactory;
5
+import se.citerus.dddsample.domain.*;
6
+import se.citerus.dddsample.domain.HandlingEvent.Type;
7
+
3 8
 import java.text.DateFormat;
4 9
 import java.text.ParseException;
5 10
 import java.text.SimpleDateFormat;
@@ -8,16 +13,6 @@ import java.util.HashMap;
8 13
 import java.util.HashSet;
9 14
 import java.util.Set;
10 15
 
11
-import org.apache.commons.logging.Log;
12
-import org.apache.commons.logging.LogFactory;
13
-
14
-import se.citerus.dddsample.domain.Cargo;
15
-import se.citerus.dddsample.domain.CarrierMovement;
16
-import se.citerus.dddsample.domain.HandlingEvent;
17
-import se.citerus.dddsample.domain.Location;
18
-import se.citerus.dddsample.domain.TrackingId;
19
-import se.citerus.dddsample.domain.HandlingEvent.Type;
20
-
21 16
 public class HandlingEventRepositoryInMem implements HandlingEventRepository{
22 17
   private HashMap<String, HandlingEvent> eventDB;
23 18
   private CarrierRepository carrierRepository;
@@ -64,7 +59,9 @@ public class HandlingEventRepositoryInMem implements HandlingEventRepository{
64 59
     final Cargo cargoABC = new Cargo(new TrackingId("ABC"), new Location("SESTO"), new Location("FIHEL"));
65 60
     registerEvent(cargoABC, "2008-01-01", HandlingEvent.Type.RECEIVE, null);
66 61
     
67
-    final CarrierMovement stockholmToHelsinki = new CarrierMovement(new Location("SESTO"), new Location("FIHEL"));
62
+    final CarrierMovement stockholmToHelsinki = new CarrierMovement(
63
+            new CarrierId("CAR_001"), new Location("SESTO"), new Location("FIHEL"));
64
+
68 65
     registerEvent(cargoABC, "2008-01-02", HandlingEvent.Type.LOAD, stockholmToHelsinki);
69 66
     registerEvent(cargoABC, "2008-01-03", HandlingEvent.Type.UNLOAD, stockholmToHelsinki);
70 67
     registerEvent(cargoABC, "2008-01-05", HandlingEvent.Type.CLAIM, null);

+ 0
- 1
dddsample/src/main/resources/context-persistence.xml Ver arquivo

@@ -21,7 +21,6 @@
21 21
       <list>
22 22
         <value>se.citerus.dddsample.domain.Cargo</value>
23 23
         <value>se.citerus.dddsample.domain.Location</value>
24
-        <value>se.citerus.dddsample.domain.DeliveryHistory</value>
25 24
         <value>se.citerus.dddsample.domain.HandlingEvent</value>
26 25
         <value>se.citerus.dddsample.domain.CarrierMovement</value>
27 26
       </list>

+ 3
- 3
dddsample/src/test/java/se/citerus/dddsample/domain/CargoRepositoryTest.java Ver arquivo

@@ -17,10 +17,10 @@ public class CargoRepositoryTest extends AbstractTransactionalDataSourceSpringCo
17 17
 
18 18
   protected void onSetUpInTransaction() throws Exception {
19 19
     String[] testData = {
20
-            "INSERT INTO locations (id, unlocode) VALUES (1, 'SESTO')",
21
-            "INSERT INTO locations (id, unlocode) VALUES (2, 'CNHKG')",
20
+            "INSERT INTO Location (id, unlocode) VALUES (1, 'SESTO')",
21
+            "INSERT INTO Location (id, unlocode) VALUES (2, 'CNHKG')",
22 22
 
23
-            "INSERT INTO cargo (tracking_id, origin_location_fk, final_destination_location_fk) " +
23
+            "INSERT INTO Cargo (id, origin_id, finalDestination_id) " +
24 24
                     "VALUES ('XYZ', 1, 2)"
25 25
     };
26 26
     jdbcTemplate.batchUpdate(testData);

+ 21
- 11
dddsample/src/test/java/se/citerus/dddsample/domain/CargoTest.java Ver arquivo

@@ -14,7 +14,7 @@ public class CargoTest extends TestCase {
14 14
     Location origin = new Location("SESTO");
15 15
     Cargo cargo = new Cargo(new TrackingId("XYZ"), origin, destination);
16 16
 
17
-    assertEquals(Location.NULL, cargo.getCurrentLocation());
17
+    assertEquals(Location.UNKNOWN, cargo.getCurrentLocation());
18 18
   }
19 19
   
20 20
   public void testCurrentLocationReceived() throws Exception {
@@ -85,12 +85,14 @@ public class CargoTest extends TestCase {
85 85
   private Cargo populateCargoOffHongKong() throws Exception {
86 86
     final Cargo cargo = new Cargo(new TrackingId("XYZ"), new Location("SESTO"), new Location("AUMEL"));
87 87
 
88
-    final CarrierMovement stockholmToHamburg = new CarrierMovement(new Location("SESTO"), new Location("DEHAM"));
88
+    final CarrierMovement stockholmToHamburg = new CarrierMovement(
89
+            new CarrierId("CAR_001"), new Location("SESTO"), new Location("DEHAM"));
89 90
 
90 91
     cargo.handle(new HandlingEvent(getDate("2007-12-01"), HandlingEvent.Type.LOAD, stockholmToHamburg));
91 92
     cargo.handle(new HandlingEvent(getDate("2007-12-02"), HandlingEvent.Type.UNLOAD, stockholmToHamburg));
92 93
 
93
-    final CarrierMovement hamburgToHongKong = new CarrierMovement(new Location("DEHAM"), new Location("CNHGK"));
94
+    final CarrierMovement hamburgToHongKong = new CarrierMovement(
95
+            new CarrierId("CAR_001"), new Location("DEHAM"), new Location("CNHGK"));
94 96
 
95 97
     cargo.handle(new HandlingEvent(getDate("2007-12-03"), HandlingEvent.Type.LOAD, hamburgToHongKong));
96 98
     cargo.handle(new HandlingEvent(getDate("2007-12-04"), HandlingEvent.Type.UNLOAD, hamburgToHongKong));
@@ -101,12 +103,14 @@ public class CargoTest extends TestCase {
101 103
   private Cargo populateCargoOnHamburg() throws Exception {
102 104
     final Cargo cargo = new Cargo(new TrackingId("XYZ"), new Location("SESTO"), new Location("AUMEL"));
103 105
 
104
-    final CarrierMovement stockholmToHamburg = new CarrierMovement(new Location("SESTO"), new Location("DEHAM"));
106
+    final CarrierMovement stockholmToHamburg = new CarrierMovement(
107
+            new CarrierId("CAR_001"), new Location("SESTO"), new Location("DEHAM"));
105 108
 
106 109
     cargo.handle(new HandlingEvent(getDate("2007-12-01"), HandlingEvent.Type.LOAD, stockholmToHamburg));
107 110
     cargo.handle(new HandlingEvent(getDate("2007-12-02"), HandlingEvent.Type.UNLOAD, stockholmToHamburg));
108 111
 
109
-    final CarrierMovement hamburgToHongKong = new CarrierMovement(new Location("DEHAM"), new Location("CNHGK"));
112
+    final CarrierMovement hamburgToHongKong = new CarrierMovement(
113
+            new CarrierId("CAR_001"), new Location("DEHAM"), new Location("CNHGK"));
110 114
 
111 115
     cargo.handle(new HandlingEvent(getDate("2007-12-03"), HandlingEvent.Type.LOAD, hamburgToHongKong));
112 116
 
@@ -116,17 +120,20 @@ public class CargoTest extends TestCase {
116 120
   private Cargo populateCargoOffMelbourne() throws Exception {
117 121
     final Cargo cargo = new Cargo(new TrackingId("XYZ"), new Location("SESTO"), new Location("AUMEL"));
118 122
 
119
-    final CarrierMovement stockholmToHamburg = new CarrierMovement(new Location("SESTO"), new Location("DEHAM"));
123
+    final CarrierMovement stockholmToHamburg = new CarrierMovement(
124
+            new CarrierId("CAR_001"), new Location("SESTO"), new Location("DEHAM"));
120 125
 
121 126
     cargo.handle(new HandlingEvent(getDate("2007-12-01"), HandlingEvent.Type.LOAD, stockholmToHamburg));
122 127
     cargo.handle(new HandlingEvent(getDate("2007-12-02"), HandlingEvent.Type.UNLOAD, stockholmToHamburg));
123 128
 
124
-    final CarrierMovement hamburgToHongKong = new CarrierMovement(new Location("DEHAM"), new Location("CNHGK"));
129
+    final CarrierMovement hamburgToHongKong = new CarrierMovement(
130
+            new CarrierId("CAR_001"), new Location("DEHAM"), new Location("CNHGK"));
125 131
 
126 132
     cargo.handle(new HandlingEvent(getDate("2007-12-03"), HandlingEvent.Type.LOAD, hamburgToHongKong));
127 133
     cargo.handle(new HandlingEvent(getDate("2007-12-04"), HandlingEvent.Type.UNLOAD, hamburgToHongKong));
128 134
 
129
-    final CarrierMovement hongKongToMelbourne = new CarrierMovement(new Location("CNHGK"), new Location("AUMEL"));
135
+    final CarrierMovement hongKongToMelbourne = new CarrierMovement(
136
+            new CarrierId("CAR_001"), new Location("CNHGK"), new Location("AUMEL"));
130 137
 
131 138
     cargo.handle(new HandlingEvent(getDate("2007-12-05"), HandlingEvent.Type.LOAD, hongKongToMelbourne));
132 139
     cargo.handle(new HandlingEvent(getDate("2007-12-07"), HandlingEvent.Type.UNLOAD, hongKongToMelbourne));
@@ -137,17 +144,20 @@ public class CargoTest extends TestCase {
137 144
   private Cargo populateCargoOnHongKong() throws Exception {
138 145
     final Cargo cargo = new Cargo(new TrackingId("XYZ"), new Location("SESTO"), new Location("AUMEL"));
139 146
 
140
-    final CarrierMovement stockholmToHamburg = new CarrierMovement(new Location("SESTO"), new Location("DEHAM"));
147
+    final CarrierMovement stockholmToHamburg = new CarrierMovement(
148
+            new CarrierId("CAR_001"), new Location("SESTO"), new Location("DEHAM"));
141 149
 
142 150
     cargo.handle(new HandlingEvent(getDate("2007-12-01"), HandlingEvent.Type.LOAD, stockholmToHamburg));
143 151
     cargo.handle(new HandlingEvent(getDate("2007-12-02"), HandlingEvent.Type.UNLOAD, stockholmToHamburg));
144 152
 
145
-    final CarrierMovement hamburgToHongKong = new CarrierMovement(new Location("DEHAM"), new Location("CNHGK"));
153
+    final CarrierMovement hamburgToHongKong = new CarrierMovement(
154
+            new CarrierId("CAR_001"), new Location("DEHAM"), new Location("CNHGK"));
146 155
 
147 156
     cargo.handle(new HandlingEvent(getDate("2007-12-03"), HandlingEvent.Type.LOAD, hamburgToHongKong));
148 157
     cargo.handle(new HandlingEvent(getDate("2007-12-04"), HandlingEvent.Type.UNLOAD, hamburgToHongKong));
149 158
 
150
-    final CarrierMovement hongKongToMelbourne = new CarrierMovement(new Location("CNHGK"), new Location("AUMEL"));
159
+    final CarrierMovement hongKongToMelbourne = new CarrierMovement(
160
+            new CarrierId("CAR_001"), new Location("CNHGK"), new Location("AUMEL"));
151 161
 
152 162
     cargo.handle(new HandlingEvent(getDate("2007-12-05"), HandlingEvent.Type.LOAD, hongKongToMelbourne));
153 163
 

+ 19
- 14
dddsample/src/test/java/se/citerus/dddsample/domain/DeliveryHistoryTest.java Ver arquivo

@@ -1,24 +1,29 @@
1 1
 package se.citerus.dddsample.domain;
2 2
 
3
+import junit.framework.TestCase;
4
+
3 5
 import java.text.DateFormat;
4 6
 import java.text.SimpleDateFormat;
5
-
6
-import junit.framework.TestCase;
7
+import java.util.List;
7 8
 
8 9
 public class DeliveryHistoryTest extends TestCase {
9
-  public void testAddEventUnique() throws Exception {
10
+
11
+  public void testEvensOrderedByTime() throws Exception {
10 12
     DeliveryHistory dh = new DeliveryHistory();
11
-    
12
-    DateFormat f = new SimpleDateFormat("yyyy-MM-dd");
13
+    assertTrue(dh.eventsOrderedByTime().isEmpty());
14
+
15
+    DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
16
+    HandlingEvent he1 = new HandlingEvent(df.parse("2010-01-03"), HandlingEvent.Type.RECEIVE);
17
+    HandlingEvent he2 = new HandlingEvent(df.parse("2010-01-01"), HandlingEvent.Type.LOAD);
18
+    HandlingEvent he3 = new HandlingEvent(df.parse("2010-01-04"), HandlingEvent.Type.CLAIM);
19
+    HandlingEvent he4 = new HandlingEvent(df.parse("2010-01-02"), HandlingEvent.Type.UNLOAD);
20
+    dh.addEvent(he1, he2, he3, he4);
13 21
 
14
-    dh.addEvent(new HandlingEvent(f.parse("2010-01-01"), HandlingEvent.Type.RECEIVE, null));
15
-    
16
-    // Expect exception to be thrown when unique events are added (e.g. same timestamp)
17
-    try {
18
-      dh.addEvent(new HandlingEvent(f.parse("2010-01-01"), HandlingEvent.Type.LOAD, null));
19
-      assertFalse(true);
20
-    } catch (RuntimeException e) {
21
-      assertTrue(true);
22
-    }
22
+    List<HandlingEvent> orderEvents = dh.eventsOrderedByTime();
23
+    assertEquals(4, orderEvents.size());
24
+    assertSame(he2, orderEvents.get(0));
25
+    assertSame(he4, orderEvents.get(1));
26
+    assertSame(he1, orderEvents.get(2));
27
+    assertSame(he3, orderEvents.get(3));
23 28
   }
24 29
 }

+ 11
- 8
dddsample/src/test/java/se/citerus/dddsample/domain/HandlingEventTest.java Ver arquivo

@@ -1,18 +1,19 @@
1 1
 package se.citerus.dddsample.domain;
2 2
 
3
+import junit.framework.TestCase;
4
+import se.citerus.dddsample.domain.HandlingEvent.Type;
5
+
3 6
 import java.util.Calendar;
4 7
 import java.util.Date;
5 8
 import java.util.HashSet;
6 9
 import java.util.Set;
7 10
 
8
-import se.citerus.dddsample.domain.HandlingEvent.Type;
9
-import junit.framework.TestCase;
10
-
11 11
 public class HandlingEventTest extends TestCase {
12 12
   public void testCurrentLocationLoadEvent() throws Exception {
13 13
     Location locationAAA = new Location("AAA");
14 14
     Location locationBBB = new Location("BBB");
15
-    CarrierMovement cm = new CarrierMovement(locationAAA, locationBBB);
15
+    CarrierId carrierId = new CarrierId("CAR_001");
16
+    CarrierMovement cm = new CarrierMovement(carrierId, locationAAA, locationBBB);
16 17
     
17 18
     HandlingEvent ev = new HandlingEvent(null, HandlingEvent.Type.LOAD, cm);
18 19
     
@@ -22,7 +23,8 @@ public class HandlingEventTest extends TestCase {
22 23
   public void testCurrentLocationUnloadEvent() throws Exception {
23 24
     Location locationAAA = new Location("AAA");
24 25
     Location locationBBB = new Location("BBB");
25
-    CarrierMovement cm = new CarrierMovement(locationAAA, locationBBB);
26
+    CarrierId carrierId = new CarrierId("CAR_001");
27
+    CarrierMovement cm = new CarrierMovement(carrierId, locationAAA, locationBBB);
26 28
     
27 29
     HandlingEvent ev = new HandlingEvent(null, HandlingEvent.Type.UNLOAD, cm);
28 30
     
@@ -32,12 +34,12 @@ public class HandlingEventTest extends TestCase {
32 34
   public void testCurrentLocationReceivedEvent() throws Exception {
33 35
     HandlingEvent ev = new HandlingEvent(null, HandlingEvent.Type.RECEIVE, null);
34 36
 
35
-    assertEquals(Location.NULL, ev.getLocation());
37
+    assertEquals(Location.UNKNOWN, ev.getLocation());
36 38
   }
37 39
   public void testCurrentLocationClaimedEvent() throws Exception {
38 40
     HandlingEvent ev = new HandlingEvent(null, HandlingEvent.Type.CLAIM, null);
39 41
 
40
-    assertEquals(Location.NULL, ev.getLocation());
42
+    assertEquals(Location.UNKNOWN, ev.getLocation());
41 43
   }
42 44
   
43 45
   public void testParseType() throws Exception {
@@ -60,7 +62,8 @@ public class HandlingEventTest extends TestCase {
60 62
     Date date = Calendar.getInstance().getTime();
61 63
     Location locationAAA = new Location("AAA");
62 64
     Location locationBBB = new Location("BBB");
63
-    CarrierMovement cm = new CarrierMovement(locationAAA, locationBBB);
65
+    CarrierId carrierId = new CarrierId("CAR_001");
66
+    CarrierMovement cm = new CarrierMovement(carrierId, locationAAA, locationBBB);
64 67
     
65 68
     Cargo cargo1 = new Cargo(new TrackingId("ABC"), new Location("A"), new Location("C"));
66 69
     Cargo cargo2 = new Cargo(new TrackingId("CBA"), new Location("C"), new Location("A"));

+ 5
- 5
dddsample/src/test/java/se/citerus/dddsample/domain/LocationTest.java Ver arquivo

@@ -19,13 +19,13 @@ public class LocationTest extends TestCase {
19 19
     assertFalse(location.equals(null));
20 20
 
21 21
     // Special NULL location is equal to itself
22
-    assertTrue(Location.NULL.equals(Location.NULL));
22
+    assertTrue(Location.UNKNOWN.equals(Location.UNKNOWN));
23 23
 
24 24
     // No other location should be equal to the NULL location
25
-    assertFalse(new Location(null).equals(Location.NULL));
26
-    assertFalse(new Location("").equals(Location.NULL));
27
-    assertFalse(new Location("   ").equals(Location.NULL));
28
-    assertFalse(new Location("   FOO  BAR ").equals(Location.NULL));
25
+    assertFalse(new Location(null).equals(Location.UNKNOWN));
26
+    assertFalse(new Location("").equals(Location.UNKNOWN));
27
+    assertFalse(new Location("   ").equals(Location.UNKNOWN));
28
+    assertFalse(new Location("   FOO  BAR ").equals(Location.UNKNOWN));
29 29
   }
30 30
 
31 31
 }

+ 8
- 5
dddsample/src/test/java/se/citerus/dddsample/domain/TrackingScenarioTest.java Ver arquivo

@@ -6,7 +6,7 @@ import java.text.DateFormat;
6 6
 import java.text.ParseException;
7 7
 import java.text.SimpleDateFormat;
8 8
 import java.util.Date;
9
-import java.util.SortedSet;
9
+import java.util.List;
10 10
 
11 11
 public class TrackingScenarioTest extends TestCase {
12 12
 
@@ -16,10 +16,11 @@ public class TrackingScenarioTest extends TestCase {
16 16
 
17 17
     DeliveryHistory deliveryHistory = cargo.getDeliveryHistory();
18 18
 
19
-    SortedSet<HandlingEvent> handlingEvents = deliveryHistory.getEvents();
19
+    List<HandlingEvent> handlingEvents = deliveryHistory.eventsOrderedByTime();
20 20
 
21 21
     assertEquals(4, handlingEvents.size());
22
-    final HandlingEvent event = handlingEvents.last();
22
+    final HandlingEvent event = deliveryHistory.lastEvent();
23
+
23 24
     assertSame(HandlingEvent.Type.UNLOAD, event.getType());
24 25
     assertFalse(cargo.atFinalDestiation());
25 26
     assertEquals("CNHKG", cargo.getCurrentLocation().unlocode());
@@ -29,12 +30,14 @@ public class TrackingScenarioTest extends TestCase {
29 30
   private Cargo populateCargo() throws Exception {
30 31
     final Cargo cargo = new Cargo(new TrackingId("XYZ"), new Location("SESTO"), new Location("AUMEL"));
31 32
 
32
-    final CarrierMovement stockholmToHamburg = new CarrierMovement(new Location("SESTO"), new Location("DEHAM"));
33
+    final CarrierMovement stockholmToHamburg = new CarrierMovement(
34
+            new CarrierId("CAR_001"), new Location("SESTO"), new Location("DEHAM"));
33 35
 
34 36
     cargo.handle(new HandlingEvent(getDate("2007-12-01"), HandlingEvent.Type.LOAD, stockholmToHamburg));
35 37
     cargo.handle(new HandlingEvent(getDate("2007-12-02"), HandlingEvent.Type.UNLOAD, stockholmToHamburg));
36 38
 
37
-    final CarrierMovement hamburgToHongKong = new CarrierMovement(new Location("DEHAM"), new Location("CNHKG"));
39
+    final CarrierMovement hamburgToHongKong = new CarrierMovement(
40
+            new CarrierId("CAR_002"), new Location("DEHAM"), new Location("CNHKG"));
38 41
 
39 42
     cargo.handle(new HandlingEvent(getDate("2007-12-03"), HandlingEvent.Type.LOAD, hamburgToHongKong));
40 43
     cargo.handle(new HandlingEvent(getDate("2007-12-05"), HandlingEvent.Type.UNLOAD, hamburgToHongKong));

+ 9
- 12
dddsample/src/test/java/se/citerus/dddsample/service/HandlingEventServiceTest.java Ver arquivo

@@ -1,20 +1,16 @@
1 1
 package se.citerus.dddsample.service;
2 2
 
3
-import java.util.Calendar;
4
-import java.util.Date;
5
-import java.util.HashSet;
6
-import java.util.Set;
7
-
8 3
 import junit.framework.TestCase;
9
-import se.citerus.dddsample.domain.Cargo;
10
-import se.citerus.dddsample.domain.CarrierMovement;
11
-import se.citerus.dddsample.domain.HandlingEvent;
12
-import se.citerus.dddsample.domain.Location;
13
-import se.citerus.dddsample.domain.TrackingId;
4
+import static org.easymock.EasyMock.*;
5
+import se.citerus.dddsample.domain.*;
14 6
 import se.citerus.dddsample.repository.CargoRepository;
15 7
 import se.citerus.dddsample.repository.CarrierRepository;
16 8
 import se.citerus.dddsample.repository.HandlingEventRepository;
17
-import static org.easymock.EasyMock.*;
9
+
10
+import java.util.Calendar;
11
+import java.util.Date;
12
+import java.util.HashSet;
13
+import java.util.Set;
18 14
 
19 15
 public class HandlingEventServiceTest extends TestCase {
20 16
   private HandlingEventServiceImpl service;
@@ -24,7 +20,8 @@ public class HandlingEventServiceTest extends TestCase {
24 20
   
25 21
   private final Cargo cargoABC = new Cargo(new TrackingId("ABC"), new Location("ABCFROM"), new Location("ABCTO"));
26 22
   private final Cargo cargoXYZ = new Cargo(new TrackingId("XYZ"), new Location("XYZFROM"), new Location("XYZTO"));
27
-  private final CarrierMovement cmAAA_BBB = new CarrierMovement(new Location("AAA"), new Location("BBB"));
23
+  private final CarrierMovement cmAAA_BBB = new CarrierMovement(
24
+          new CarrierId("CAR_001"), new Location("AAA"), new Location("BBB"));
28 25
 
29 26
   protected void setUp() throws Exception{
30 27
     service = new HandlingEventServiceImpl();