Bladeren bron

Persisted Itinerary and Leg, with sample data and mapping.

Introduced Itinerary.EMPTY_ITINERARY to represent an emtpy itinerary (null object pattern)

Added capability to display expected/misdirected status of cargo and events to web tracking interface (jsp, DTOs, etc)

Location constructor now only has package-level visibility, and test code uses static location instances.

Rewrote UN Locode import to use straight JDBC access.
peter_backlund 18 jaren geleden
bovenliggende
commit
d70a69a3b5
22 gewijzigde bestanden met toevoegingen van 311 en 155 verwijderingen
  1. 18
    12
      dddsample/src/main/java/se/citerus/dddsample/domain/Cargo.java
  2. 18
    9
      dddsample/src/main/java/se/citerus/dddsample/domain/Itinerary.java
  3. 16
    1
      dddsample/src/main/java/se/citerus/dddsample/domain/Leg.java
  4. 3
    4
      dddsample/src/main/java/se/citerus/dddsample/domain/Location.java
  5. 3
    0
      dddsample/src/main/java/se/citerus/dddsample/repository/CargoRepositoryHibernate.java
  6. 12
    10
      dddsample/src/main/java/se/citerus/dddsample/service/CargoServiceImpl.java
  7. 8
    1
      dddsample/src/main/java/se/citerus/dddsample/service/dto/CargoWithHistoryDTO.java
  8. 7
    1
      dddsample/src/main/java/se/citerus/dddsample/service/dto/HandlingEventDTO.java
  9. 40
    29
      dddsample/src/main/java/se/citerus/dddsample/util/LocationsImporter.java
  10. 68
    9
      dddsample/src/main/java/se/citerus/dddsample/util/SampleDataGenerator.java
  11. 3
    2
      dddsample/src/main/resources/hibernate.cfg.xml
  12. 5
    0
      dddsample/src/main/webapp/WEB-INF/jsp/start.jsp
  13. 1
    1
      dddsample/src/test/java/se/citerus/dddsample/domain/CargoTest.java
  14. 0
    8
      dddsample/src/test/java/se/citerus/dddsample/domain/ItineraryTest.java
  15. 17
    0
      dddsample/src/test/java/se/citerus/dddsample/domain/SampleLocations.java
  16. 53
    15
      dddsample/src/test/java/se/citerus/dddsample/repository/CargoRepositoryTest.java
  17. 4
    8
      dddsample/src/test/java/se/citerus/dddsample/repository/CarrierMovementRepositoryTest.java
  18. 11
    13
      dddsample/src/test/java/se/citerus/dddsample/service/CargoServiceTest.java
  19. 12
    21
      dddsample/src/test/java/se/citerus/dddsample/service/HandlingEventServiceTest.java
  20. 1
    1
      dddsample/src/test/java/se/citerus/dddsample/service/RoutingServiceTest.java
  21. 3
    3
      dddsample/src/test/java/se/citerus/dddsample/util/LocationsImporterTest.java
  22. 8
    7
      dddsample/src/test/java/se/citerus/dddsample/web/CargoTrackingControllerTest.java

+ 18
- 12
dddsample/src/main/java/se/citerus/dddsample/domain/Cargo.java Bestand weergeven

@@ -29,10 +29,11 @@ public class Cargo {
29 29
   @Transient
30 30
   private DeliveryHistory deliveryHistory = new DeliveryHistory();
31 31
 
32
-  @Transient
32
+  @ManyToOne
33 33
   private Itinerary itinerary;
34 34
 
35 35
   //TODO Remove this constructor
36
+  //TODO Shouldn't origin and destination be implicitly derived from itinerary?
36 37
   public Cargo(TrackingId trackingId, Location origin, Location destination) {
37 38
     Validate.noNullElements(new Object[] {trackingId, origin, destination});
38 39
     this.trackingId = trackingId;
@@ -61,10 +62,12 @@ public class Cargo {
61 62
   }
62 63
 
63 64
   public void setOrigin(Location origin) {
65
+    Validate.notNull(origin);
64 66
     this.origin = origin;
65 67
   }
66 68
 
67 69
   public void setDestination(Location destination) {
70
+    Validate.notNull(destination);
68 71
     this.destination = destination;
69 72
   }
70 73
 
@@ -83,6 +86,17 @@ public class Cargo {
83 86
   }
84 87
 
85 88
   /**
89
+   * @return The itinerary.
90
+   */
91
+  public Itinerary itinerary() {
92
+    if (this.itinerary == null) {
93
+      return Itinerary.EMPTY_ITINERARY;
94
+    } else {
95
+      return this.itinerary;
96
+    }
97
+  }
98
+
99
+  /**
86 100
    * @return Last known location of the cargo, or Location.UNKNOWN if the delivery history is empty.
87 101
    */
88 102
   public Location lastKnownLocation() {
@@ -106,7 +120,8 @@ public class Cargo {
106 120
    *
107 121
    * @param itinerary an itinerary
108 122
    */
109
-  public void assignItinerary(Itinerary itinerary) {
123
+  public void setItinerary(Itinerary itinerary) {
124
+    Validate.notNull(itinerary);
110 125
     this.itinerary = itinerary;
111 126
   }
112 127
 
@@ -129,10 +144,6 @@ public class Cargo {
129 144
     return !itinerary.isExpected(lastEvent);
130 145
   }
131 146
 
132
-  public Itinerary itinerary() {
133
-    return this.itinerary;
134
-  }
135
-
136 147
   /**
137 148
    * Entities compare by identity, therefore the trackingId field is the only basis of comparison. For persistence we
138 149
    * have an id field, but it is not used for identiy comparison.
@@ -144,7 +155,7 @@ public class Cargo {
144 155
    *         attributes.
145 156
    */
146 157
   private boolean sameIdentityAs(Cargo other) {
147
-    return trackingId.equals(other.trackingId);
158
+    return other != null && trackingId.equals(other.trackingId);
148 159
   }
149 160
 
150 161
   /**
@@ -169,11 +180,6 @@ public class Cargo {
169 180
     return trackingId.hashCode();
170 181
   }
171 182
 
172
-  @Override
173
-  public String toString() {
174
-    return ReflectionToStringBuilder.toString(this, ToStringStyle.MULTI_LINE_STYLE);
175
-  }
176
-
177 183
   Cargo() {
178 184
     // Needed by Hibernate
179 185
   }

+ 18
- 9
dddsample/src/main/java/se/citerus/dddsample/domain/Itinerary.java Bestand weergeven

@@ -2,25 +2,30 @@ package se.citerus.dddsample.domain;
2 2
 
3 3
 import org.apache.commons.lang.Validate;
4 4
 
5
-import javax.persistence.GeneratedValue;
6
-import javax.persistence.Id;
5
+import javax.persistence.*;
7 6
 import java.util.Arrays;
8 7
 import java.util.List;
8
+import java.util.Collections;
9 9
 
10 10
 /**
11 11
  *
12 12
  */
13
-
13
+@Entity
14 14
 public class Itinerary {
15 15
 
16 16
   @Id
17 17
   @GeneratedValue
18 18
   private Long id;
19 19
 
20
-  private List<Leg> legs;
20
+  @OneToMany
21
+  @JoinColumn(name = "itinerary_id")
22
+  private List<Leg> legs = Collections.emptyList();
23
+
24
+  public static final Itinerary EMPTY_ITINERARY = new Itinerary();
21 25
 
22 26
   public Itinerary(List<Leg> legs) {
23 27
     Validate.notEmpty(legs);
28
+    Validate.noNullElements(legs);
24 29
     this.legs = legs;
25 30
   }
26 31
 
@@ -28,6 +33,10 @@ public class Itinerary {
28 33
     this(Arrays.asList(legs));
29 34
   }
30 35
 
36
+  public List<Leg> legs() {
37
+    return legs;
38
+  }
39
+
31 40
   /**
32 41
    * Test if the given handling event is expected when executing this itinerary.
33 42
    *
@@ -35,7 +44,6 @@ public class Itinerary {
35 44
    * @return <code>true</code> if the event is expected
36 45
    */
37 46
   public boolean isExpected(HandlingEvent event) {
38
-
39 47
     if (legs.isEmpty()) {
40 48
       return true;
41 49
     }
@@ -48,8 +56,6 @@ public class Itinerary {
48 56
 
49 57
     if (event.type() == HandlingEvent.Type.LOAD) {
50 58
       //Check that the there is one leg with same from location and carrier movement
51
-      boolean found = false;
52
-
53 59
       for (Leg leg : legs) {
54 60
         if (leg.from().equals(event.location())
55 61
            && leg.carrierMovementId().equals(event.carrierMovement().carrierId()))
@@ -66,7 +72,6 @@ public class Itinerary {
66 72
           return true;
67 73
       }
68 74
       return false;
69
-
70 75
     }
71 76
 
72 77
     if (event.type() == HandlingEvent.Type.CLAIM) {
@@ -84,7 +89,7 @@ public class Itinerary {
84 89
    * @return <code>true</code> if the legs in this and the other itinerary are all equal.
85 90
    */
86 91
   public boolean sameValueAs(Itinerary other) {
87
-    return legs.equals(other.legs);
92
+    return other != null && legs.equals(other.legs);
88 93
   }
89 94
 
90 95
   @Override
@@ -101,4 +106,8 @@ public class Itinerary {
101 106
   public int hashCode() {
102 107
     return legs.hashCode();
103 108
   }
109
+
110
+  Itinerary() {
111
+    // Needed by Hibernate
112
+  }
104 113
 }

+ 16
- 1
dddsample/src/main/java/se/citerus/dddsample/domain/Leg.java Bestand weergeven

@@ -6,12 +6,23 @@ import org.apache.commons.lang.builder.ToStringStyle;
6 6
 import org.apache.commons.lang.builder.EqualsBuilder;
7 7
 import org.apache.commons.lang.Validate;
8 8
 
9
+import javax.persistence.*;
10
+
9 11
 /**
10 12
  * An itinerary consists of one or more legs.
11 13
  */
14
+@Entity
12 15
 public class Leg {
16
+  @Id
17
+  @GeneratedValue
18
+  private Long id;
19
+
20
+  // TODO: why is this not related to CarrierMovement?
21
+  @Embedded
13 22
   private CarrierMovementId carrierMovementId;
23
+  @ManyToOne
14 24
   private Location from;
25
+  @ManyToOne
15 26
   private Location to;
16 27
 
17 28
   public Leg(CarrierMovementId carrierMovementId, Location from, Location to) {
@@ -63,7 +74,11 @@ public class Leg {
63 74
 
64 75
   @Override
65 76
   public int hashCode() {
66
-    return HashCodeBuilder.reflectionHashCode(this);
77
+    return new HashCodeBuilder(13,17).
78
+      append(carrierMovementId).
79
+      append(from).
80
+      append(to).
81
+      toHashCode();
67 82
   }
68 83
 
69 84
   @Override

+ 3
- 4
dddsample/src/main/java/se/citerus/dddsample/domain/Location.java Bestand weergeven

@@ -27,15 +27,14 @@ public class Location {
27 27
   );
28 28
 
29 29
   /**
30
+   * Package-level constructor, visible for test only.
31
+   * 
30 32
    * @param unLocode UN Locode
31 33
    * @param name     location name
32 34
    * @throws IllegalArgumentException if the UN Locode or name is null
33 35
    */
34
-  public Location(UnLocode unLocode, String name) {
36
+  Location(UnLocode unLocode, String name) {
35 37
     Validate.noNullElements(new Object[] {unLocode, name});
36
-    // TODO:
37
-    // It shouldn't really be possible to create a new location -
38
-    // it should only be looked up in the location repository.
39 38
     Validate.notNull(unLocode);
40 39
     Validate.notNull(name);
41 40
     this.unLocode = unLocode;

+ 3
- 0
dddsample/src/main/java/se/citerus/dddsample/repository/CargoRepositoryHibernate.java Bestand weergeven

@@ -17,6 +17,9 @@ public class CargoRepositoryHibernate extends HibernateRepository implements Car
17 17
             createQuery("from Cargo where trackingId = :tid").
18 18
             setParameter("tid", tid).
19 19
             uniqueResult();
20
+    if (cargo == null) {
21
+      return null;
22
+    }
20 23
     /*  There's no OR-mapped relation between the cargo delivery history and its handling events
21 24
         because the handling events are in a different aggregate.
22 25
 

+ 12
- 10
dddsample/src/main/java/se/citerus/dddsample/service/CargoServiceImpl.java Bestand weergeven

@@ -28,12 +28,13 @@ public class CargoServiceImpl implements CargoService {
28 28
     Location currentLocation = deliveryHistory.currentLocation();
29 29
     CarrierMovement currentCarrierMovement = deliveryHistory.currentCarrierMovement();
30 30
     final CargoWithHistoryDTO dto = new CargoWithHistoryDTO(
31
-            cargo.trackingId().idString(),
32
-            cargo.origin().toString(),
33
-            cargo.finalDestination().toString(),
34
-            deliveryHistory.status(),
35
-            currentLocation == null ? null : currentLocation.unLocode().idString(),
36
-            currentCarrierMovement == null ? null : currentCarrierMovement.carrierId().idString()
31
+      cargo.trackingId().idString(),
32
+      cargo.origin().toString(),
33
+      cargo.finalDestination().toString(),
34
+      deliveryHistory.status(),
35
+      currentLocation == null ? null : currentLocation.unLocode().idString(),
36
+      currentCarrierMovement == null ? null : currentCarrierMovement.carrierId().idString(),
37
+      cargo.isMisdirected()
37 38
     );
38 39
 
39 40
     final List<HandlingEvent> events = deliveryHistory.eventsOrderedByCompletionTime();
@@ -41,10 +42,11 @@ public class CargoServiceImpl implements CargoService {
41 42
       CarrierMovement cm = event.carrierMovement();
42 43
       String carrierIdString = (cm == null) ? "" : cm.carrierId().idString();
43 44
       dto.addEvent(new HandlingEventDTO(
44
-              event.location().toString(),
45
-              event.type().toString(),
46
-              carrierIdString,
47
-              event.completionTime()
45
+        event.location().toString(),
46
+        event.type().toString(),
47
+        carrierIdString,
48
+        event.completionTime(),
49
+        cargo.itinerary().isExpected(event)
48 50
       ));
49 51
     }
50 52
     return dto;

+ 8
- 1
dddsample/src/main/java/se/citerus/dddsample/service/dto/CargoWithHistoryDTO.java Bestand weergeven

@@ -20,15 +20,18 @@ public class CargoWithHistoryDTO implements Serializable {
20 20
   List<HandlingEventDTO> events;
21 21
   String carrierMovementId;
22 22
   StatusCode statusCode;
23
+  boolean misdirected;
23 24
 
24 25
   public CargoWithHistoryDTO(String trackingId, String origin, String finalDestination,
25
-                             StatusCode statusCode, String currentLocationId, String carrierMovementId) {
26
+                             StatusCode statusCode, String currentLocationId, String carrierMovementId,
27
+                             boolean isMisdirected) {
26 28
     this.trackingId = trackingId;
27 29
     this.origin = origin;
28 30
     this.finalDestination = finalDestination;
29 31
     this.statusCode = statusCode;
30 32
     this.currentLocationId = currentLocationId;
31 33
     this.carrierMovementId = carrierMovementId;
34
+    this.misdirected = isMisdirected;
32 35
 
33 36
     this.events = new ArrayList<HandlingEventDTO>();
34 37
   }
@@ -65,4 +68,8 @@ public class CargoWithHistoryDTO implements Serializable {
65 68
     return carrierMovementId;
66 69
   }
67 70
 
71
+  public boolean isMisdirected() {
72
+    return misdirected;
73
+  }
74
+
68 75
 }

+ 7
- 1
dddsample/src/main/java/se/citerus/dddsample/service/dto/HandlingEventDTO.java Bestand weergeven

@@ -12,12 +12,14 @@ public class HandlingEventDTO implements Serializable {
12 12
   private final String location;
13 13
   private final String carrier;
14 14
   private final Date time;
15
+  private boolean expected;
15 16
 
16
-  public HandlingEventDTO(String location, String type, String carrier, Date time) {
17
+  public HandlingEventDTO(String location, String type, String carrier, Date time, boolean expected) {
17 18
     this.location = location;
18 19
     this.type = type;
19 20
     this.carrier = carrier;
20 21
     this.time = time;
22
+    this.expected = expected;
21 23
   }
22 24
 
23 25
   public String getLocation() {
@@ -35,4 +37,8 @@ public class HandlingEventDTO implements Serializable {
35 37
   public String getCarrier() {
36 38
     return carrier;
37 39
   }
40
+
41
+  public boolean isExpected() {
42
+    return expected;
43
+  }
38 44
 }

+ 40
- 29
dddsample/src/main/java/se/citerus/dddsample/util/LocationsImporter.java Bestand weergeven

@@ -4,10 +4,6 @@ import org.apache.commons.io.IOUtils;
4 4
 import org.apache.commons.io.LineIterator;
5 5
 import org.apache.commons.logging.Log;
6 6
 import org.apache.commons.logging.LogFactory;
7
-import org.hibernate.CacheMode;
8
-import org.hibernate.FlushMode;
9
-import org.hibernate.SessionFactory;
10
-import org.hibernate.classic.Session;
11 7
 import org.springframework.beans.factory.BeanFactoryUtils;
12 8
 import org.springframework.core.io.ClassPathResource;
13 9
 import org.springframework.transaction.PlatformTransactionManager;
@@ -16,15 +12,18 @@ import org.springframework.transaction.support.TransactionCallback;
16 12
 import org.springframework.transaction.support.TransactionTemplate;
17 13
 import org.springframework.web.context.WebApplicationContext;
18 14
 import org.springframework.web.context.support.WebApplicationContextUtils;
19
-import se.citerus.dddsample.domain.Location;
20
-import se.citerus.dddsample.domain.UnLocode;
15
+import org.springframework.jdbc.core.JdbcTemplate;
16
+import org.springframework.jdbc.core.BatchPreparedStatementSetter;
21 17
 
22 18
 import javax.servlet.ServletContextEvent;
23 19
 import javax.servlet.ServletContextListener;
20
+import javax.sql.DataSource;
24 21
 import java.io.IOException;
25 22
 import java.io.InputStream;
26 23
 import java.util.zip.ZipEntry;
27 24
 import java.util.zip.ZipFile;
25
+import java.sql.PreparedStatement;
26
+import java.sql.SQLException;
28 27
 
29 28
 /**
30 29
  * Imports about 55 000 locations from an official UN Locode CSV export.
@@ -36,55 +35,67 @@ public class LocationsImporter implements ServletContextListener {
36 35
   private static final int BATCH_SIZE = 1000;
37 36
   private static final Log logger = LogFactory.getLog(LocationsImporter.class);
38 37
 
39
-  protected int importLocations(Session session) throws IOException {
38
+  protected int importLocations(JdbcTemplate jt) throws IOException {
40 39
     ZipFile zipFile = new ZipFile(new ClassPathResource(ZIP_FILE_NAME).getFile());
41 40
     ZipEntry zipEntry = zipFile.getEntry(ZIP_ENTRY_NAME);
42 41
     InputStream inputStream = zipFile.getInputStream(zipEntry);
43 42
     LineIterator iterator = IOUtils.lineIterator(inputStream, "ISO-8859-1");
44
-    session.setCacheMode(CacheMode.IGNORE);
45
-    session.setFlushMode(FlushMode.MANUAL);
46 43
 
47
-    int insertCount = 1;
44
+    int count = 0;
45
+    String sql = "INSERT INTO Location (unlocode,name) VALUES (?,?)";
46
+
47
+    final String[][] batchArgs = new String[BATCH_SIZE][2];
48 48
     while (iterator.hasNext()) {
49 49
       String line = iterator.nextLine();
50
-      Location location = parseLocation(line);
51
-      if (location != Location.UNKNOWN) {
52
-          session.save(location);
53
-          if (insertCount % BATCH_SIZE == 0) {
54
-            session.flush();
55
-            session.clear();
56
-          }
57
-          insertCount++;
50
+      String[] args = parseLocation(line);
51
+      if (args != null) {
52
+        int pos = count % BATCH_SIZE;
53
+        batchArgs[pos][0] = args[0];
54
+        batchArgs[pos][1] = args[1];
55
+        count++;
56
+        if (count % BATCH_SIZE == 0) {
57
+          jt.batchUpdate(sql, new BatchPreparedStatementSetter() {
58
+            public void setValues(PreparedStatement ps, int i) throws SQLException {
59
+              ps.setString(1, batchArgs[i][0]);
60
+              ps.setString(2, batchArgs[i][1]);
61
+            }
62
+            public int getBatchSize() {
63
+              return BATCH_SIZE;
64
+            }
65
+          });
66
+        }
67
+        //jt.update(sql, new Object[] {pos, args[0], args[1]});
58 68
       }
59 69
     }
60
-    session.flush();
70
+    // TODO: batch insert the tail of the line list
61 71
 
62
-    return insertCount;
72
+    return count;
63 73
   }
64 74
 
65
-  private Location parseLocation(String line) {
75
+  private String[] parseLocation(String line) {
66 76
     String countryCode = line.substring(3, 5);
67 77
     String locationCode = line.substring(6, 9);
68 78
     if (locationCode.trim().length() == 3) {
69 79
       String name = line.substring(10, 46).trim();
70
-      UnLocode unlocode = new UnLocode(countryCode, locationCode);
71
-      return new Location(unlocode, name);
80
+      return new String[] {countryCode + locationCode, name};
72 81
     } else {
73
-      return Location.UNKNOWN;
82
+      return null;
74 83
     }
75 84
   }
76 85
 
77 86
   public void contextInitialized(ServletContextEvent event) {
78
-    final WebApplicationContext context = WebApplicationContextUtils.getRequiredWebApplicationContext(event.getServletContext());
79
-    final PlatformTransactionManager ptm = (PlatformTransactionManager) BeanFactoryUtils.beanOfType(context, PlatformTransactionManager.class);
80
-    final SessionFactory sf = (SessionFactory) BeanFactoryUtils.beanOfType(context, SessionFactory.class);
81
-    final TransactionTemplate tt = new TransactionTemplate(ptm);
87
+    WebApplicationContext context = WebApplicationContextUtils.getRequiredWebApplicationContext(event.getServletContext());
88
+    PlatformTransactionManager ptm = (PlatformTransactionManager) BeanFactoryUtils.beanOfType(context, PlatformTransactionManager.class);
89
+    TransactionTemplate tt = new TransactionTemplate(ptm);
90
+    DataSource dataSource = (DataSource) BeanFactoryUtils.beanOfType(context, DataSource.class);
91
+    final JdbcTemplate jt = new JdbcTemplate(dataSource);
92
+
82 93
 
83 94
     long t = System.currentTimeMillis();
84 95
     Integer count = (Integer) tt.execute(new TransactionCallback() {
85 96
       public Object doInTransaction(TransactionStatus status) {
86 97
         try {
87
-          return importLocations(sf.getCurrentSession());
98
+          return importLocations(jt);
88 99
         } catch (IOException e) {
89 100
           throw new RuntimeException(e);
90 101
         }

+ 68
- 9
dddsample/src/main/java/se/citerus/dddsample/util/SampleDataGenerator.java Bestand weergeven

@@ -23,6 +23,7 @@ public class SampleDataGenerator implements ServletContextListener {
23 23
     String handlingEventSql =
24 24
       "insert into HandlingEvent (completionTime, registrationTime, type, location_id, carrierMovement_id, cargo_id) " +
25 25
       "values (?, ?, ?, ?, ?, ?)";
26
+
26 27
     Object[][] handlingEventArgs = {
27 28
         //XYZ (SESTO-FIHEL-DEHAM-CNHKG-JPTOK-AUMEL)
28 29
         {ts(0),     ts((1)),    "RECEIVE",  1,  null,  1},
@@ -53,12 +54,24 @@ public class SampleDataGenerator implements ServletContextListener {
53 54
         {ts((0)),   ts((1)),    "RECEIVE",  2,  null,  4},
54 55
         {ts((10)),  ts((11)),   "LOAD",     2,  7,     4},
55 56
         {ts((20)),  ts((21)),   "UNLOAD",   7,  7,     4},
57
+
58
+        //FGH
59
+        {ts(100),   ts(160),    "RECEIVE",  3,  null,   5},
60
+        {ts(150),   ts(110),    "LOAD",     3,  10,     5},
61
+
62
+        // JKL
63
+        {ts(200),   ts(220),    "RECEIVE",  6,  null,   6},
64
+        {ts(300),   ts(330),    "LOAD",     6,  12,     6},
65
+        {ts(400),   ts(440),    "UNLOAD",   5,  12,     6}  // Unexpected event
56 66
     };
57 67
     executeUpdate(jdbcTemplate, handlingEventSql, handlingEventArgs);
58 68
   }
59 69
 
60 70
   private static void loadCarrierMovementData(JdbcTemplate jdbcTemplate) {
61
-    String carrierMovementSql = "insert into CarrierMovement (id, carrier_movement_id, from_id, to_id) values (?,?,?,?)";
71
+    String carrierMovementSql =
72
+      "insert into CarrierMovement (id, carrier_movement_id, from_id, to_id) " +
73
+      "values (?,?,?,?)";
74
+
62 75
     Object[][] carrierMovementArgs = {
63 76
      // SESTO-FIHEL-DEHAM-CNHKG-JPTOK-AUMEL
64 77
       {1, "CAR_001",1,5},
@@ -73,24 +86,43 @@ public class SampleDataGenerator implements ServletContextListener {
73 86
       // AUMEL - USCHI - DEHAM - SESTO
74 87
       {7, "CAR_007",2,7},
75 88
       {8, "CAR_008",7,6},
76
-      {9, "CAR_009",6,1}
89
+      {9, "CAR_009",6,1},
90
+
91
+      // CNHKG - AUMEL
92
+      {10,"CAR_010",3,2},
93
+      // AUMEL - FIHEL
94
+      {11,"CAR_011",2,5},
95
+      // DEHAM - SESTO
96
+      {12,"CAR_020",6,1},
97
+      // SESTO - USCHI
98
+      {13,"CAR_021",1,7},
99
+      // USCHI - JPTKO
100
+      {14,"CAR_022",7,4}
77 101
     };
78 102
     executeUpdate(jdbcTemplate, carrierMovementSql, carrierMovementArgs);
79 103
   }
80 104
 
81 105
   private static void loadCargoData(JdbcTemplate jdbcTemplate) {
82
-    String cargoSql = "insert into Cargo (id, tracking_id, origin_id, destination_id) values (?, ?, ?, ?)";
106
+    String cargoSql =
107
+      "insert into Cargo (id, tracking_id, origin_id, destination_id, itinerary_id) " +
108
+      "values (?, ?, ?, ?, ?)";
109
+
83 110
     Object[][] cargoArgs = {
84
-      {1, "XYZ",1,2},
85
-      {2, "ABC",1,5},
86
-      {3, "ZYX",2,1},
87
-      {4, "CBA",5,1}
111
+      {1, "XYZ", 1, 2, null},
112
+      {2, "ABC", 1, 5, null},
113
+      {3, "ZYX", 2, 1, null},
114
+      {4, "CBA", 5, 1, null},
115
+      {5, "FGH", 3, 5, 1},
116
+      {6, "JKL", 6, 4, 2}
88 117
     };
89 118
     executeUpdate(jdbcTemplate, cargoSql, cargoArgs);
90 119
   }
91 120
 
92 121
   private static void loadLocationData(JdbcTemplate jdbcTemplate) {
93
-    String locationSql = "insert into Location (id, unlocode, name) values (?, ?, ?)";
122
+    String locationSql =
123
+      "insert into Location (id, unlocode, name) " +
124
+      "values (?, ?, ?)";
125
+
94 126
     Object[][] locationArgs = {
95 127
       {1, "SESTO", "Stockholm"},
96 128
       {2, "AUMEL", "Melbourne"},
@@ -103,6 +135,32 @@ public class SampleDataGenerator implements ServletContextListener {
103 135
     executeUpdate(jdbcTemplate, locationSql, locationArgs);
104 136
   }
105 137
 
138
+  private static void loadItineraryData(JdbcTemplate jdbcTemplate) {
139
+    String itinerarySql = "insert into Itinerary (id) values (?)";
140
+
141
+    Object[][] itineraryArgs = {
142
+      {1},
143
+      {2}
144
+    };
145
+    executeUpdate(jdbcTemplate, itinerarySql, itineraryArgs);
146
+
147
+    String legSql =
148
+      "insert into Leg (id, itinerary_id, carrier_movement_id, from_id, to_id) " +
149
+      "values (?,?,?,?,?)";
150
+
151
+    Object [][] legArgs = {
152
+      // Cargo 5: Hongkong - Melbourne - Stockholm - Helsinki
153
+      {1,1,"CAR_010",3,2},
154
+      {2,1,"CAR_011",2,1},
155
+      {3,1,"CAR_011",1,5},
156
+      // Cargo 6: Hamburg - Stockholm - Chicago - Tokyo
157
+      {4,2,"CAR_020",6,1},
158
+      {5,2,"CAR_021",1,7},
159
+      {6,2,"CAR_022",7,4}
160
+    };
161
+    executeUpdate(jdbcTemplate, legSql, legArgs);
162
+  }
163
+
106 164
   public void contextInitialized(ServletContextEvent event) {
107 165
     WebApplicationContext context = WebApplicationContextUtils.getRequiredWebApplicationContext(event.getServletContext());
108 166
     DataSource dataSource = (DataSource) BeanFactoryUtils.beanOfType(context, DataSource.class);
@@ -116,8 +174,9 @@ public class SampleDataGenerator implements ServletContextListener {
116 174
     transactionTemplate.execute(new TransactionCallbackWithoutResult() {
117 175
       protected void doInTransactionWithoutResult(TransactionStatus status) {
118 176
         loadLocationData(jdbcTemplate);
119
-        loadCargoData(jdbcTemplate);
120 177
         loadCarrierMovementData(jdbcTemplate);
178
+        loadItineraryData(jdbcTemplate);
179
+        loadCargoData(jdbcTemplate);
121 180
         loadHandlingEventData(jdbcTemplate);
122 181
       }
123 182
     });

+ 3
- 2
dddsample/src/main/resources/hibernate.cfg.xml Bestand weergeven

@@ -10,11 +10,12 @@
10 10
     <!-- Properties defined here are shared between test and production -->
11 11
     <property name="cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
12 12
     <mapping class="se.citerus.dddsample.domain.Cargo"/>
13
+    <mapping class="se.citerus.dddsample.domain.TrackingId"/>
14
+    <mapping class="se.citerus.dddsample.domain.Leg"/>
15
+    <mapping class="se.citerus.dddsample.domain.Itinerary"/>
13 16
     <mapping class="se.citerus.dddsample.domain.Location"/>
14 17
     <mapping class="se.citerus.dddsample.domain.HandlingEvent"/>
15 18
     <mapping class="se.citerus.dddsample.domain.CarrierMovement"/>
16
-    <mapping class="se.citerus.dddsample.domain.Itinerary"/>
17
-    <mapping class="se.citerus.dddsample.domain.TrackingId"/>
18 19
     <mapping class="se.citerus.dddsample.domain.CarrierMovementId"/>
19 20
     <mapping class="se.citerus.dddsample.domain.UnLocode"/>
20 21
   </session-factory>

+ 5
- 0
dddsample/src/main/webapp/WEB-INF/jsp/start.jsp Bestand weergeven

@@ -29,6 +29,9 @@
29 29
   <c:if test="${cargo ne null}">
30 30
     <div id="result">	
31 31
     <h2>Status: <spring:message code="cargo.status.${cargo.statusCode}"/>&nbsp;${cargo.currentLocationId}&nbsp;${cargo.carrierMovementId}</h2>
32
+    <c:if test="${cargo.misdirected}">
33
+      <p class="notify"><img src="${rc.contextPath}/images/error.png" alt="" />Cargo is misdirected</p>
34
+    </c:if>  
32 35
     <h3>Tracking History</h3>
33 36
     <table cellspacing="4">
34 37
       <thead>
@@ -36,6 +39,7 @@
36 39
           <td>Event</td>
37 40
           <td>Location</td>
38 41
           <td>Time</td>
42
+          <td></td>
39 43
         </tr>
40 44
       </thead>
41 45
       <tbody>
@@ -44,6 +48,7 @@
44 48
             <td>${event.type}</td>
45 49
             <td>${event.location}</td>
46 50
             <td>${event.time}</td>
51
+            <td><img src="${rc.contextPath}/images/${event.expected ? "tick" : "cross"}.png" alt=""/></td>
47 52
           </tr>
48 53
         </c:forEach>
49 54
       </tbody>

+ 1
- 1
dddsample/src/test/java/se/citerus/dddsample/domain/CargoTest.java Bestand weergeven

@@ -258,7 +258,7 @@ public class CargoTest extends TestCase {
258 258
        new Leg(new CarrierMovementId("DEF"), rotterdam, goteborg)
259 259
     );
260 260
 
261
-    cargo.assignItinerary(itinerary);
261
+    cargo.setItinerary(itinerary);
262 262
     return cargo;
263 263
   }
264 264
 

+ 0
- 8
dddsample/src/test/java/se/citerus/dddsample/domain/ItineraryTest.java Bestand weergeven

@@ -77,14 +77,6 @@ public class ItineraryTest extends TestCase {
77 77
   }
78 78
 
79 79
   public void testCreateItinerary() throws Exception {
80
-    //An empty legs list is not OK:
81
-    try {
82
-      new Itinerary();
83
-      fail("An empty itinerary is not OK");
84
-    } catch (IllegalArgumentException iae) {
85
-      //Expected
86
-    }
87
-
88 80
     try {
89 81
       new Itinerary(new ArrayList<Leg>());
90 82
       fail("An empty itinerary is not OK");

+ 17
- 0
dddsample/src/test/java/se/citerus/dddsample/domain/SampleLocations.java Bestand weergeven

@@ -0,0 +1,17 @@
1
+package se.citerus.dddsample.domain;
2
+
3
+/**
4
+ * A few locations for easy testing.
5
+ *
6
+ */
7
+public class SampleLocations {
8
+
9
+  public static final Location HONGKONG = new Location(new UnLocode("CN", "HKG"), "Hongkong");
10
+  public static final Location MELBOURNE = new Location(new UnLocode("AU","MEL"), "Melbourne");
11
+  public static final Location STOCKHOLM = new Location(new UnLocode("SE","STO"), "Stockholm");
12
+  public static final Location HELSINKI = new Location(new UnLocode("Fi","HEL"), "Helsinki");
13
+  public static final Location USCHI = new Location(new UnLocode("US", "CHI"), "Chicago");
14
+  public static final Location JPTKO = new Location(new UnLocode("JN","TKO"), "Tokyo");
15
+  public static final Location DEHAM = new Location(new UnLocode("DE", "HAM"), "Hamburg");
16
+
17
+}

+ 53
- 15
dddsample/src/test/java/se/citerus/dddsample/repository/CargoRepositoryTest.java Bestand weergeven

@@ -1,39 +1,77 @@
1 1
 package se.citerus.dddsample.repository;
2 2
 
3
-import se.citerus.dddsample.domain.Cargo;
4
-import se.citerus.dddsample.domain.Location;
5
-import se.citerus.dddsample.domain.TrackingId;
6
-import se.citerus.dddsample.domain.UnLocode;
3
+import se.citerus.dddsample.domain.*;
4
+import static se.citerus.dddsample.domain.HandlingEvent.Type.*;
5
+import static se.citerus.dddsample.domain.SampleLocations.*;
7 6
 
8 7
 import java.util.Map;
8
+import java.util.List;
9
+import java.util.Date;
9 10
 
10 11
 public class CargoRepositoryTest extends AbstractRepositoryTest {
11 12
 
12 13
   CargoRepository cargoRepository;
13
-  private final Location stockholm = new Location(new UnLocode("SE","STO"), "Stockholm");
14
-  private final Location melbourne = new Location(new UnLocode("AU","MEL"), "Melbourne");
15 14
 
16 15
   public void setCargoRepository(CargoRepository cargoRepository) {
17 16
     this.cargoRepository = cargoRepository;
18 17
   }
19 18
 
20 19
   public void testFindByCargoId() {
21
-    final TrackingId trackingId = new TrackingId("XYZ");
20
+    Cargo cargo = cargoRepository.find(new TrackingId("FGH"));
21
+    assertEquals(HONGKONG, cargo.origin());
22
+    assertEquals(HELSINKI, cargo.finalDestination());
22 23
 
23
-    Cargo cargo = cargoRepository.find(trackingId);
24
+    DeliveryHistory dh = cargo.deliveryHistory();
25
+    assertNotNull(dh);
24 26
 
25
-    assertEquals(trackingId, cargo.trackingId());
26
-    assertEquals(stockholm, cargo.origin());
27
-    assertEquals(melbourne, cargo.finalDestination());
28
-    // TODO: verify delivery history
27
+    List<HandlingEvent> events = dh.eventsOrderedByCompletionTime();
28
+    assertEquals(2, events.size());
29
+
30
+    HandlingEvent firstEvent = events.get(0);
31
+    assertHandlingEvent(cargo, firstEvent, RECEIVE, HONGKONG, 100, 160, null);
32
+
33
+    HandlingEvent secondEvent = events.get(1);
34
+    CarrierMovement expectedCm = new CarrierMovement(new CarrierMovementId("CAR_010"), HONGKONG, MELBOURNE);
35
+    assertHandlingEvent(cargo,  secondEvent, LOAD, HONGKONG, 150, 110, expectedCm);
36
+
37
+    List<Leg> legs = cargo.itinerary().legs();
38
+    assertEquals(3, legs.size());
39
+
40
+    Leg firstLeg = legs.get(0);
41
+    assertLeg(firstLeg, "CAR_010", HONGKONG, MELBOURNE);
42
+
43
+    Leg secondLeg = legs.get(1);
44
+    assertLeg(secondLeg, "CAR_011", MELBOURNE, STOCKHOLM);
45
+
46
+    Leg thirdLeg = legs.get(2);
47
+    assertLeg(thirdLeg, "CAR_011", STOCKHOLM, HELSINKI);
48
+  }
49
+
50
+  private void assertHandlingEvent(Cargo cargo, HandlingEvent event, HandlingEvent.Type expectedEventType, Location expectedLocation, int completionTimeMs, int registrationTimeMs, CarrierMovement expectedCarrierMovement) {
51
+    assertEquals(expectedEventType, event.type());
52
+    assertEquals(expectedLocation, event.location());
53
+    assertEquals(new Date(completionTimeMs), event.completionTime());
54
+    assertEquals(new Date(registrationTimeMs), event.registrationTime());
55
+    if (expectedCarrierMovement == null) {
56
+      assertNull(event.carrierMovement());
57
+    } else {
58
+      assertEquals(expectedCarrierMovement, event.carrierMovement());
59
+    }
60
+    assertEquals(cargo, event.cargo());
61
+  }
62
+
63
+  private void assertLeg(Leg firstLeg, String cmId, Location expectedFrom, Location expectedTo) {
64
+    assertEquals(new CarrierMovementId(cmId), firstLeg.carrierMovementId());
65
+    assertEquals(expectedFrom, firstLeg.from());
66
+    assertEquals(expectedTo, firstLeg.to());
29 67
   }
30 68
 
31 69
   public void testSave() {
32
-    sessionFactory.getCurrentSession().saveOrUpdate(stockholm);
33
-    sessionFactory.getCurrentSession().saveOrUpdate(melbourne);
70
+    sessionFactory.getCurrentSession().saveOrUpdate(STOCKHOLM);
71
+    sessionFactory.getCurrentSession().saveOrUpdate(MELBOURNE);
34 72
 
35 73
 
36
-    Cargo cargo = new Cargo(new TrackingId("AAA"), stockholm, melbourne);
74
+    Cargo cargo = new Cargo(new TrackingId("AAA"), STOCKHOLM, MELBOURNE);
37 75
     cargoRepository.save(cargo);
38 76
 
39 77
     flush();

+ 4
- 8
dddsample/src/test/java/se/citerus/dddsample/repository/CarrierMovementRepositoryTest.java Bestand weergeven

@@ -1,15 +1,11 @@
1 1
 package se.citerus.dddsample.repository;
2 2
 
3
-import se.citerus.dddsample.domain.CarrierMovement;
4
-import se.citerus.dddsample.domain.CarrierMovementId;
5
-import se.citerus.dddsample.domain.Location;
6
-import se.citerus.dddsample.domain.UnLocode;
3
+import se.citerus.dddsample.domain.*;
4
+import static se.citerus.dddsample.domain.SampleLocations.*;
7 5
 
8 6
 public class CarrierMovementRepositoryTest extends AbstractRepositoryTest {
9 7
 
10 8
   CarrierMovementRepository carrierMovementRepository;
11
-  private final Location stockholm = new Location(new UnLocode("SE","STO"), "Stockholm");
12
-  private final Location helsinki = new Location(new UnLocode("FI","HEL"), "Helsinki");
13 9
 
14 10
   public void setCarrierMovementRepository(CarrierMovementRepository carrierMovementRepository) {
15 11
     this.carrierMovementRepository = carrierMovementRepository;
@@ -19,8 +15,8 @@ public class CarrierMovementRepositoryTest extends AbstractRepositoryTest {
19 15
     CarrierMovement carrierMovement = carrierMovementRepository.find(new CarrierMovementId("CAR_001"));
20 16
     assertNotNull(carrierMovement);
21 17
     assertEquals("CAR_001", carrierMovement.carrierId().idString());
22
-    assertEquals(stockholm, carrierMovement.from());
23
-    assertEquals(helsinki, carrierMovement.to());
18
+    assertEquals(STOCKHOLM, carrierMovement.from());
19
+    assertEquals(HELSINKI, carrierMovement.to());
24 20
   }
25 21
 
26 22
 }

+ 11
- 13
dddsample/src/test/java/se/citerus/dddsample/service/CargoServiceTest.java Bestand weergeven

@@ -10,6 +10,7 @@ import org.springframework.test.AbstractDependencyInjectionSpringContextTests;
10 10
 import org.springframework.transaction.TransactionStatus;
11 11
 import org.springframework.transaction.interceptor.TransactionAspectSupport;
12 12
 import se.citerus.dddsample.domain.*;
13
+import static se.citerus.dddsample.domain.SampleLocations.*;
13 14
 import se.citerus.dddsample.repository.CargoRepository;
14 15
 import se.citerus.dddsample.repository.HandlingEventRepository;
15 16
 import se.citerus.dddsample.service.dto.CargoWithHistoryDTO;
@@ -76,15 +77,12 @@ public class CargoServiceTest extends AbstractDependencyInjectionSpringContextTe
76 77
    * Cargo returned.
77 78
    */
78 79
   public void testCargoServiceFindByTrackingIdScenario() {
79
-    Location origin = new Location(new UnLocode("OR","IGI"), "Origin");
80
-    Location finalDestination = new Location(new UnLocode("DE","STI"), "Destination");
81
-    final Cargo cargo = new Cargo(new TrackingId("XYZ"), origin, finalDestination);
82
-    Location sesto = new Location(new UnLocode("SE","STO"), "Stockholm");
83
-    HandlingEvent claimed = new HandlingEvent(cargo, new Date(10), new Date(20), HandlingEvent.Type.CLAIM, sesto, null);
84
-    Location to = new Location(new UnLocode("MU","GER"), "München");
85
-    CarrierMovement carrierMovement = new CarrierMovement(new CarrierMovementId("CAR_001"), sesto, to);
86
-    HandlingEvent loaded = new HandlingEvent(cargo, new Date(12), new Date(25), HandlingEvent.Type.LOAD, sesto, carrierMovement);
87
-    HandlingEvent unloaded = new HandlingEvent(cargo, new Date(100), new Date(110), HandlingEvent.Type.UNLOAD, to, carrierMovement);
80
+    final Cargo cargo = new Cargo(new TrackingId("XYZ"), STOCKHOLM, USCHI);
81
+
82
+    HandlingEvent claimed = new HandlingEvent(cargo, new Date(10), new Date(20), HandlingEvent.Type.CLAIM, STOCKHOLM, null);
83
+    CarrierMovement carrierMovement = new CarrierMovement(new CarrierMovementId("CAR_001"), STOCKHOLM, USCHI);
84
+    HandlingEvent loaded = new HandlingEvent(cargo, new Date(12), new Date(25), HandlingEvent.Type.LOAD, STOCKHOLM, carrierMovement);
85
+    HandlingEvent unloaded = new HandlingEvent(cargo, new Date(100), new Date(110), HandlingEvent.Type.UNLOAD, USCHI, carrierMovement);
88 86
     // Add out of order to verify ordering in DTO
89 87
     cargo.deliveryHistory().addAllEvents(Arrays.asList(loaded, unloaded, claimed));
90 88
 
@@ -103,9 +101,9 @@ public class CargoServiceTest extends AbstractDependencyInjectionSpringContextTe
103 101
 
104 102
 
105 103
     assertEquals("XYZ", cargoDTO.getTrackingId());
106
-    assertEquals("ORIGI (Origin)", cargoDTO.getOrigin());
107
-    assertEquals("DESTI (Destination)", cargoDTO.getFinalDestination());
108
-    assertEquals("MUGER", cargoDTO.getCurrentLocationId());
104
+    assertEquals("SESTO (Stockholm)", cargoDTO.getOrigin());
105
+    assertEquals("USCHI (Chicago)", cargoDTO.getFinalDestination());
106
+    assertEquals("USCHI", cargoDTO.getCurrentLocationId());
109 107
 
110 108
     List<HandlingEventDTO> events = cargoDTO.getEvents();
111 109
     assertEquals(3, events.size());
@@ -126,7 +124,7 @@ public class CargoServiceTest extends AbstractDependencyInjectionSpringContextTe
126 124
 
127 125
     // Finally unload
128 126
     eventDTO = events.get(2);
129
-    assertEquals("MUGER (München)", eventDTO.getLocation());
127
+    assertEquals("USCHI (Chicago)", eventDTO.getLocation());
130 128
     assertEquals("UNLOAD", eventDTO.getType());
131 129
     assertEquals("CAR_001", eventDTO.getCarrier());
132 130
     assertEquals(new Date(100), eventDTO.getTime());

+ 12
- 21
dddsample/src/test/java/se/citerus/dddsample/service/HandlingEventServiceTest.java Bestand weergeven

@@ -3,6 +3,7 @@ package se.citerus.dddsample.service;
3 3
 import junit.framework.TestCase;
4 4
 import static org.easymock.EasyMock.*;
5 5
 import se.citerus.dddsample.domain.*;
6
+import static se.citerus.dddsample.domain.SampleLocations.*;
6 7
 import se.citerus.dddsample.repository.CargoRepository;
7 8
 import se.citerus.dddsample.repository.CarrierMovementRepository;
8 9
 import se.citerus.dddsample.repository.HandlingEventRepository;
@@ -18,23 +19,13 @@ public class HandlingEventServiceTest extends TestCase {
18 19
   private HandlingEventRepository handlingEventRepository;
19 20
   private LocationRepository locationRepository;
20 21
 
21
-  private Location origin = new Location(new UnLocode("AF","ROM"), "AFROM");
22
-  private Location finalDestination = new Location(new UnLocode("AB","CTO"), "ABCTO");
23
-  private final Cargo cargoABC = new Cargo(new TrackingId("ABC"), origin, finalDestination);
22
+  private final Cargo cargoABC = new Cargo(new TrackingId("ABC"), DEHAM, JPTKO);
24 23
 
25
-  private Location xfrom = new Location(new UnLocode("XF","ROM"), "XFROM");
26
-  private Location xyzto = new Location(new UnLocode("XY","ZTO"), "XYZTO");
27
-  private final Cargo cargoXYZ = new Cargo(new TrackingId("XYZ"), xfrom, xyzto);
24
+  private final Cargo cargoXYZ = new Cargo(new TrackingId("XYZ"), HONGKONG, HELSINKI);
28 25
 
29
-  private Location a5 = new Location(new UnLocode("AA","AAA"), "AAAAA");
30
-  private Location b5 = new Location(new UnLocode("BB","BBB"), "BBBBB");
31 26
   private final CarrierMovement cmAAA_BBB = new CarrierMovement(
32
-          new CarrierMovementId("CAR_001"), a5, b5);
27
+          new CarrierMovementId("CAR_001"), USCHI, STOCKHOLM);
33 28
   
34
-  private final Location stockholm = new Location(new UnLocode("SE","STO"), "Stockholm");
35
-  private final Location melbourne = new Location(new UnLocode("AU","MEL"), "Melbourne");
36
-  private final Location hongkong = new Location(new UnLocode("CN","HKG"), "Hongkong");
37
-
38 29
   protected void setUp() throws Exception{
39 30
     service = new HandlingEventServiceImpl();
40 31
     cargoRepository = createMock(CargoRepository.class);
@@ -64,7 +55,7 @@ public class HandlingEventServiceTest extends TestCase {
64 55
     expect(carrierMovementRepository.find(carrierMovementId)).andReturn(cmAAA_BBB);
65 56
 
66 57
     final UnLocode unLocode = new UnLocode("SE", "STO");
67
-    expect(locationRepository.find(unLocode)).andReturn(stockholm);
58
+    expect(locationRepository.find(unLocode)).andReturn(STOCKHOLM);
68 59
 
69 60
     // TODO: does not inspect the handling event instance in a sufficient way
70 61
     handlingEventRepository.save(isA(HandlingEvent.class));
@@ -84,11 +75,11 @@ public class HandlingEventServiceTest extends TestCase {
84 75
     handlingEventRepository.save(isA(HandlingEvent.class));
85 76
     eventService.fireHandlingEventRegistered(isA(HandlingEvent.class));
86 77
 
87
-    expect(locationRepository.find(stockholm.unLocode())).andReturn(stockholm);
78
+    expect(locationRepository.find(STOCKHOLM.unLocode())).andReturn(STOCKHOLM);
88 79
 
89 80
     replay(cargoRepository, carrierMovementRepository, handlingEventRepository, locationRepository, eventService);
90 81
 
91
-    service.register(date, trackingId, null, stockholm.unLocode(), HandlingEvent.Type.CLAIM);
82
+    service.register(date, trackingId, null, STOCKHOLM.unLocode(), HandlingEvent.Type.CLAIM);
92 83
   }
93 84
   
94 85
 
@@ -99,14 +90,14 @@ public class HandlingEventServiceTest extends TestCase {
99 90
     expect(carrierMovementRepository.find(carrierMovementId)).andReturn(null);
100 91
 
101 92
     final TrackingId trackingId = new TrackingId("XYZ");
102
-    expect(cargoRepository.find(trackingId)).andReturn(new Cargo(trackingId, a5, b5));
93
+    expect(cargoRepository.find(trackingId)).andReturn(new Cargo(trackingId, USCHI, STOCKHOLM));
103 94
 
104
-    expect(locationRepository.find(melbourne.unLocode())).andReturn(melbourne);
95
+    expect(locationRepository.find(MELBOURNE.unLocode())).andReturn(MELBOURNE);
105 96
     
106 97
     replay(cargoRepository, carrierMovementRepository, handlingEventRepository, locationRepository, eventService);
107 98
     
108 99
     try {
109
-      service.register(date, trackingId, carrierMovementId, melbourne.unLocode(), HandlingEvent.Type.UNLOAD);
100
+      service.register(date, trackingId, carrierMovementId, MELBOURNE.unLocode(), HandlingEvent.Type.UNLOAD);
110 101
       fail("Should not be able to register an event with non-existing carrier movement");
111 102
     } catch (UnknownCarrierMovementIdException expected) {}
112 103
   }
@@ -117,12 +108,12 @@ public class HandlingEventServiceTest extends TestCase {
117 108
     final TrackingId trackingId = new TrackingId("XYZ");
118 109
     expect(cargoRepository.find(trackingId)).andReturn(null);
119 110
 
120
-    expect(locationRepository.find(hongkong.unLocode())).andReturn(hongkong);
111
+    expect(locationRepository.find(HONGKONG.unLocode())).andReturn(HONGKONG);
121 112
     
122 113
     replay(cargoRepository, carrierMovementRepository, handlingEventRepository, locationRepository, eventService);
123 114
     
124 115
     try {
125
-      service.register(date, trackingId, null, hongkong.unLocode(), HandlingEvent.Type.CLAIM);
116
+      service.register(date, trackingId, null, HONGKONG.unLocode(), HandlingEvent.Type.CLAIM);
126 117
       fail("Should not be able to register an event with non-existing cargo");
127 118
     } catch (UnknownTrackingIdException expected) {}
128 119
   }

+ 1
- 1
dddsample/src/test/java/se/citerus/dddsample/service/RoutingServiceTest.java Bestand weergeven

@@ -31,7 +31,7 @@ public class RoutingServiceTest extends TestCase {
31 31
       assigns that itinerary to the cargo.
32 32
      */
33 33
     Itinerary itinerary = stubbedItinerarySelection(itineraryCandidates);
34
-    cargo.assignItinerary(itinerary);
34
+    cargo.setItinerary(itinerary);
35 35
 
36 36
     /*
37 37
       A number of events occur, all of which are according to plan

+ 3
- 3
dddsample/src/test/java/se/citerus/dddsample/util/LocationsImporterTest.java Bestand weergeven

@@ -8,10 +8,10 @@ public class LocationsImporterTest extends AbstractRepositoryTest {
8 8
     LocationsImporter importer = new LocationsImporter();
9 9
     long t = System.currentTimeMillis();
10 10
 
11
-    //importer.importLocations(getSessionFactory().getCurrentSession());
12
-
11
+    int inserted = importer.importLocations(jdbcTemplate);
12
+    assertEquals(54600, inserted);
13
+    
13 14
     System.out.println("\n* * * Time to import: " + (System.currentTimeMillis() - t)/1000.0 + " seconds.\n");
14
-    //setComplete();
15 15
   }
16 16
 
17 17
 }

+ 8
- 7
dddsample/src/test/java/se/citerus/dddsample/web/CargoTrackingControllerTest.java Bestand weergeven

@@ -10,6 +10,7 @@ import org.springframework.validation.Errors;
10 10
 import org.springframework.validation.FieldError;
11 11
 import org.springframework.web.servlet.ModelAndView;
12 12
 import se.citerus.dddsample.domain.*;
13
+import static se.citerus.dddsample.domain.SampleLocations.*;
13 14
 import se.citerus.dddsample.service.CargoService;
14 15
 import se.citerus.dddsample.service.dto.CargoWithHistoryDTO;
15 16
 import se.citerus.dddsample.service.dto.HandlingEventDTO;
@@ -40,10 +41,8 @@ public class CargoTrackingControllerTest extends TestCase {
40 41
   private CargoService getCargoServiceMock() {
41 42
     return new CargoService() {
42 43
       public CargoWithHistoryDTO track(TrackingId trackingId) {
43
-        final Location a5 = new Location(new UnLocode("AA","AAA"), "AAAAA");
44
-        final Location b5 = new Location(new UnLocode("BB","BBB"), "BBBBB");
45
-        Cargo cargo = new Cargo(trackingId, a5, b5);
46
-        HandlingEvent event = new HandlingEvent(cargo, new Date(10L), new Date(20L), HandlingEvent.Type.RECEIVE, b5, null);
44
+        Cargo cargo = new Cargo(trackingId, HONGKONG, JPTKO);
45
+        HandlingEvent event = new HandlingEvent(cargo, new Date(10L), new Date(20L), HandlingEvent.Type.RECEIVE, HONGKONG, null);
47 46
 
48 47
         // TODO: use DTO assemblers
49 48
         CargoWithHistoryDTO cargoDTO = new CargoWithHistoryDTO(
@@ -52,12 +51,14 @@ public class CargoTrackingControllerTest extends TestCase {
52 51
                 cargo.finalDestination().unLocode().idString(),
53 52
                 StatusCode.CLAIMED,
54 53
                 "AAAAA",
55
-                "BALO");
54
+                "BALO",
55
+                false);
56 56
         cargoDTO.addEvent(new HandlingEventDTO(
57 57
           event.location().unLocode().idString(),
58 58
           event.type().toString(),
59
-          null, // TODO: event hierarchy will remove this kind of code
60
-          event.completionTime()));
59
+          null,
60
+          event.completionTime(),
61
+          true));
61 62
         return cargoDTO;
62 63
       }
63 64