Bläddra i källkod

Big slew of changes (too big) leading up to draft presentation:

Removed unneeded constructors in Cargo and UnLocode.

Fixed spelling error in StatusCode - "e before i except after c", or whatever that was :-)

Cascade Itinerary/Leg on Cargo persist.

Cargo registration and routing web administration interface.

Better randomization in RoutingServiceImpl.

Replaced more test locations with the SampleLocations instances.
peter_backlund 18 år sedan
förälder
incheckning
ce9f0f97a8
51 ändrade filer med 992 tillägg och 244 borttagningar
  1. 1
    1
      dddsample/pom.xml
  2. 2
    12
      dddsample/src/main/java/se/citerus/dddsample/domain/Cargo.java
  3. 1
    1
      dddsample/src/main/java/se/citerus/dddsample/domain/DeliveryHistory.java
  4. 1
    1
      dddsample/src/main/java/se/citerus/dddsample/domain/HandlingEvent.java
  5. 2
    2
      dddsample/src/main/java/se/citerus/dddsample/domain/Itinerary.java
  6. 1
    1
      dddsample/src/main/java/se/citerus/dddsample/domain/Location.java
  7. 1
    1
      dddsample/src/main/java/se/citerus/dddsample/domain/StatusCode.java
  8. 6
    17
      dddsample/src/main/java/se/citerus/dddsample/domain/UnLocode.java
  9. 4
    0
      dddsample/src/main/java/se/citerus/dddsample/repository/CargoRepository.java
  10. 9
    1
      dddsample/src/main/java/se/citerus/dddsample/repository/CargoRepositoryHibernate.java
  11. 5
    0
      dddsample/src/main/java/se/citerus/dddsample/repository/CargoRepositoryInMem.java
  12. 36
    2
      dddsample/src/main/java/se/citerus/dddsample/service/CargoService.java
  13. 110
    6
      dddsample/src/main/java/se/citerus/dddsample/service/CargoServiceImpl.java
  14. 2
    2
      dddsample/src/main/java/se/citerus/dddsample/service/RoutingService.java
  15. 29
    11
      dddsample/src/main/java/se/citerus/dddsample/service/RoutingServiceImpl.java
  16. 48
    0
      dddsample/src/main/java/se/citerus/dddsample/service/dto/CargoRoutingDTO.java
  17. 31
    0
      dddsample/src/main/java/se/citerus/dddsample/service/dto/LegDTO.java
  18. 111
    0
      dddsample/src/main/java/se/citerus/dddsample/web/CargoAdminController.java
  19. 26
    0
      dddsample/src/main/java/se/citerus/dddsample/web/command/RegistrationCommand.java
  20. 67
    0
      dddsample/src/main/java/se/citerus/dddsample/web/command/RoutingCommand.java
  21. 1
    1
      dddsample/src/main/java/se/citerus/dddsample/ws/HandlingEventServiceEndpointImpl.java
  22. 1
    0
      dddsample/src/main/resources/context-service.xml
  23. 4
    1
      dddsample/src/main/webapp/WEB-INF/decorators.xml
  24. 5
    0
      dddsample/src/main/webapp/WEB-INF/dispatch-servlet.xml
  25. 33
    0
      dddsample/src/main/webapp/WEB-INF/jsp/admin/list.jsp
  26. 49
    0
      dddsample/src/main/webapp/WEB-INF/jsp/admin/registrationForm.jsp
  27. 49
    0
      dddsample/src/main/webapp/WEB-INF/jsp/admin/selectItinerary.jsp
  28. 53
    0
      dddsample/src/main/webapp/WEB-INF/jsp/admin/show.jsp
  29. 33
    0
      dddsample/src/main/webapp/WEB-INF/jsp/adminDecorator.jsp
  30. 9
    5
      dddsample/src/main/webapp/WEB-INF/jsp/cargo/track.jsp
  31. 10
    6
      dddsample/src/main/webapp/WEB-INF/jsp/decorator.jsp
  32. 33
    0
      dddsample/src/main/webapp/admin.css
  33. Binär
      dddsample/src/main/webapp/images/dddsample_logotype.png
  34. 52
    26
      dddsample/src/main/webapp/style.css
  35. 25
    10
      dddsample/src/test/java/se/citerus/dddsample/domain/CargoTest.java
  36. 8
    9
      dddsample/src/test/java/se/citerus/dddsample/domain/CarrierMovementTest.java
  37. 1
    1
      dddsample/src/test/java/se/citerus/dddsample/domain/DeliveryHistoryTest.java
  38. 13
    13
      dddsample/src/test/java/se/citerus/dddsample/domain/HandlingEventTest.java
  39. 19
    29
      dddsample/src/test/java/se/citerus/dddsample/domain/ItineraryTest.java
  40. 5
    5
      dddsample/src/test/java/se/citerus/dddsample/domain/LocationTest.java
  41. 12
    12
      dddsample/src/test/java/se/citerus/dddsample/domain/SampleLocations.java
  42. 8
    11
      dddsample/src/test/java/se/citerus/dddsample/domain/TrackingScenarioTest.java
  43. 21
    23
      dddsample/src/test/java/se/citerus/dddsample/domain/UnLocodeTest.java
  44. 10
    3
      dddsample/src/test/java/se/citerus/dddsample/repository/CargoRepositoryTest.java
  45. 1
    1
      dddsample/src/test/java/se/citerus/dddsample/repository/HandlingEventRepositoryTest.java
  46. 2
    2
      dddsample/src/test/java/se/citerus/dddsample/repository/LocationRepositoryTest.java
  47. 2
    2
      dddsample/src/test/java/se/citerus/dddsample/service/HandlingEventServiceTest.java
  48. 4
    4
      dddsample/src/test/java/se/citerus/dddsample/service/RoutingScenarioTest.java
  49. 1
    2
      dddsample/src/test/java/se/citerus/dddsample/service/RoutingServiceTest.java
  50. 32
    17
      dddsample/src/test/java/se/citerus/dddsample/web/CargoTrackingControllerTest.java
  51. 3
    3
      dddsample/src/test/java/se/citerus/dddsample/ws/HandlinEventServiceEndpointTest.java

+ 1
- 1
dddsample/pom.xml Visa fil

@@ -106,7 +106,7 @@
106 106
         <artifactId>maven-jetty-plugin</artifactId>
107 107
         <version>6.1.4</version>
108 108
         <configuration>
109
-          <!--scanIntervalSeconds>10</scanIntervalSeconds-->
109
+          <scanIntervalSeconds>3</scanIntervalSeconds>
110 110
         </configuration>
111 111
       </plugin>
112 112
 

+ 2
- 12
dddsample/src/main/java/se/citerus/dddsample/domain/Cargo.java Visa fil

@@ -1,7 +1,5 @@
1 1
 package se.citerus.dddsample.domain;
2
-                        
3
-import org.apache.commons.lang.builder.ReflectionToStringBuilder;
4
-import org.apache.commons.lang.builder.ToStringStyle;
2
+
5 3
 import org.apache.commons.lang.Validate;
6 4
 
7 5
 import javax.persistence.*;
@@ -29,11 +27,9 @@ public class Cargo {
29 27
   @Transient
30 28
   private DeliveryHistory deliveryHistory = new DeliveryHistory();
31 29
 
32
-  @ManyToOne
30
+  @ManyToOne(cascade = CascadeType.ALL)
33 31
   private Itinerary itinerary;
34 32
 
35
-  //TODO Remove this constructor
36
-  //TODO Shouldn't origin and destination be implicitly derived from itinerary?
37 33
   public Cargo(TrackingId trackingId, Location origin, Location destination) {
38 34
     Validate.noNullElements(new Object[] {trackingId, origin, destination});
39 35
     this.trackingId = trackingId;
@@ -41,12 +37,6 @@ public class Cargo {
41 37
     this.destination = destination;
42 38
   }
43 39
 
44
-  public Cargo(TrackingId trackingId) {
45
-    Validate.notNull(trackingId);
46
-    this.trackingId = trackingId;
47
-  }
48
-
49
-
50 40
   /**
51 41
    * @return Tracking id.
52 42
    */

+ 1
- 1
dddsample/src/main/java/se/citerus/dddsample/domain/DeliveryHistory.java Visa fil

@@ -64,7 +64,7 @@ public class DeliveryHistory {
64 64
 
65 65
   public StatusCode status() {
66 66
     if (lastEvent() == null)
67
-      return StatusCode.NOT_RECIEVED;
67
+      return StatusCode.NOT_RECEIVED;
68 68
 
69 69
     HandlingEvent.Type type = lastEvent().type();
70 70
     if (type == HandlingEvent.Type.LOAD)

+ 1
- 1
dddsample/src/main/java/se/citerus/dddsample/domain/HandlingEvent.java Visa fil

@@ -1,8 +1,8 @@
1 1
 package se.citerus.dddsample.domain;
2 2
 
3
+import org.apache.commons.lang.Validate;
3 4
 import org.apache.commons.lang.builder.EqualsBuilder;
4 5
 import org.apache.commons.lang.builder.HashCodeBuilder;
5
-import org.apache.commons.lang.Validate;
6 6
 
7 7
 import javax.persistence.*;
8 8
 import java.util.Comparator;

+ 2
- 2
dddsample/src/main/java/se/citerus/dddsample/domain/Itinerary.java Visa fil

@@ -4,8 +4,8 @@ import org.apache.commons.lang.Validate;
4 4
 
5 5
 import javax.persistence.*;
6 6
 import java.util.Arrays;
7
-import java.util.List;
8 7
 import java.util.Collections;
8
+import java.util.List;
9 9
 
10 10
 /**
11 11
  *
@@ -17,7 +17,7 @@ public class Itinerary {
17 17
   @GeneratedValue
18 18
   private Long id;
19 19
 
20
-  @OneToMany
20
+  @OneToMany(cascade = CascadeType.ALL)
21 21
   @JoinColumn(name = "itinerary_id")
22 22
   private List<Leg> legs = Collections.emptyList();
23 23
 

+ 1
- 1
dddsample/src/main/java/se/citerus/dddsample/domain/Location.java Visa fil

@@ -23,7 +23,7 @@ public class Location {
23 23
    * Special Location object that marks an unknown location.
24 24
    */
25 25
   public static final Location UNKNOWN = new Location(
26
-     new UnLocode("XX", "XXX"), "Unknown location"
26
+     new UnLocode("XXXXX"), "Unknown location"
27 27
   );
28 28
 
29 29
   /**

+ 1
- 1
dddsample/src/main/java/se/citerus/dddsample/domain/StatusCode.java Visa fil

@@ -4,5 +4,5 @@ package se.citerus.dddsample.domain;
4 4
  * These are the different status codes for a cargo.
5 5
  */
6 6
 public enum StatusCode {
7
-    NOT_RECIEVED, IN_PORT, ONBOARD_CARRIER, CLAIMED
7
+  NOT_RECEIVED, IN_PORT, ONBOARD_CARRIER, CLAIMED
8 8
 }

+ 6
- 17
dddsample/src/main/java/se/citerus/dddsample/domain/UnLocode.java Visa fil

@@ -5,7 +5,6 @@ import org.apache.commons.lang.builder.EqualsBuilder;
5 5
 import org.apache.commons.lang.builder.HashCodeBuilder;
6 6
 
7 7
 import javax.persistence.Embeddable;
8
-import java.util.Arrays;
9 8
 import java.util.regex.Pattern;
10 9
 
11 10
 /**
@@ -19,25 +18,15 @@ public class UnLocode {
19 18
 
20 19
   private String unlocode;
21 20
 
22
-  // Country code is exactly two letters
23
-  private static final Pattern countryCodePattern = Pattern.compile("[a-zA-Z]{2}");
24
-
21
+  // Country code is exactly two letters.
25 22
   // Location code is usually three letters, but may contain the numbers 2-9 as well
26
-  private static final Pattern locationCodePattern = Pattern.compile("[a-zA-Z2-9]{3}");
27
-
28
-  public UnLocode(String countryCode, String locationCode) {
29
-    validateArgs(countryCode, locationCode);
23
+  private static final Pattern validPattern = Pattern.compile("[a-zA-Z]{2}[a-zA-Z2-9]{3}");
30 24
 
31
-    this.unlocode = (countryCode + locationCode).toUpperCase();
32
-  }
25
+  public UnLocode(String countryAndLocation) {
26
+    Validate.notNull(countryAndLocation);
27
+    Validate.isTrue(validPattern.matcher(countryAndLocation).matches());
33 28
 
34
-  private void validateArgs(String countryCode, String locationCode) {
35
-    Validate.noNullElements(new Object[] {countryCode, locationCode},
36
-            "Neither country code nor location code may be null");
37
-    Validate.isTrue(countryCodePattern.matcher(countryCode).matches(),
38
-      "\"" + countryCode + "\" is not a valid country code");
39
-    Validate.isTrue(locationCodePattern.matcher(locationCode).matches(),
40
-      "\"" + locationCode + "\" is not a valid location code");
29
+    this.unlocode = countryAndLocation.toUpperCase();
41 30
   }
42 31
 
43 32
   /**

+ 4
- 0
dddsample/src/main/java/se/citerus/dddsample/repository/CargoRepository.java Visa fil

@@ -3,10 +3,14 @@ package se.citerus.dddsample.repository;
3 3
 import se.citerus.dddsample.domain.Cargo;
4 4
 import se.citerus.dddsample.domain.TrackingId;
5 5
 
6
+import java.util.List;
7
+
6 8
 public interface CargoRepository {
7 9
 
8 10
   Cargo find(TrackingId trackingId);
9 11
 
12
+  List<Cargo> findAll();
13
+
10 14
   void save(Cargo cargo);
11 15
 
12 16
   TrackingId nextTrackingId();

+ 9
- 1
dddsample/src/main/java/se/citerus/dddsample/repository/CargoRepositoryHibernate.java Visa fil

@@ -4,6 +4,7 @@ import org.springframework.stereotype.Repository;
4 4
 import se.citerus.dddsample.domain.Cargo;
5 5
 import se.citerus.dddsample.domain.TrackingId;
6 6
 
7
+import java.util.List;
7 8
 import java.util.UUID;
8 9
 
9 10
 /**
@@ -41,7 +42,14 @@ public class CargoRepositoryHibernate extends HibernateRepository implements Car
41 42
     // Could be an opportunity to maybe illustrate how to handle pessimistic locking
42 43
     // and aggregate boundaries, and maybe problems with a distributed application
43 44
     // sharing a database. For now it's simply random though.
44
-    return new TrackingId(UUID.randomUUID().toString());
45
+    String random = UUID.randomUUID().toString().toUpperCase();
46
+    return new TrackingId(
47
+      random.substring(0, random.indexOf("-"))
48
+    );
49
+  }
50
+
51
+  public List<Cargo> findAll() {
52
+    return getSession().createQuery("from Cargo").list();
45 53
   }
46 54
 
47 55
   public void setHandlingEventRepository(HandlingEventRepository handlingEventRepository) {

+ 5
- 0
dddsample/src/main/java/se/citerus/dddsample/repository/CargoRepositoryInMem.java Visa fil

@@ -5,6 +5,7 @@ import se.citerus.dddsample.domain.Cargo;
5 5
 import se.citerus.dddsample.domain.TrackingId;
6 6
 
7 7
 import java.util.HashMap;
8
+import java.util.List;
8 9
 import java.util.Map;
9 10
 import java.util.UUID;
10 11
 
@@ -42,6 +43,10 @@ public class CargoRepositoryInMem implements CargoRepository {
42 43
     return new TrackingId(UUID.randomUUID().toString());
43 44
   }
44 45
 
46
+  public List<Cargo> findAll() {
47
+    return null;  //To change body of implemented methods use File | Settings | File Templates.
48
+  }
49
+
45 50
   /**
46 51
    * 
47 52
    * @throws Exception

+ 36
- 2
dddsample/src/main/java/se/citerus/dddsample/service/CargoService.java Visa fil

@@ -1,8 +1,12 @@
1 1
 package se.citerus.dddsample.service;
2 2
 
3
-import se.citerus.dddsample.domain.Location;
4 3
 import se.citerus.dddsample.domain.TrackingId;
4
+import se.citerus.dddsample.domain.UnLocode;
5
+import se.citerus.dddsample.service.dto.CargoRoutingDTO;
5 6
 import se.citerus.dddsample.service.dto.CargoTrackingDTO;
7
+import se.citerus.dddsample.service.dto.LegDTO;
8
+
9
+import java.util.List;
6 10
 
7 11
 /**
8 12
  * Cargo service.
@@ -17,7 +21,7 @@ public interface CargoService {
17 21
    * @param destination cargo destination
18 22
    * @return Cargo tracking id
19 23
    */
20
-  TrackingId registerNew(Location origin, Location destination);
24
+  TrackingId registerNew(UnLocode origin, UnLocode destination);
21 25
 
22 26
   /**
23 27
    * @param trackingId tracking id
@@ -26,6 +30,11 @@ public interface CargoService {
26 30
   CargoTrackingDTO track(TrackingId trackingId);
27 31
 
28 32
   /**
33
+   * @return A list of all locations where the company ships cargo to.
34
+   */
35
+  List<String> shippingLocations();
36
+
37
+  /**
29 38
    * Send relevant notifications to interested parties,
30 39
    * for example if a cargo has been misdirected, or unloaded
31 40
    * at the final destination.
@@ -33,4 +42,29 @@ public interface CargoService {
33 42
    * @param trackingId cargo tracking id
34 43
    */
35 44
   void notify(TrackingId trackingId);
45
+
46
+  /**
47
+   * Loads a cargo for routing operations.
48
+   *
49
+   * @param trackingId cargo tracking id
50
+   * @return A cargo with it's itinerary, or null if none found.
51
+   */
52
+  CargoRoutingDTO loadForRouting(TrackingId trackingId);
53
+
54
+  /**
55
+   * Loads all cargos for routing operations.
56
+   *
57
+   * @return All cargos with their itineraries.
58
+   */
59
+  List<CargoRoutingDTO> loadAllForRouting();
60
+
61
+  /**
62
+   * Assigns a new itinerary to a cargo,
63
+   * based on this list of legs.
64
+   *
65
+   * @param trackingId cargo tracking id
66
+   * @param legDTOs the legs of the route
67
+   */
68
+  void assignItinerary(TrackingId trackingId, List<LegDTO> legDTOs);
69
+
36 70
 }

+ 110
- 6
dddsample/src/main/java/se/citerus/dddsample/service/CargoServiceImpl.java Visa fil

@@ -6,32 +6,52 @@ import org.apache.commons.logging.LogFactory;
6 6
 import org.springframework.transaction.annotation.Transactional;
7 7
 import se.citerus.dddsample.domain.*;
8 8
 import se.citerus.dddsample.repository.CargoRepository;
9
+import se.citerus.dddsample.repository.LocationRepository;
10
+import se.citerus.dddsample.service.dto.CargoRoutingDTO;
9 11
 import se.citerus.dddsample.service.dto.CargoTrackingDTO;
10 12
 import se.citerus.dddsample.service.dto.HandlingEventDTO;
13
+import se.citerus.dddsample.service.dto.LegDTO;
11 14
 
15
+import java.util.ArrayList;
12 16
 import java.util.List;
13 17
 
14 18
 public class CargoServiceImpl implements CargoService {
15 19
 
16 20
   private CargoRepository cargoRepository;
21
+  private LocationRepository locationRepository;
17 22
   private static final Log logger = LogFactory.getLog(CargoServiceImpl.class);
18 23
 
19 24
   @Transactional(readOnly = false)
20
-  public TrackingId registerNew(Location origin, Location destination) {
21
-    Validate.notNull(origin);
22
-    Validate.notNull(destination);
25
+  public TrackingId registerNew(UnLocode originUnLocode, UnLocode destinationUnLocode) {
26
+    Validate.notNull(originUnLocode);
27
+    Validate.notNull(destinationUnLocode);
23 28
 
24 29
     TrackingId trackingId = cargoRepository.nextTrackingId();
25
-    Cargo cargo = new Cargo(trackingId, origin, destination);
26
-    cargoRepository.save(cargo);
30
+    Location origin = locationRepository.find(originUnLocode);
31
+    Location destination = locationRepository.find(destinationUnLocode);
32
+
33
+    Cargo cargo = new Cargo(trackingId,origin,destination);
27 34
 
35
+    cargoRepository.save(cargo);
28 36
     logger.info("Registered new cargo with tracking id " + trackingId.idString());
29
-    
37
+
30 38
     return trackingId;
31 39
   }
32 40
 
33 41
   @Transactional(readOnly = true)
42
+  public List<String> shippingLocations() {
43
+    List<Location> allLocations = locationRepository.findAll();
44
+    List<String> unlocodes = new ArrayList<String>(allLocations.size());
45
+    for (Location location : allLocations) {
46
+      unlocodes.add(location.unLocode().idString());
47
+    }
48
+    return unlocodes;
49
+  }
50
+
51
+  @Transactional(readOnly = true)
34 52
   public CargoTrackingDTO track(TrackingId trackingId) {
53
+    Validate.notNull(trackingId);
54
+
35 55
     final Cargo cargo = cargoRepository.find(trackingId);
36 56
     if (cargo == null) {
37 57
       return null;
@@ -39,6 +59,7 @@ public class CargoServiceImpl implements CargoService {
39 59
 
40 60
     DeliveryHistory deliveryHistory = cargo.deliveryHistory();
41 61
 
62
+    // TODO: use DTO assemblers
42 63
     Location currentLocation = deliveryHistory.currentLocation();
43 64
     CarrierMovement currentCarrierMovement = deliveryHistory.currentCarrierMovement();
44 65
     final CargoTrackingDTO dto = new CargoTrackingDTO(
@@ -70,7 +91,14 @@ public class CargoServiceImpl implements CargoService {
70 91
   // TODO: move this to another class?
71 92
   @Transactional(readOnly = true)
72 93
   public void notify(TrackingId trackingId) {
94
+    Validate.notNull(trackingId);
95
+
73 96
     Cargo cargo = cargoRepository.find(trackingId);
97
+    if (cargo == null) {
98
+      logger.warn("Can't notify listeners for non-existing cargo " + trackingId);
99
+      return;
100
+    }
101
+
74 102
     // TODO: more elaborate notifications, such as email to affected customer
75 103
     if (cargo.isMisdirected()) {
76 104
       logger.info("Cargo " + trackingId + " has been misdirected. " +
@@ -82,8 +110,84 @@ public class CargoServiceImpl implements CargoService {
82 110
     }
83 111
   }
84 112
 
113
+  @Transactional(readOnly = true)
114
+  public List<CargoRoutingDTO> loadAllForRouting() {
115
+    List<Cargo> allCargos = cargoRepository.findAll();
116
+
117
+    // TODO: use DTO assembler
118
+    List<CargoRoutingDTO> dtoList = new ArrayList<CargoRoutingDTO>(allCargos.size());
119
+    for (Cargo cargo : allCargos) {
120
+      CargoRoutingDTO dto = new CargoRoutingDTO(
121
+        cargo.trackingId().idString(),
122
+        cargo.origin().toString(),
123
+        cargo.finalDestination().toString()
124
+      );
125
+      for (Leg leg : cargo.itinerary().legs()) {
126
+        dto.addLeg(
127
+          leg.carrierMovementId().idString(),
128
+          leg.from().unLocode().idString(),
129
+          leg.to().unLocode().idString()
130
+        );
131
+      }
132
+      dtoList.add(dto);
133
+    }
134
+
135
+    return dtoList;
136
+  }
137
+
138
+  @Transactional(readOnly = true)
139
+  public CargoRoutingDTO loadForRouting(TrackingId trackingId) {
140
+    Validate.notNull(trackingId);
141
+    Cargo cargo = cargoRepository.find(trackingId);
142
+    if (cargo == null) {
143
+      return null;
144
+    }
145
+
146
+    // TODO: use DTO assembler
147
+    CargoRoutingDTO dto = new CargoRoutingDTO(
148
+      cargo.trackingId().idString(),
149
+      cargo.origin().toString(),
150
+      cargo.finalDestination().toString()
151
+    );
152
+    for (Leg leg : cargo.itinerary().legs()) {
153
+      dto.addLeg(
154
+        leg.carrierMovementId().idString(),
155
+        leg.from().toString(),
156
+        leg.to().toString()
157
+      );
158
+    }
159
+    return dto;
160
+  }
161
+
162
+  @Transactional(readOnly = false)
163
+  public void assignItinerary(TrackingId trackingId, List<LegDTO> legDTOs) {
164
+    Validate.notNull(trackingId);
165
+    Validate.notNull(legDTOs);
166
+
167
+    Cargo cargo = cargoRepository.find(trackingId);
168
+    if (cargo == null) {
169
+      throw new IllegalArgumentException("Can't assign itinerary to non-existing cargo " + trackingId);
170
+    }
171
+
172
+    List<Leg> legs = new ArrayList<Leg>(legDTOs.size());
173
+    for (LegDTO legDTO : legDTOs) {
174
+      legs.add(new Leg(
175
+        new CarrierMovementId(legDTO.getCarrierMovementId()),
176
+        locationRepository.find(new UnLocode(legDTO.getFrom())),
177
+        locationRepository.find(new UnLocode(legDTO.getTo())))
178
+      );
179
+    }
180
+
181
+    cargo.setItinerary(new Itinerary(legs));
182
+    cargoRepository.save(cargo);
183
+  }
184
+
185
+
85 186
   public void setCargoRepository(CargoRepository cargoRepository) {
86 187
     this.cargoRepository = cargoRepository;
87 188
   }
88 189
 
190
+  public void setLocationRepository(LocationRepository locationRepository) {
191
+    this.locationRepository = locationRepository;
192
+  }
89 193
 }

+ 2
- 2
dddsample/src/main/java/se/citerus/dddsample/service/RoutingService.java Visa fil

@@ -4,13 +4,13 @@ import se.citerus.dddsample.domain.Itinerary;
4 4
 import se.citerus.dddsample.domain.Specification;
5 5
 import se.citerus.dddsample.domain.TrackingId;
6 6
 
7
-import java.util.Set;
7
+import java.util.List;
8 8
 
9 9
 /**
10 10
  *  
11 11
  */
12 12
 public interface RoutingService {
13 13
 
14
-  Set<Itinerary> calculatePossibleRoutes(TrackingId trackingId, Specification specification);
14
+  List<Itinerary> calculatePossibleRoutes(TrackingId trackingId, Specification specification);
15 15
 
16 16
 }

+ 29
- 11
dddsample/src/main/java/se/citerus/dddsample/service/RoutingServiceImpl.java Visa fil

@@ -5,7 +5,10 @@ import se.citerus.dddsample.domain.*;
5 5
 import se.citerus.dddsample.repository.CargoRepository;
6 6
 import se.citerus.dddsample.repository.LocationRepository;
7 7
 
8
-import java.util.*;
8
+import java.util.ArrayList;
9
+import java.util.Collections;
10
+import java.util.List;
11
+import java.util.Random;
9 12
 
10 13
 /**
11 14
  * Simple routing service implementation that randomly creates a number
@@ -17,36 +20,36 @@ public class RoutingServiceImpl implements RoutingService {
17 20
   LocationRepository locationRepository;
18 21
   CargoRepository cargoRepository;
19 22
 
23
+  Random random = new Random();
24
+
20 25
   @Transactional(readOnly = true)
21
-  public Set<Itinerary> calculatePossibleRoutes(TrackingId trackingId, Specification specification) {
26
+  public List<Itinerary> calculatePossibleRoutes(TrackingId trackingId, Specification specification) {
22 27
     Cargo cargo = cargoRepository.find(trackingId);
23 28
     if (cargo == null) {
24
-      return Collections.emptySet();
29
+      return Collections.emptyList();
25 30
     }
26 31
     List<Location> allLocations = locationRepository.findAll();
27 32
 
28 33
     allLocations.remove(cargo.origin());
29 34
     allLocations.remove(cargo.finalDestination());
30 35
 
31
-    // TODO: vary the number of locations and number of candidates randomly
32
-
33
-    int candidateCount = 3;
34
-    Set<Itinerary> candidates = new HashSet<Itinerary>(candidateCount);
36
+    int candidateCount = getRandomNumberOfCandidates();
37
+    List<Itinerary> candidates = new ArrayList<Itinerary>(candidateCount);
35 38
     for (int i = 0; i < candidateCount; i++) {
36
-      Collections.shuffle(allLocations);
39
+      allLocations = getRandomChunkOfLocations(allLocations);
37 40
       List<Leg> legs = new ArrayList<Leg>(allLocations.size() - 1);
38 41
 
39 42
       Location firstLegTo = allLocations.get(0);
40
-      legs.add(new Leg(new CarrierMovementId("CM000"), cargo.origin(), firstLegTo));
43
+      legs.add(new Leg(new CarrierMovementId("CAR_002"), cargo.origin(), firstLegTo));
41 44
 
42 45
       for (int j = 0; j < allLocations.size() - 1 ; j++) {
43 46
         legs.add(new Leg(
44
-          new CarrierMovementId("CM00" + j),
47
+          getRandomCarrierMovementId(),
45 48
           allLocations.get(j), allLocations.get(j + 1)));
46 49
       }
47 50
 
48 51
       Location lastLegFrom = allLocations.get(allLocations.size() - 1);
49
-      legs.add(new Leg(new CarrierMovementId("CM999"), lastLegFrom, cargo.finalDestination()));
52
+      legs.add(new Leg(getRandomCarrierMovementId(), lastLegFrom, cargo.finalDestination()));
50 53
 
51 54
       candidates.add(new Itinerary(legs));
52 55
     }
@@ -54,6 +57,21 @@ public class RoutingServiceImpl implements RoutingService {
54 57
     return candidates;
55 58
   }
56 59
 
60
+  private List<Location> getRandomChunkOfLocations(List<Location> allLocations) {
61
+    Collections.shuffle(allLocations);
62
+    int total = allLocations.size();
63
+    int chunk = total > 4 ? (total - 4) + random.nextInt(5) : total;
64
+    return allLocations.subList(0, chunk);
65
+  }
66
+
67
+  private int getRandomNumberOfCandidates() {
68
+    return 1 + random.nextInt(4);
69
+  }
70
+
71
+  private CarrierMovementId getRandomCarrierMovementId() {
72
+    return new CarrierMovementId("CM" + random.nextInt(1000));
73
+  }
74
+
57 75
   public void setLocationRepository(LocationRepository locationRepository) {
58 76
     this.locationRepository = locationRepository;
59 77
   }

+ 48
- 0
dddsample/src/main/java/se/citerus/dddsample/service/dto/CargoRoutingDTO.java Visa fil

@@ -0,0 +1,48 @@
1
+package se.citerus.dddsample.service.dto;
2
+
3
+import java.util.ArrayList;
4
+import java.util.Collections;
5
+import java.util.List;
6
+
7
+/**
8
+ * DTO for registering and routing a cargo.
9
+ *
10
+ */
11
+public class CargoRoutingDTO {
12
+  String trackingId;
13
+  String origin;
14
+  String finalDestination;
15
+  List<LegDTO> legs;
16
+
17
+  public CargoRoutingDTO(String trackingId, String origin, String finalDestination) {
18
+    this.trackingId = trackingId;
19
+    this.origin = origin;
20
+    this.finalDestination = finalDestination;
21
+    this.legs = new ArrayList<LegDTO>();
22
+  }
23
+
24
+  public String getTrackingId() {
25
+    return trackingId;
26
+  }
27
+
28
+  public String getOrigin() {
29
+    return origin;
30
+  }
31
+
32
+  public String getFinalDestination() {
33
+    return finalDestination;
34
+  }
35
+
36
+  public void addLeg(String carrierMovementId, String from, String to) {
37
+    legs.add(new LegDTO(carrierMovementId, from, to));
38
+  }
39
+
40
+  public List<LegDTO> getLegs() {
41
+    return Collections.unmodifiableList(legs);
42
+  }
43
+
44
+  public boolean isRouted() {
45
+    return !legs.isEmpty();
46
+  }
47
+
48
+}

+ 31
- 0
dddsample/src/main/java/se/citerus/dddsample/service/dto/LegDTO.java Visa fil

@@ -0,0 +1,31 @@
1
+package se.citerus.dddsample.service.dto;
2
+
3
+/**
4
+ * DTO for a leg in an itinerary.
5
+ *
6
+ */
7
+public class LegDTO {
8
+
9
+  String carrierMovementId;
10
+  String from;
11
+  String to;
12
+
13
+  public LegDTO(String carrierMovementId, String from, String to) {
14
+    this.carrierMovementId = carrierMovementId;
15
+    this.from = from;
16
+    this.to = to;
17
+  }
18
+
19
+  public String getCarrierMovementId() {
20
+    return carrierMovementId;
21
+  }
22
+
23
+  public String getFrom() {
24
+    return from;
25
+  }
26
+
27
+  public String getTo() {
28
+    return to;
29
+  }
30
+
31
+}

+ 111
- 0
dddsample/src/main/java/se/citerus/dddsample/web/CargoAdminController.java Visa fil

@@ -0,0 +1,111 @@
1
+package se.citerus.dddsample.web;
2
+
3
+import org.springframework.web.servlet.mvc.multiaction.MultiActionController;
4
+import se.citerus.dddsample.domain.Itinerary;
5
+import se.citerus.dddsample.domain.Leg;
6
+import se.citerus.dddsample.domain.TrackingId;
7
+import se.citerus.dddsample.domain.UnLocode;
8
+import se.citerus.dddsample.service.CargoService;
9
+import se.citerus.dddsample.service.RoutingService;
10
+import se.citerus.dddsample.service.dto.LegDTO;
11
+import se.citerus.dddsample.web.command.RegistrationCommand;
12
+import se.citerus.dddsample.web.command.RoutingCommand;
13
+
14
+import javax.servlet.http.HttpServletRequest;
15
+import javax.servlet.http.HttpServletResponse;
16
+import java.util.ArrayList;
17
+import java.util.HashMap;
18
+import java.util.List;
19
+import java.util.Map;
20
+
21
+/**
22
+ * Handles cargo routing and administration.
23
+ *
24
+ */
25
+public class CargoAdminController extends MultiActionController {
26
+
27
+  private CargoService cargoService;
28
+  private RoutingService routingService;
29
+
30
+  public Map registrationForm(HttpServletRequest request, HttpServletResponse response) throws Exception {
31
+    Map map = new HashMap();
32
+    map.put("unlocodes", cargoService.shippingLocations());
33
+    return map;
34
+  }
35
+
36
+  public void register(HttpServletRequest request, HttpServletResponse response, RegistrationCommand command) throws Exception {
37
+    TrackingId trackingId = cargoService.registerNew(
38
+      new UnLocode(command.getOriginUnlocode()),
39
+      new UnLocode(command.getDestinationUnlocode())
40
+    );
41
+    response.sendRedirect("show.html?trackingId=" + trackingId.idString());
42
+  }
43
+
44
+  public Map list(HttpServletRequest request, HttpServletResponse response) {
45
+    Map map = new HashMap();
46
+    map.put("cargoList", cargoService.loadAllForRouting());
47
+    return map;
48
+  }
49
+
50
+  public Map show(HttpServletRequest request, HttpServletResponse response) {
51
+    Map map = new HashMap();
52
+    String param = request.getParameter("trackingId");
53
+    TrackingId trackingId = new TrackingId(param);
54
+    map.put("cargo", cargoService.loadForRouting(trackingId));
55
+    return map;
56
+  }
57
+
58
+  public Map selectItinerary(HttpServletRequest request, HttpServletResponse response) {
59
+    Map map = new HashMap();
60
+    TrackingId trackingId = new TrackingId(request.getParameter("trackingId"));
61
+
62
+    // TODO: more consistent to return some sort of LegDTO map/list from service layer, not the Itinerary
63
+    List<Itinerary> itineraries = routingService.calculatePossibleRoutes(trackingId, null);
64
+
65
+    List<RoutingCommand.ItineraryCandidateCommand> itineraryCandidates = new ArrayList<RoutingCommand.ItineraryCandidateCommand>();
66
+
67
+    for (Itinerary itinerary : itineraries) {
68
+      RoutingCommand.ItineraryCandidateCommand itineraryCandidateCommand = new RoutingCommand.ItineraryCandidateCommand();
69
+      itineraryCandidateCommand.setTrackingId(trackingId.idString());
70
+      itineraryCandidates.add(itineraryCandidateCommand);
71
+      for (Leg leg : itinerary.legs()) {
72
+        RoutingCommand.LegCommand legCommand = new RoutingCommand.LegCommand();
73
+        legCommand.setCarrierMovementId(leg.carrierMovementId().idString());
74
+        legCommand.setFromUnlocode(leg.from().unLocode().idString());
75
+        legCommand.setToUnlocode(leg.to().unLocode().idString());
76
+        itineraryCandidateCommand.getLegs().add(legCommand);
77
+      }
78
+    }
79
+
80
+    map.put("itineraryCandidates", itineraryCandidates);
81
+    map.put("trackingId", trackingId.idString());
82
+    return map;
83
+  }
84
+
85
+  public void assignItinerary(HttpServletRequest request, HttpServletResponse response) throws Exception {
86
+    TrackingId trackingId = new TrackingId(request.getParameter("trackingId"));
87
+
88
+    // TODO:  gah, any attempt at a proper command object fails due to indexoutofbounds (legs[0].fromUnlocode etc)...fix
89
+    String[] cmIds = (String[]) request.getParameterMap().get("legs.carrierMovementId");
90
+    String[] fromUnlocodes = (String[]) request.getParameterMap().get("legs.fromUnlocode");
91
+    String[] toUnlocodes = (String[]) request.getParameterMap().get("legs.toUnlocode");
92
+
93
+    List<LegDTO> legDTOs = new ArrayList<LegDTO>(cmIds.length);
94
+    for (int i = 0; i < cmIds.length; i++) {
95
+      legDTOs.add(new LegDTO(cmIds[i], fromUnlocodes[i], toUnlocodes[i]));
96
+    }
97
+
98
+    cargoService.assignItinerary(trackingId, legDTOs);
99
+
100
+    response.sendRedirect("list.html");
101
+  }
102
+
103
+  public void setCargoService(CargoService cargoService) {
104
+    this.cargoService = cargoService;
105
+  }
106
+
107
+  public void setRoutingService(RoutingService routingService) {
108
+    this.routingService = routingService;
109
+  }
110
+
111
+}

+ 26
- 0
dddsample/src/main/java/se/citerus/dddsample/web/command/RegistrationCommand.java Visa fil

@@ -0,0 +1,26 @@
1
+package se.citerus.dddsample.web.command;
2
+
3
+/**
4
+ *
5
+ */
6
+public class RegistrationCommand {
7
+  private String originUnlocode;
8
+  private String destinationUnlocode;
9
+
10
+  public String getOriginUnlocode() {
11
+    return originUnlocode;
12
+  }
13
+
14
+  public void setOriginUnlocode(String originUnlocode) {
15
+    this.originUnlocode = originUnlocode;
16
+  }
17
+
18
+  public String getDestinationUnlocode() {
19
+    return destinationUnlocode;
20
+  }
21
+
22
+  public void setDestinationUnlocode(String destinationUnlocode) {
23
+    this.destinationUnlocode = destinationUnlocode;
24
+  }
25
+
26
+}

+ 67
- 0
dddsample/src/main/java/se/citerus/dddsample/web/command/RoutingCommand.java Visa fil

@@ -0,0 +1,67 @@
1
+package se.citerus.dddsample.web.command;
2
+
3
+import java.util.ArrayList;
4
+import java.util.List;
5
+
6
+public class RoutingCommand {
7
+  List<ItineraryCandidateCommand> itineraryCandidates = new ArrayList<ItineraryCandidateCommand>();
8
+
9
+  public List<ItineraryCandidateCommand> getItineraryCandidates() {
10
+    return itineraryCandidates;
11
+  }
12
+
13
+  public void setItineraryCandidates(List<ItineraryCandidateCommand> itineraryCandidates) {
14
+    this.itineraryCandidates = itineraryCandidates;
15
+  }
16
+
17
+  public static class ItineraryCandidateCommand {
18
+    String trackingId;
19
+    List<LegCommand> legs = new ArrayList<LegCommand>();
20
+
21
+    public String getTrackingId() {
22
+      return trackingId;
23
+    }
24
+
25
+    public void setTrackingId(String trackingId) {
26
+      this.trackingId = trackingId;
27
+    }
28
+
29
+    public List<LegCommand> getLegs() {
30
+      return legs;
31
+    }
32
+
33
+    public void setLegs(List<LegCommand> legs) {
34
+      this.legs = legs;
35
+    }
36
+  }
37
+
38
+  public static class LegCommand {
39
+    String carrierMovementId;
40
+    String fromUnlocode;
41
+    String toUnlocode;
42
+
43
+    public String getCarrierMovementId() {
44
+      return carrierMovementId;
45
+    }
46
+
47
+    public void setCarrierMovementId(String carrierMovementId) {
48
+      this.carrierMovementId = carrierMovementId;
49
+    }
50
+
51
+    public String getFromUnlocode() {
52
+      return fromUnlocode;
53
+    }
54
+
55
+    public void setFromUnlocode(String fromUnlocode) {
56
+      this.fromUnlocode = fromUnlocode;
57
+    }
58
+
59
+    public String getToUnlocode() {
60
+      return toUnlocode;
61
+    }
62
+
63
+    public void setToUnlocode(String toUnlocode) {
64
+      this.toUnlocode = toUnlocode;
65
+    }
66
+  }
67
+}

+ 1
- 1
dddsample/src/main/java/se/citerus/dddsample/ws/HandlingEventServiceEndpointImpl.java Visa fil

@@ -37,7 +37,7 @@ public class HandlingEventServiceEndpointImpl implements HandlingEventServiceEnd
37 37
       }
38 38
       HandlingEvent.Type type = parseEventType(eventType);
39 39
 
40
-      UnLocode ul = new UnLocode(unlocode.substring(0,2), unlocode.substring(2,5));
40
+      UnLocode ul = new UnLocode(unlocode);
41 41
 
42 42
       handlingEventService.register(date, tid, cid, ul, type);
43 43
     } catch (ParseException pe) {

+ 1
- 0
dddsample/src/main/resources/context-service.xml Visa fil

@@ -15,6 +15,7 @@
15 15
 
16 16
   <bean id="cargoService" class="se.citerus.dddsample.service.CargoServiceImpl">
17 17
     <property name="cargoRepository" ref="cargoRepository"/>
18
+    <property name="locationRepository" ref="locationRepository"/>
18 19
   </bean>
19 20
 
20 21
   <bean id="handlingEventService" class="se.citerus.dddsample.service.HandlingEventServiceImpl">

+ 4
- 1
dddsample/src/main/webapp/WEB-INF/decorators.xml Visa fil

@@ -1,5 +1,8 @@
1 1
 <decorators defaultdir="/WEB-INF/jsp">
2 2
     <decorator name="main" page="decorator.jsp">
3
-          <pattern>*.html</pattern>
3
+          <pattern>/cargo/*.html</pattern>
4 4
     </decorator>
5
+  <decorator name="admin" page="adminDecorator.jsp">
6
+        <pattern>/admin/*.html</pattern>
7
+  </decorator>
5 8
 </decorators>

+ 5
- 0
dddsample/src/main/webapp/WEB-INF/dispatch-servlet.xml Visa fil

@@ -14,4 +14,9 @@
14 14
 
15 15
   <bean id="trackCommandValidator" class="se.citerus.dddsample.web.command.TrackCommandValidator"/>
16 16
 
17
+  <bean name="/admin/*" class="se.citerus.dddsample.web.CargoAdminController">
18
+    <property name="cargoService" ref="cargoService"/>
19
+    <property name="routingService" ref="routingService"/>
20
+  </bean>
21
+
17 22
 </beans>

+ 33
- 0
dddsample/src/main/webapp/WEB-INF/jsp/admin/list.jsp Visa fil

@@ -0,0 +1,33 @@
1
+<html>
2
+<head>
3
+  <title>Cargo Administration</title>
4
+</head>
5
+<body>
6
+  <table>
7
+    <caption>All cargos</caption>
8
+    <thead>
9
+      <tr>
10
+        <td>Tracking ID</td>
11
+        <td>Origin</td>
12
+        <td>Destination</td>
13
+        <td>Routed</td>
14
+      </tr>
15
+    </thead>
16
+    <tbody>
17
+      <c:forEach items="${cargoList}" var="cargo">
18
+      <tr>
19
+        <td>
20
+          <c:url value="/admin/show.html" var="showUrl">
21
+            <c:param name="trackingId" value="${cargo.trackingId}"/>
22
+          </c:url>
23
+          <a href="${showUrl}">${cargo.trackingId}</a>
24
+        </td>
25
+        <td>${cargo.origin}</td>
26
+        <td>${cargo.finalDestination}</td>
27
+        <td>${cargo.routed ? "Yes" : "No"}</td>
28
+      </tr>  
29
+      </c:forEach>
30
+    </tbody>
31
+  </table>
32
+</body>
33
+</html>

+ 49
- 0
dddsample/src/main/webapp/WEB-INF/jsp/admin/registrationForm.jsp Visa fil

@@ -0,0 +1,49 @@
1
+<html>
2
+<head>
3
+  <title>Cargo Administration</title>
4
+  <style type="text/css">
5
+    td {
6
+      align: left;
7
+    }
8
+  </style>
9
+</head>
10
+<body>
11
+<div id="container">
12
+  <form action="<c:url value="/admin/register.html"/>" method="post">
13
+  <table>
14
+    <caption>Register cargo</caption>
15
+    <tbody>
16
+      <tr>
17
+        <td>Origin</td>
18
+        <td>
19
+          <select name="originUnlocode">
20
+            <c:forEach items="${unlocodes}" var="u">
21
+            <option value="${u}">${u}</option>
22
+            </c:forEach>
23
+          </select>
24
+        </td>
25
+      </tr>
26
+      <tr>
27
+        <td>Final destination</td>
28
+        <td>
29
+          <select name="destinationUnlocode">
30
+            <c:forEach items="${unlocodes}" var="u">
31
+            <option value="${u}">${u}</option>
32
+            </c:forEach>
33
+          </select>
34
+        </td>
35
+      </tr>
36
+    </tbody>
37
+    <tfoot>
38
+      <tr>
39
+        <td> </td>
40
+        <td>
41
+          <input type="submit" value="Register"/>
42
+        </td>
43
+      </tr>
44
+    </tfoot>
45
+  </table>
46
+  </form>
47
+</div>
48
+</body>
49
+</html>

+ 49
- 0
dddsample/src/main/webapp/WEB-INF/jsp/admin/selectItinerary.jsp Visa fil

@@ -0,0 +1,49 @@
1
+<html>
2
+<head>
3
+  <title>Cargo Administration</title>
4
+</head>
5
+<body>
6
+<div id="container">
7
+  <h1>Select itinerary</h1>
8
+  <c:url value="/admin/assignItinerary.html" var="postUrl"/>
9
+
10
+  <c:forEach items="${itineraryCandidates}" var="it" varStatus="itStatus">
11
+      <form action="${postUrl}" method="post">
12
+        <input type="hidden" name="trackingId" value="${trackingId}"/>
13
+        <table>
14
+          <caption>Itinerary ${status.index + 1}</caption>
15
+          <thead>
16
+            <tr>
17
+              <td>Carrier</td>
18
+              <td>From</td>
19
+              <td>To</td>
20
+            </tr>
21
+          </thead>
22
+          <tbody>
23
+            <c:forEach items="${it.legs}" var="leg" varStatus="legStatus">
24
+              <input type="hidden" name="legs.carrierMovementId" value="${leg.carrierMovementId}"/>
25
+              <input type="hidden" name="legs.fromUnlocode" value="${leg.fromUnlocode}"/>
26
+              <input type="hidden" name="legs.toUnlocode" value="${leg.toUnlocode}"/>
27
+              <tr>
28
+                <td>${leg.carrierMovementId}</td>
29
+                <td>${leg.fromUnlocode}</td>
30
+                <td>${leg.toUnlocode}</td>
31
+              </tr>
32
+            </c:forEach>
33
+          </tbody>
34
+          <tfoot>
35
+            <tr>
36
+              <td colspan="3">
37
+                <p>
38
+                  <input type="submit" value="Select"/>
39
+                </p>
40
+              </td>
41
+            </tr>
42
+          </tfoot>
43
+        </table>
44
+      </form>
45
+  </c:forEach>
46
+
47
+</div>
48
+</body>
49
+</html>

+ 53
- 0
dddsample/src/main/webapp/WEB-INF/jsp/admin/show.jsp Visa fil

@@ -0,0 +1,53 @@
1
+<html>
2
+<head>
3
+  <title>Cargo Administration</title>
4
+</head>
5
+<body>
6
+<div id="container">
7
+  <table>
8
+    <caption>Details for cargo ${cargo.trackingId}</caption>
9
+    <tbody>
10
+      <tr>
11
+        <td>Origin</td>
12
+        <td>${cargo.origin}</td>
13
+      </tr>
14
+      <tr>
15
+        <td>Final destination</td>
16
+        <td>${cargo.finalDestination}</td>
17
+      </tr>
18
+    </tbody>
19
+  </table>
20
+  <c:choose>
21
+    <c:when test="${cargo.routed}">
22
+      <table>
23
+        <caption>Itinerary</caption>
24
+        <thead>
25
+          <tr>
26
+            <td>Carrier</td>
27
+            <td>From</td>
28
+            <td>To</td>
29
+          </tr>
30
+        </thead>
31
+        <tbody>
32
+          <c:forEach items="${cargo.legs}" var="leg">
33
+            <tr>
34
+              <td>${leg.carrierMovementId}</td>
35
+              <td>${leg.from}</td>
36
+              <td>${leg.to}</td>
37
+            </tr>
38
+          </c:forEach>
39
+        </tbody>
40
+      </table>
41
+    </c:when>
42
+    <c:otherwise>
43
+      <p>
44
+        <c:url value="/admin/selectItinerary.html" var="selectUrl">
45
+          <c:param name="trackingId" value="${cargo.trackingId}"/>
46
+        </c:url>
47
+        Not routed - <a href="${selectUrl}">Route this cargo</a>
48
+      </p>
49
+    </c:otherwise>
50
+  </c:choose>
51
+</div>
52
+</body>
53
+</html>

+ 33
- 0
dddsample/src/main/webapp/WEB-INF/jsp/adminDecorator.jsp Visa fil

@@ -0,0 +1,33 @@
1
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
+
3
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
4
+<head>
5
+  <meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
6
+  <title><decorator:title/></title>
7
+  <script type="text/javascript" charset="UTF-8"></script>
8
+  <style type="text/css" title="style" media="screen">
9
+    @import "${rc.contextPath}/admin.css";
10
+  </style>
11
+  <decorator:head/>
12
+</head>
13
+<body>
14
+  <div id="outer">
15
+    <h1>Cargo administration</h1>
16
+    <ul id="menu">
17
+      <li>
18
+        <a href="${rc.contextPath}/admin/list.html">
19
+          List all cargos
20
+        </a>
21
+      </li>
22
+      <li>
23
+        <a href="${rc.contextPath}/admin/registrationForm.html">
24
+          Register cargo
25
+        </a>
26
+      </li>
27
+    </ul>
28
+    <div id="body">
29
+      <decorator:body/>
30
+    </div>
31
+  </div>
32
+</body>
33
+</html>

+ 9
- 5
dddsample/src/main/webapp/WEB-INF/jsp/cargo/track.jsp Visa fil

@@ -4,23 +4,27 @@
4 4
 </head>
5 5
 <body>
6 6
 <div id="container">
7
+  <h1>Track Your Cargo</h1>
7 8
   <div id="search">
8
-  <h1>Search for Your Cargo</h1>
9 9
   <form:form method="post" commandName="trackCommand">
10
-    <table cellspacing="0" cellpadding="4">
10
+    <table>
11 11
       <tr>
12
-        <td align="right">
12
+        <td>
13 13
           Enter tracking id:
14 14
         </td>
15 15
         <td>
16 16
           <form:input path="trackingId" id="idInput"/>
17 17
         </td>
18 18
         <td>
19
-          <form:errors path="trackingId" cssClass="error"/>
19
+          <input type="submit" value="Track!">
20 20
         </td>
21
+      </tr>
22
+      <tr>
23
+        <td></td>
21 24
         <td>
22
-          <input type="submit" value="Track!">
25
+          <form:errors path="trackingId" cssClass="error"/>
23 26
         </td>
27
+        <td></td>
24 28
       </tr>
25 29
     </table>
26 30
   </form:form>

+ 10
- 6
dddsample/src/main/webapp/WEB-INF/jsp/decorator.jsp Visa fil

@@ -11,12 +11,16 @@
11 11
   <decorator:head/>
12 12
 </head>
13 13
 <body>
14
-  <div id="apptitle">
15
-    <h1>Domain Driven Delivery</h1>
14
+  <div id="outer">
15
+    <div id="apptitle">
16
+      <img src="${rc.contextPath}/images/dddsample_logotype.png" alt="Domain Driven Delivery"/>
17
+    </div>
18
+    <div id="body">
19
+      <decorator:body/>
20
+    </div>
21
+    <div id="footer">
22
+      This application is written by <a href="http://www.citerus.se" target="_blank">Citerus</a>
23
+      and <a href="http://www.domainlanguage.com" target="_blank">Domain Language</a></div>
16 24
   </div>
17
-  <div id="body">
18
-    <decorator:body/>
19
-  </div>
20
-  <div id="footer">Written by Citerus and Domain Language</div>
21 25
 </body>
22 26
 </html>

+ 33
- 0
dddsample/src/main/webapp/admin.css Visa fil

@@ -0,0 +1,33 @@
1
+html,body {
2
+  height: 100%;
3
+}
4
+
5
+body {
6
+  font: Arial, sans-serif; 
7
+  color: black;
8
+  padding: 10px;
9
+}
10
+
11
+ul#menu {
12
+}
13
+
14
+ul#menu li {
15
+  margin: 5px;
16
+  display: inline;
17
+}
18
+
19
+table {
20
+}
21
+
22
+table td {
23
+  padding: 4px 10px;
24
+}
25
+
26
+table thead {
27
+  font-weight: bold;
28
+}
29
+
30
+table caption {
31
+  text-align: left;
32
+  font-weight: bold;
33
+}

Binär
dddsample/src/main/webapp/images/dddsample_logotype.png Visa fil


+ 52
- 26
dddsample/src/main/webapp/style.css Visa fil

@@ -1,24 +1,15 @@
1
-
2
-/*********************************************************
3
-   HTML Elements
4
- *********************************************************/
5
-
6
-html,
7
-body {
1
+html,body {
8 2
   height: 100%;
9 3
 }
10 4
 
11 5
 body {
12
-  margin-left: 150px;
13
-  margin-right: 150px;
14
-  padding: 0;
6
+  margin: auto;
15 7
   font: 400 0.7em verdana, arial, sans-serif;
16 8
   line-height: 170%;
17
-  
18 9
   color: #555;
10
+  background-color: orange;
19 11
 }
20 12
 
21
-
22 13
 /* Headers */
23 14
 h1, h2, h3, h4, h5, h6 {
24 15
   margin: 0 0 10px 0;
@@ -31,7 +22,6 @@ h1 {
31 22
 
32 23
   font: 400 1.6em arial, sans-serif;
33 24
   color: #536C71;
34
-  border-bottom: 6px solid #ddd;
35 25
 }
36 26
 
37 27
 h2 {
@@ -57,11 +47,11 @@ h5 {
57 47
 /* Links */
58 48
 a {
59 49
   text-decoration: none;
60
-  color: #3B5D77;
50
+  color: blue;
61 51
 }
62 52
 
63 53
 a:hover {
64
-  color: #668FA3;
54
+  color: darkblue;
65 55
 }
66 56
 
67 57
 a img {
@@ -181,41 +171,77 @@ input.radio {
181 171
   border: 0px;
182 172
 }
183 173
 
174
+table {
175
+  width: 100%;
176
+}
184 177
 
178
+table caption {
179
+  font-weight: bold;
180
+  text-align: left;
181
+  margin: 5px 0;
182
+}
185 183
 
186 184
 
187 185
 /**************************************************************
188 186
    Custom div and span
189 187
  **************************************************************/
190
-#apptitle h1{
191
-  font-size: 1.6em;
192
-  margin-left: 200px;
193
-  margin-bottom: 10px;
194
-  border-bottom: 0px
195
-  
188
+
189
+div#outer {
190
+  margin: auto;
191
+  padding: 0 20px;
192
+  width: 600px;
193
+  height: 100%;
194
+  text-align: center;
195
+  background-color: white;
196
+  border-left: 5px dashed orange;
197
+  border-right: 5px dashed orange;
198
+}
199
+
200
+
201
+#apptitle {
202
+  padding-top: 20px;
203
+  padding-bottom: 10px;
204
+  margin-bottom: 20px;
205
+  border-bottom: 2px solid #555;
206
+}
207
+
208
+#footer {
209
+  border-top: 2px solid #555;
210
+  margin-top: 30px;
211
+  padding-top: 10px;
212
+  background-color: white;
196 213
 }
197 214
 
198 215
 #container {
199 216
   text-align: left;
200
-  width: 500px;
217
+  background-color: white;
201 218
 }
202 219
 
203 220
 #search {
204 221
   font-size: 1.0em;
205
-  border-bottom: 6px solid #ddd;
222
+  padding: 10px 0;
223
+  text-align: center;
224
+}
225
+
226
+#search table {
227
+  width: 320px;
228
+  margin: 0 auto;
229
+}
230
+
231
+#search td {
232
+  white-space: nowrap;
206 233
 }
207 234
 
208 235
 #result {
209 236
   font-size: 1.0em;
210
-  border-bottom: 6px solid #ddd;
211 237
 }
212 238
 
213
-#result thead{
239
+#result thead {
214 240
   font-size: 1.2em;
215 241
   font-weight: bold;	
216 242
 }
217 243
 
218
-#result tr{
244
+#result tr {
219 245
   line-height: 120%;
220 246
 }
221 247
 

+ 25
- 10
dddsample/src/test/java/se/citerus/dddsample/domain/CargoTest.java Visa fil

@@ -1,6 +1,7 @@
1 1
 package se.citerus.dddsample.domain;
2 2
 
3 3
 import junit.framework.TestCase;
4
+import static se.citerus.dddsample.domain.SampleLocations.*;
4 5
 
5 6
 import java.text.DateFormat;
6 7
 import java.text.ParseException;
@@ -9,8 +10,6 @@ import java.util.ArrayList;
9 10
 import java.util.Collection;
10 11
 import java.util.Date;
11 12
 
12
-import static se.citerus.dddsample.domain.SampleLocations.*;
13
-
14 13
 public class CargoTest extends TestCase {
15 14
 
16 15
   // TODO:
@@ -103,6 +102,28 @@ public class CargoTest extends TestCase {
103 102
     assertTrue(cargo.isUnloadedAtDestination());
104 103
   }
105 104
 
105
+  /* TODO implement nextExpectedEvent
106
+  public void testNextExpectedEvent() {
107
+    Cargo cargo = setUpCargoWithItinerary(HANGZOU, TOKYO, NEWYORK);
108
+    CarrierMovementId cmid = new CarrierMovementId("CM1");
109
+    CarrierMovement cm1 = new CarrierMovement(cmid, HANGZOU, TOKYO);
110
+    CarrierMovement cm2 = new CarrierMovement(cmid, TOKYO, NEWYORK);
111
+
112
+    HandlingEvent event1 = new HandlingEvent(cargo, new Date(), new Date(), HandlingEvent.Type.RECEIVE, HANGZOU, null);
113
+
114
+    assertEquals(event1, cargo.nextExpectedEvent());
115
+
116
+    cargo.deliveryHistory().addEvent(event1);
117
+
118
+    HandlingEvent event2 = new HandlingEvent(cargo, new Date(), new Date(), HandlingEvent.Type.LOAD, HANGZOU, cm1);
119
+
120
+    assertEquals(event2, cargo.nextExpectedEvent());
121
+
122
+    cargo.deliveryHistory().addEvent(event2);
123
+  }
124
+  */
125
+
126
+
106 127
   // TODO: Generate test data some better way
107 128
   private Cargo populateCargoReceivedStockholm() throws Exception {
108 129
     final Cargo cargo = new Cargo(new TrackingId("XYZ"), STOCKHOLM, MELBOURNE);
@@ -204,9 +225,8 @@ public class CargoTest extends TestCase {
204 225
   }
205 226
 
206 227
   public void testIsMisdirected() throws Exception {
207
-
208 228
     //A cargo with no itinerary is not misdirected
209
-    Cargo cargo = new Cargo(new TrackingId("TRKID"));
229
+    Cargo cargo = new Cargo(new TrackingId("TRKID"), SHANGHAI, GOTHENBURG);
210 230
     assertFalse(cargo.isMisdirected());
211 231
 
212 232
     cargo = setUpCargoWithItinerary(SHANGHAI, ROTTERDAM, GOTHENBURG);
@@ -267,12 +287,7 @@ public class CargoTest extends TestCase {
267 287
   }
268 288
 
269 289
   private Cargo setUpCargoWithItinerary(Location origin, Location midpoint, Location destination) {
270
-    Cargo cargo = new Cargo(new TrackingId("CARGO1")); //Immutable things go into the constructor
271
-
272
-    //Mutable things in setters
273
-    cargo.setOrigin(origin);
274
-    cargo.setDestination(destination);
275
-
290
+    Cargo cargo = new Cargo(new TrackingId("CARGO1"), origin, destination);
276 291
 
277 292
     Itinerary itinerary = new Itinerary(
278 293
        new Leg(new CarrierMovementId("ABC"), origin, midpoint),

+ 8
- 9
dddsample/src/test/java/se/citerus/dddsample/domain/CarrierMovementTest.java Visa fil

@@ -1,12 +1,11 @@
1 1
 package se.citerus.dddsample.domain;
2 2
 
3 3
 import junit.framework.TestCase;
4
+import static se.citerus.dddsample.domain.SampleLocations.HAMBURG;
5
+import static se.citerus.dddsample.domain.SampleLocations.STOCKHOLM;
4 6
 
5 7
 public class CarrierMovementTest extends TestCase {
6 8
 
7
-  Location stockholm = new Location(new UnLocode("SE", "STO"), "Stockholm");
8
-  Location hamburg = new Location(new UnLocode("DE", "HAM"), "Hamburg");
9
-
10 9
   public void testConstructor() throws Exception {
11 10
     CarrierMovementId id = new CarrierMovementId("CAR001");
12 11
 
@@ -21,12 +20,12 @@ public class CarrierMovementTest extends TestCase {
21 20
     } catch (IllegalArgumentException expected) {}
22 21
 
23 22
     try {
24
-      new CarrierMovement(id, stockholm, null);
23
+      new CarrierMovement(id, STOCKHOLM, null);
25 24
       fail("Should not accept null constructor arguments");
26 25
     } catch (IllegalArgumentException expected) {}
27 26
 
28 27
     // Legal
29
-    new CarrierMovement(id, stockholm, hamburg);
28
+    new CarrierMovement(id, STOCKHOLM, HAMBURG);
30 29
   }
31 30
 
32 31
   public void testSameValueAsEqualsHashCode() throws Exception {
@@ -34,10 +33,10 @@ public class CarrierMovementTest extends TestCase {
34 33
     CarrierMovementId id2a = new CarrierMovementId("CAR2");
35 34
     CarrierMovementId id2b = new CarrierMovementId("CAR2");
36 35
 
37
-    CarrierMovement cm1 = new CarrierMovement(id1, stockholm, hamburg);
38
-    CarrierMovement cm2 = new CarrierMovement(id1, stockholm, hamburg);
39
-    CarrierMovement cm3 = new CarrierMovement(id2a, hamburg, stockholm);
40
-    CarrierMovement cm4 = new CarrierMovement(id2b, hamburg, stockholm);
36
+    CarrierMovement cm1 = new CarrierMovement(id1, STOCKHOLM, HAMBURG);
37
+    CarrierMovement cm2 = new CarrierMovement(id1, STOCKHOLM, HAMBURG);
38
+    CarrierMovement cm3 = new CarrierMovement(id2a, HAMBURG, STOCKHOLM);
39
+    CarrierMovement cm4 = new CarrierMovement(id2b, HAMBURG, STOCKHOLM);
41 40
 
42 41
     assertTrue(cm1.sameIdentityAs(cm2));
43 42
     assertFalse(cm2.sameIdentityAs(cm3));

+ 1
- 1
dddsample/src/test/java/se/citerus/dddsample/domain/DeliveryHistoryTest.java Visa fil

@@ -36,7 +36,7 @@ public class DeliveryHistoryTest extends TestCase {
36 36
   public void testCargoStatusFromLastHandlingEvent() {
37 37
     DeliveryHistory deliveryHistory = new DeliveryHistory();
38 38
 
39
-    assertEquals(StatusCode.NOT_RECIEVED, deliveryHistory.status());
39
+    assertEquals(StatusCode.NOT_RECEIVED, deliveryHistory.status());
40 40
 
41 41
     deliveryHistory.addEvent(new HandlingEvent(cargo, new Date(10), new Date(11), HandlingEvent.Type.RECEIVE, HAMBURG, null));
42 42
     assertEquals(StatusCode.IN_PORT, deliveryHistory.status());

+ 13
- 13
dddsample/src/test/java/se/citerus/dddsample/domain/HandlingEventTest.java Visa fil

@@ -3,30 +3,30 @@ package se.citerus.dddsample.domain;
3 3
 import junit.framework.TestCase;
4 4
 import se.citerus.dddsample.domain.HandlingEvent.Type;
5 5
 import static se.citerus.dddsample.domain.HandlingEvent.Type.*;
6
+import static se.citerus.dddsample.domain.SampleLocations.HONGKONG;
7
+import static se.citerus.dddsample.domain.SampleLocations.NEWYORK;
6 8
 
7 9
 import static java.util.Arrays.asList;
8 10
 import java.util.Date;
9 11
 
10 12
 public class HandlingEventTest extends TestCase {
11
-  private final Location origin = new Location(new UnLocode("FR","OMX"), "From");
12
-  private final Location finalDestination = new Location(new UnLocode("TO","YYY"), "To");
13
-  private final Location a5 = new Location(new UnLocode("AA","AAA"), "AAAAA");
14
-  private final Location b5 = new Location(new UnLocode("BB","BBB"), "BBBBB");
15
-  private final Cargo cargo = new Cargo(new TrackingId("XYZ"), origin, finalDestination);
13
+  private final Location a5 = new Location(new UnLocode("AAAAA"), "AAAAA");
14
+  private final Location b5 = new Location(new UnLocode("BBBBB"), "BBBBB");
15
+  private final Cargo cargo = new Cargo(new TrackingId("XYZ"), HONGKONG, NEWYORK);
16 16
 
17 17
   public void testNewWithCarrierMovement() throws Exception {
18
-    CarrierMovement carrierMovement = new CarrierMovement(new CarrierMovementId("C01"), origin, finalDestination);
18
+    CarrierMovement carrierMovement = new CarrierMovement(new CarrierMovementId("C01"), HONGKONG, NEWYORK);
19 19
 
20
-    HandlingEvent e1 = new HandlingEvent(cargo, new Date(), new Date(), LOAD, origin, carrierMovement);
21
-    assertEquals(origin, e1.location());
20
+    HandlingEvent e1 = new HandlingEvent(cargo, new Date(), new Date(), LOAD, HONGKONG, carrierMovement);
21
+    assertEquals(HONGKONG, e1.location());
22 22
 
23
-    HandlingEvent e2 = new HandlingEvent(cargo, new Date(), new Date(), UNLOAD, finalDestination, carrierMovement);
24
-    assertEquals(finalDestination, e2.location());
23
+    HandlingEvent e2 = new HandlingEvent(cargo, new Date(), new Date(), UNLOAD, NEWYORK, carrierMovement);
24
+    assertEquals(NEWYORK, e2.location());
25 25
 
26 26
       // These event types prohibit a carrier movement association
27 27
     for (Type type : asList(CLAIM, RECEIVE, CUSTOMS)) {
28 28
       try {
29
-        new HandlingEvent(cargo, new Date(), new Date(), type, origin, carrierMovement);
29
+        new HandlingEvent(cargo, new Date(), new Date(), type, HONGKONG, carrierMovement);
30 30
         fail("Handling event type " + type + " prohibits carrier movement");
31 31
       } catch (IllegalArgumentException expected) {}
32 32
     }
@@ -34,14 +34,14 @@ public class HandlingEventTest extends TestCase {
34 34
       // These event types requires a carrier movement association
35 35
     for (Type type : asList(LOAD, UNLOAD)) {
36 36
         try {
37
-          new HandlingEvent(cargo, new Date(), new Date(), type, origin, null);
37
+          new HandlingEvent(cargo, new Date(), new Date(), type, HONGKONG, null);
38 38
             fail("Handling event type " + type + " requires carrier movement");
39 39
         } catch (IllegalArgumentException expected) {}
40 40
     }
41 41
   }
42 42
 
43 43
   public void testNewWithLocation() throws Exception {
44
-    Location location = new Location(new UnLocode("FO","OOO"), "Foo");
44
+    Location location = new Location(new UnLocode("FOOOO"), "Foo");
45 45
     HandlingEvent e1 = new HandlingEvent(cargo, new Date(), new Date(), Type.CLAIM, location, null);
46 46
     assertEquals(location, e1.location());
47 47
   }

+ 19
- 29
dddsample/src/test/java/se/citerus/dddsample/domain/ItineraryTest.java Visa fil

@@ -1,73 +1,63 @@
1 1
 package se.citerus.dddsample.domain;
2 2
 
3 3
 import junit.framework.TestCase;
4
+import static se.citerus.dddsample.domain.SampleLocations.*;
4 5
 
5 6
 import java.util.ArrayList;
6 7
 import java.util.Date;
7 8
 import java.util.List;
8 9
 
9 10
 public class ItineraryTest extends TestCase {
10
-  private final Location shanghai = new Location(new UnLocode("CN", "SHA"), "Shanghai");
11
-  private final Location rotterdam = new Location(new UnLocode("NL", "RTM"), "Rotterdam");
12
-  private final Location goteborg = new Location(new UnLocode("SE", "GOT"), "Goteborg");
13
-  private final Location hangzhou = new Location(new UnLocode("CN", "HGH"), "Hangzhou");
14
-  private final Location nyc = new Location(new UnLocode("US", "NYC"), "New York");
15
-  private final Location longBeach = new Location(new UnLocode("US", "LGB"), "Long Beach");
16
-  private final CarrierMovement abc = new CarrierMovement(new CarrierMovementId("ABC"), shanghai, rotterdam);
17
-  private final CarrierMovement def = new CarrierMovement(new CarrierMovementId("DEF"), rotterdam, goteborg);
18
-  private final CarrierMovement ghi = new CarrierMovement(new CarrierMovementId("GHI"), rotterdam, nyc);
19
-  private final CarrierMovement jkl = new CarrierMovement(new CarrierMovementId("JKL"), shanghai, longBeach);
11
+  private final CarrierMovement abc = new CarrierMovement(new CarrierMovementId("ABC"), SHANGHAI, ROTTERDAM);
12
+  private final CarrierMovement def = new CarrierMovement(new CarrierMovementId("DEF"), ROTTERDAM, GOTHENBURG);
13
+  private final CarrierMovement ghi = new CarrierMovement(new CarrierMovementId("GHI"), ROTTERDAM, NEWYORK);
14
+  private final CarrierMovement jkl = new CarrierMovement(new CarrierMovementId("JKL"), SHANGHAI, HELSINKI);
20 15
 
21 16
   public void testCargoOnTrack() throws Exception {
22 17
 
23
-    Cargo cargo = new Cargo(new TrackingId("CARGO1")); //Immutable things go into the constructor
24
-
25
-    //Mutable things in setters
26
-    cargo.setOrigin(shanghai);
27
-    cargo.setDestination(goteborg);
28
-
18
+    Cargo cargo = new Cargo(new TrackingId("CARGO1"), SHANGHAI, GOTHENBURG);
29 19
 
30 20
     Itinerary itinerary = new Itinerary(
31
-       new Leg(new CarrierMovementId("ABC"), shanghai, rotterdam),
32
-       new Leg(new CarrierMovementId("DEF"), rotterdam, goteborg)
21
+       new Leg(new CarrierMovementId("ABC"), SHANGHAI, ROTTERDAM),
22
+       new Leg(new CarrierMovementId("DEF"), ROTTERDAM, GOTHENBURG)
33 23
     );
34 24
 
35 25
     //Happy path
36
-    HandlingEvent event = new HandlingEvent(cargo, new Date(), new Date(), HandlingEvent.Type.RECEIVE, shanghai,null);
26
+    HandlingEvent event = new HandlingEvent(cargo, new Date(), new Date(), HandlingEvent.Type.RECEIVE, SHANGHAI,null);
37 27
     assertTrue(itinerary.isExpected(event));
38 28
 
39
-    event = new HandlingEvent(cargo, new Date(), new Date(), HandlingEvent.Type.LOAD, shanghai, abc);
29
+    event = new HandlingEvent(cargo, new Date(), new Date(), HandlingEvent.Type.LOAD, SHANGHAI, abc);
40 30
     assertTrue(itinerary.isExpected(event));
41 31
 
42
-    event = new HandlingEvent(cargo, new Date(), new Date(), HandlingEvent.Type.UNLOAD, rotterdam, abc);
32
+    event = new HandlingEvent(cargo, new Date(), new Date(), HandlingEvent.Type.UNLOAD, ROTTERDAM, abc);
43 33
     assertTrue(itinerary.isExpected(event));
44 34
 
45
-    event = new HandlingEvent(cargo, new Date(), new Date(), HandlingEvent.Type.LOAD, rotterdam, def);
35
+    event = new HandlingEvent(cargo, new Date(), new Date(), HandlingEvent.Type.LOAD, ROTTERDAM, def);
46 36
     assertTrue(itinerary.isExpected(event));
47 37
 
48
-    event = new HandlingEvent(cargo, new Date(), new Date(), HandlingEvent.Type.UNLOAD, goteborg, def);
38
+    event = new HandlingEvent(cargo, new Date(), new Date(), HandlingEvent.Type.UNLOAD, GOTHENBURG, def);
49 39
     assertTrue(itinerary.isExpected(event));
50 40
 
51
-    event = new HandlingEvent(cargo, new Date(), new Date(), HandlingEvent.Type.CLAIM, goteborg, null);
41
+    event = new HandlingEvent(cargo, new Date(), new Date(), HandlingEvent.Type.CLAIM, GOTHENBURG, null);
52 42
     assertTrue(itinerary.isExpected(event));
53 43
 
54 44
     //Customs event changes nothing
55
-    event = new HandlingEvent(cargo, new Date(), new Date(), HandlingEvent.Type.CUSTOMS, goteborg, null);
45
+    event = new HandlingEvent(cargo, new Date(), new Date(), HandlingEvent.Type.CUSTOMS, GOTHENBURG, null);
56 46
     assertTrue(itinerary.isExpected(event));
57 47
 
58 48
     //Received at the wrong location
59
-    event = new HandlingEvent(cargo, new Date(), new Date(), HandlingEvent.Type.RECEIVE, hangzhou, null);
49
+    event = new HandlingEvent(cargo, new Date(), new Date(), HandlingEvent.Type.RECEIVE, HANGZOU, null);
60 50
     assertFalse(itinerary.isExpected(event));
61 51
 
62 52
     //Loaded to onto the wrong ship, correct location
63
-    event = new HandlingEvent(cargo, new Date(), new Date(), HandlingEvent.Type.LOAD, rotterdam, ghi);
53
+    event = new HandlingEvent(cargo, new Date(), new Date(), HandlingEvent.Type.LOAD, ROTTERDAM, ghi);
64 54
     assertFalse(itinerary.isExpected(event));
65 55
 
66 56
     //Unloaded from the wrong ship in the wrong location
67
-    event = new HandlingEvent(cargo, new Date(), new Date(), HandlingEvent.Type.UNLOAD, longBeach, jkl);
57
+    event = new HandlingEvent(cargo, new Date(), new Date(), HandlingEvent.Type.UNLOAD, HELSINKI, jkl);
68 58
     assertFalse(itinerary.isExpected(event));
69 59
 
70
-    event = new HandlingEvent(cargo, new Date(), new Date(), HandlingEvent.Type.CLAIM, rotterdam, null);
60
+    event = new HandlingEvent(cargo, new Date(), new Date(), HandlingEvent.Type.CLAIM, ROTTERDAM, null);
71 61
     assertFalse(itinerary.isExpected(event));
72 62
 
73 63
   }

+ 5
- 5
dddsample/src/test/java/se/citerus/dddsample/domain/LocationTest.java Visa fil

@@ -6,15 +6,15 @@ public class LocationTest extends TestCase {
6 6
 
7 7
   public void testEquals() {
8 8
     // Same UN locode - equal
9
-    assertTrue(new Location(new UnLocode("AT","EST"),"test-name").
10
-        equals(new Location(new UnLocode("AT","EST"),"test-name")));
9
+    assertTrue(new Location(new UnLocode("ATEST"),"test-name").
10
+        equals(new Location(new UnLocode("ATEST"),"test-name")));
11 11
 
12 12
     // Different UN locodes - not equal
13
-    assertFalse(new Location(new UnLocode("AT","EST"),"test-name").
14
-         equals(new Location(new UnLocode("TE","STB"), "test-name")));
13
+    assertFalse(new Location(new UnLocode("ATEST"),"test-name").
14
+         equals(new Location(new UnLocode("TESTB"), "test-name")));
15 15
 
16 16
     // Always equal to itself
17
-    Location location = new Location(new UnLocode("AT","EST"),"test-name");
17
+    Location location = new Location(new UnLocode("ATEST"),"test-name");
18 18
     assertTrue(location.equals(location));
19 19
 
20 20
     // Never equal to null

+ 12
- 12
dddsample/src/test/java/se/citerus/dddsample/domain/SampleLocations.java Visa fil

@@ -10,18 +10,18 @@ import java.util.List;
10 10
  */
11 11
 public class SampleLocations {
12 12
 
13
-  public static final Location HONGKONG = new Location(new UnLocode("CN", "HKG"), "Hongkong");
14
-  public static final Location MELBOURNE = new Location(new UnLocode("AU","MEL"), "Melbourne");
15
-  public static final Location STOCKHOLM = new Location(new UnLocode("SE","STO"), "Stockholm");
16
-  public static final Location HELSINKI = new Location(new UnLocode("FI","HEL"), "Helsinki");
17
-  public static final Location CHICAGO = new Location(new UnLocode("US", "CHI"), "Chicago");
18
-  public static final Location TOKYO = new Location(new UnLocode("JN","TKO"), "Tokyo");
19
-  public static final Location HAMBURG = new Location(new UnLocode("DE", "HAM"), "Hamburg");
20
-  public static final Location SHANGHAI = new Location(new UnLocode("CN", "SHA"), "Shanghai");
21
-  public static final Location ROTTERDAM = new Location(new UnLocode("NL", "RTM"), "Rotterdam");
22
-  public static final Location GOTHENBURG = new Location(new UnLocode("SE", "GOT"), "Göteborg");
23
-  public static final Location HANGZOU = new Location(new UnLocode("CN", "HGH"), "Hangzhou");
24
-  public static final Location NEWYORK = new Location(new UnLocode("US", "NYC"), "New York");
13
+  public static final Location HONGKONG = new Location(new UnLocode("CNHKG"), "Hongkong");
14
+  public static final Location MELBOURNE = new Location(new UnLocode("AUMEL"), "Melbourne");
15
+  public static final Location STOCKHOLM = new Location(new UnLocode("SESTO"), "Stockholm");
16
+  public static final Location HELSINKI = new Location(new UnLocode("FIHEL"), "Helsinki");
17
+  public static final Location CHICAGO = new Location(new UnLocode("USCHI"), "Chicago");
18
+  public static final Location TOKYO = new Location(new UnLocode("JNTKO"), "Tokyo");
19
+  public static final Location HAMBURG = new Location(new UnLocode("DEHAM"), "Hamburg");
20
+  public static final Location SHANGHAI = new Location(new UnLocode("CNSHA"), "Shanghai");
21
+  public static final Location ROTTERDAM = new Location(new UnLocode("NLRTM"), "Rotterdam");
22
+  public static final Location GOTHENBURG = new Location(new UnLocode("SEGOT"), "Göteborg");
23
+  public static final Location HANGZOU = new Location(new UnLocode("CNHGH"), "Hangzhou");
24
+  public static final Location NEWYORK = new Location(new UnLocode("USNYC"), "New York");
25 25
 
26 26
   public static final List<Location> all = new ArrayList<Location>();
27 27
 

+ 8
- 11
dddsample/src/test/java/se/citerus/dddsample/domain/TrackingScenarioTest.java Visa fil

@@ -1,6 +1,7 @@
1 1
 package se.citerus.dddsample.domain;
2 2
 
3 3
 import junit.framework.TestCase;
4
+import static se.citerus.dddsample.domain.SampleLocations.*;
4 5
 
5 6
 import java.text.DateFormat;
6 7
 import java.text.ParseException;
@@ -10,10 +11,6 @@ import java.util.Date;
10 11
 import java.util.List;
11 12
 
12 13
 public class TrackingScenarioTest extends TestCase {
13
-  private final Location stockholm = new Location(new UnLocode("SE","STO"), "Stockholm");
14
-  private final Location hamburg = new Location(new UnLocode("DE","HAM"), "Hamburg");
15
-  private final Location melbourne = new Location(new UnLocode("AU","MEL"), "Melbourne");
16
-  private final Location hongkong = new Location(new UnLocode("CN","HKG"), "Hongkong");
17 14
 
18 15
   public void testTrackingScenarioStage1() throws Exception {
19 16
 
@@ -34,22 +31,22 @@ public class TrackingScenarioTest extends TestCase {
34 31
 
35 32
   private DeliveryHistory populateDeliveryHistory(Cargo cargo) throws Exception {
36 33
     final CarrierMovement stockholmToHamburg = new CarrierMovement(
37
-            new CarrierMovementId("CAR_001"), stockholm, hamburg);
34
+            new CarrierMovementId("CAR_001"), STOCKHOLM, HAMBURG);
38 35
 
39 36
     final CarrierMovement hamburgToHongKong = new CarrierMovement(
40
-            new CarrierMovementId("CAR_002"), hamburg, hongkong);
37
+            new CarrierMovementId("CAR_002"), HAMBURG, HONGKONG);
41 38
     DeliveryHistory dh = new DeliveryHistory();
42 39
     dh.addAllEvents(Arrays.asList(
43
-            new HandlingEvent(cargo, getDate("2007-12-01"), new Date(), HandlingEvent.Type.LOAD, stockholm, stockholmToHamburg),
44
-            new HandlingEvent(cargo, getDate("2007-12-02"), new Date(), HandlingEvent.Type.UNLOAD, hamburg, stockholmToHamburg),
45
-            new HandlingEvent(cargo, getDate("2007-12-03"), new Date(), HandlingEvent.Type.LOAD, hamburg, hamburgToHongKong),
46
-            new HandlingEvent(cargo, getDate("2007-12-05"), new Date(), HandlingEvent.Type.UNLOAD, hongkong, hamburgToHongKong)
40
+            new HandlingEvent(cargo, getDate("2007-12-01"), new Date(), HandlingEvent.Type.LOAD, STOCKHOLM, stockholmToHamburg),
41
+            new HandlingEvent(cargo, getDate("2007-12-02"), new Date(), HandlingEvent.Type.UNLOAD, HAMBURG, stockholmToHamburg),
42
+            new HandlingEvent(cargo, getDate("2007-12-03"), new Date(), HandlingEvent.Type.LOAD, HAMBURG, hamburgToHongKong),
43
+            new HandlingEvent(cargo, getDate("2007-12-05"), new Date(), HandlingEvent.Type.UNLOAD, HONGKONG, hamburgToHongKong)
47 44
     ));
48 45
     return dh;
49 46
   }
50 47
 
51 48
   private Cargo populateCargo() throws Exception {
52
-    final Cargo cargo = new Cargo(new TrackingId("XYZ"), stockholm, melbourne);
49
+    final Cargo cargo = new Cargo(new TrackingId("XYZ"), STOCKHOLM, MELBOURNE);
53 50
 
54 51
     return cargo;
55 52
   }

+ 21
- 23
dddsample/src/test/java/se/citerus/dddsample/domain/UnLocodeTest.java Visa fil

@@ -5,52 +5,50 @@ import junit.framework.TestCase;
5 5
 public class UnLocodeTest extends TestCase {
6 6
 
7 7
   public void testNew() throws Exception {
8
-    assertValid("AA", "234");
9
-    assertValid("AA", "A9B");
10
-    assertValid("AA", "AAA");
8
+    assertValid("AA234");
9
+    assertValid("AAA9B");
10
+    assertValid("AAAAA");
11 11
     
12
-    assertInvalid("A", "AAA");
13
-    assertInvalid("AAA", "AAA");
14
-    assertInvalid("AA", "AA");
15
-    assertInvalid("AA", "AAAA");
16
-    assertInvalid("22", "AAA");
17
-    assertInvalid("AA", "111");
18
-    assertInvalid(null, "AAA");
19
-    assertInvalid("AA", null);
20
-    assertInvalid(null, null);
12
+    assertInvalid("AAAA");
13
+    assertInvalid("AAAAAA");
14
+    assertInvalid("AAAA");
15
+    assertInvalid("AAAAAA");
16
+    assertInvalid("22AAA");
17
+    assertInvalid("AA111");
18
+    assertInvalid(null);
21 19
   }
22 20
 
23 21
   public void testIdString() throws Exception {
24
-    assertEquals("ABCDE", new UnLocode("Ab", "cDe").idString());
22
+    assertEquals("ABCDE", new UnLocode("AbcDe").idString());
25 23
   }
26 24
 
27 25
   public void testEquals() throws Exception {
28
-    UnLocode allCaps = new UnLocode("AB", "CDE");
29
-    UnLocode mixedCase = new UnLocode("aB", "cDe");
26
+    UnLocode allCaps = new UnLocode("ABCDE");
27
+    UnLocode mixedCase = new UnLocode("aBcDe");
30 28
 
31 29
     assertTrue(allCaps.equals(mixedCase));
32 30
     assertTrue(mixedCase.equals(allCaps));
33 31
     assertTrue(allCaps.equals(allCaps));
34 32
 
35 33
     assertFalse(allCaps.equals(null));
36
-    assertFalse(allCaps.equals(new UnLocode("FG","HIJ")));
34
+    assertFalse(allCaps.equals(new UnLocode("FGHIJ")));
37 35
   }
38 36
 
39 37
   public void testHashCode() throws Exception {
40
-    UnLocode allCaps = new UnLocode("AB", "CDE");
41
-    UnLocode mixedCase = new UnLocode("aB", "cDe");
38
+    UnLocode allCaps = new UnLocode("ABCDE");
39
+    UnLocode mixedCase = new UnLocode("aBcDe");
42 40
 
43 41
     assertEquals(allCaps.hashCode(), mixedCase.hashCode());  
44 42
   }
45 43
   
46
-  private void assertValid(String countryCode, String locationCode) {
47
-    new UnLocode(countryCode, locationCode);
44
+  private void assertValid(String unlocode) {
45
+    new UnLocode(unlocode);
48 46
   }
49 47
 
50
-  private void assertInvalid(String countryCode, String locationCode) {
48
+  private void assertInvalid(String unlocode) {
51 49
     try {
52
-      new UnLocode(countryCode, locationCode);
53
-      fail("The combination [" + countryCode + "," + locationCode + "] is not a valid UnLocode");
50
+      new UnLocode(unlocode);
51
+      fail("The combination [" + unlocode + "] is not a valid UnLocode");
54 52
     } catch (IllegalArgumentException expected) {}
55 53
   }
56 54
 

+ 10
- 3
dddsample/src/test/java/se/citerus/dddsample/repository/CargoRepositoryTest.java Visa fil

@@ -1,12 +1,13 @@
1 1
 package se.citerus.dddsample.repository;
2 2
 
3 3
 import se.citerus.dddsample.domain.*;
4
-import static se.citerus.dddsample.domain.HandlingEvent.Type.*;
4
+import static se.citerus.dddsample.domain.HandlingEvent.Type.LOAD;
5
+import static se.citerus.dddsample.domain.HandlingEvent.Type.RECEIVE;
5 6
 import static se.citerus.dddsample.domain.SampleLocations.*;
6 7
 
7
-import java.util.Map;
8
-import java.util.List;
9 8
 import java.util.Date;
9
+import java.util.List;
10
+import java.util.Map;
10 11
 
11 12
 public class CargoRepositoryTest extends AbstractRepositoryTest {
12 13
 
@@ -82,4 +83,10 @@ public class CargoRepositoryTest extends AbstractRepositoryTest {
82 83
     // TODO: check origin/finalDestination ids
83 84
   }
84 85
 
86
+  public void testFindAll() {
87
+    List<Cargo> all = cargoRepository.findAll();
88
+    assertNotNull(all);
89
+    assertEquals(6, all.size());
90
+  }
91
+
85 92
 }

+ 1
- 1
dddsample/src/test/java/se/citerus/dddsample/repository/HandlingEventRepositoryTest.java Visa fil

@@ -25,7 +25,7 @@ public class HandlingEventRepositoryTest extends AbstractRepositoryTest {
25 25
   }
26 26
 
27 27
   public void testSave() {
28
-    Location location = locationRepository.find(new UnLocode("SE","STO"));
28
+    Location location = locationRepository.find(new UnLocode("SESTO"));
29 29
 
30 30
     Cargo cargo = cargoRepository.find(new TrackingId("XYZ"));
31 31
     Date completionTime = new Date(10);

+ 2
- 2
dddsample/src/test/java/se/citerus/dddsample/repository/LocationRepositoryTest.java Visa fil

@@ -9,12 +9,12 @@ public class LocationRepositoryTest extends AbstractRepositoryTest {
9 9
   private LocationRepository locationRepository;
10 10
   
11 11
   public void testFind() throws Exception {
12
-    final UnLocode melbourne = new UnLocode("AU", "MEL");
12
+    final UnLocode melbourne = new UnLocode("AUMEL");
13 13
     Location location = locationRepository.find(melbourne);
14 14
     assertNotNull(location);
15 15
     assertEquals(melbourne, location.unLocode());
16 16
 
17
-    assertNull(locationRepository.find(new UnLocode("NO","LOC")));
17
+    assertNull(locationRepository.find(new UnLocode("NOLOC")));
18 18
   }
19 19
 
20 20
   public void testFindAll() throws Exception {

+ 2
- 2
dddsample/src/test/java/se/citerus/dddsample/service/HandlingEventServiceTest.java Visa fil

@@ -54,7 +54,7 @@ public class HandlingEventServiceTest extends TestCase {
54 54
     final CarrierMovementId carrierMovementId = new CarrierMovementId("AAA_BBB");
55 55
     expect(carrierMovementRepository.find(carrierMovementId)).andReturn(cmAAA_BBB);
56 56
 
57
-    final UnLocode unLocode = new UnLocode("SE", "STO");
57
+    final UnLocode unLocode = new UnLocode("SESTO");
58 58
     expect(locationRepository.find(unLocode)).andReturn(STOCKHOLM);
59 59
 
60 60
     // TODO: does not inspect the handling event instance in a sufficient way
@@ -123,7 +123,7 @@ public class HandlingEventServiceTest extends TestCase {
123 123
 
124 124
     final TrackingId trackingId = new TrackingId("XYZ");
125 125
     expect(cargoRepository.find(trackingId)).andReturn(cargoXYZ);
126
-    UnLocode wayOff = new UnLocode("XX", "YYY");
126
+    UnLocode wayOff = new UnLocode("XXYYY");
127 127
     expect(locationRepository.find(wayOff)).andReturn(null);
128 128
     
129 129
     replay(cargoRepository, carrierMovementRepository, handlingEventRepository, locationRepository, eventService);

+ 4
- 4
dddsample/src/test/java/se/citerus/dddsample/service/RoutingScenarioTest.java Visa fil

@@ -5,7 +5,7 @@ import se.citerus.dddsample.domain.*;
5 5
 import se.citerus.dddsample.repository.CargoRepository;
6 6
 
7 7
 import java.util.Date;
8
-import java.util.Set;
8
+import java.util.List;
9 9
 
10 10
 public class RoutingScenarioTest extends TestCase {
11 11
 
@@ -24,7 +24,7 @@ public class RoutingScenarioTest extends TestCase {
24 24
       satisfy the given specification (must arrive in three days, must not
25 25
       cost more than $10,000 etc).
26 26
      */
27
-    Set<Itinerary> itineraryCandidates = routingService.calculatePossibleRoutes(trackingId, specification);
27
+    List<Itinerary> itineraryCandidates = routingService.calculatePossibleRoutes(trackingId, specification);
28 28
 
29 29
     /*
30 30
       Someone, or something, selects the most appropriate itinerary and
@@ -36,7 +36,7 @@ public class RoutingScenarioTest extends TestCase {
36 36
     /*
37 37
       A number of events occur, all of which are according to plan
38 38
      */
39
-    handlingEventService.register(new Date(), trackingId, new CarrierMovementId("A001"), new UnLocode("SE","STO"), null);
39
+    handlingEventService.register(new Date(), trackingId, new CarrierMovementId("A001"), new UnLocode("SESTO"), null);
40 40
     handlingEventService.register(new Date(), trackingId, new CarrierMovementId("B002"), null, null);
41 41
     handlingEventService.register(new Date(), trackingId, new CarrierMovementId("C003"), null, null);
42 42
 
@@ -62,7 +62,7 @@ public class RoutingScenarioTest extends TestCase {
62 62
   }
63 63
 
64 64
 
65
-  private Itinerary stubbedItinerarySelection(Set<Itinerary> itineraryCandidates) {
65
+  private Itinerary stubbedItinerarySelection(List<Itinerary> itineraryCandidates) {
66 66
     return itineraryCandidates.iterator().next();
67 67
   }
68 68
 

+ 1
- 2
dddsample/src/test/java/se/citerus/dddsample/service/RoutingServiceTest.java Visa fil

@@ -9,7 +9,6 @@ import se.citerus.dddsample.repository.CargoRepository;
9 9
 import se.citerus.dddsample.repository.LocationRepository;
10 10
 
11 11
 import java.util.List;
12
-import java.util.Set;
13 12
 
14 13
 public class RoutingServiceTest extends TestCase {
15 14
 
@@ -33,7 +32,7 @@ public class RoutingServiceTest extends TestCase {
33 32
     expect(cargoRepository.find(isA(TrackingId.class))).andReturn(cargo);
34 33
     replay(locationRepository, cargoRepository);
35 34
 
36
-    Set<Itinerary> candidates = routingService.calculatePossibleRoutes(trackingId, null);
35
+    List<Itinerary> candidates = routingService.calculatePossibleRoutes(trackingId, null);
37 36
     assertNotNull(candidates);
38 37
     
39 38
     for (Itinerary itinerary : candidates) {

+ 32
- 17
dddsample/src/test/java/se/citerus/dddsample/web/CargoTrackingControllerTest.java Visa fil

@@ -13,11 +13,14 @@ import se.citerus.dddsample.domain.*;
13 13
 import static se.citerus.dddsample.domain.SampleLocations.HONGKONG;
14 14
 import static se.citerus.dddsample.domain.SampleLocations.TOKYO;
15 15
 import se.citerus.dddsample.service.CargoService;
16
+import se.citerus.dddsample.service.dto.CargoRoutingDTO;
16 17
 import se.citerus.dddsample.service.dto.CargoTrackingDTO;
17 18
 import se.citerus.dddsample.service.dto.HandlingEventDTO;
19
+import se.citerus.dddsample.service.dto.LegDTO;
18 20
 import se.citerus.dddsample.web.command.TrackCommand;
19 21
 
20 22
 import java.util.Date;
23
+import java.util.List;
21 24
 
22 25
 public class CargoTrackingControllerTest extends TestCase {
23 26
   CargoTrackingController controller;
@@ -40,10 +43,7 @@ public class CargoTrackingControllerTest extends TestCase {
40 43
   }
41 44
 
42 45
   private CargoService getCargoServiceMock() {
43
-    return new CargoService() {
44
-      public TrackingId registerNew(Location origin, Location destination) {
45
-        return null;
46
-      }
46
+    return new EmptyStubCargoService() {
47 47
 
48 48
       public CargoTrackingDTO track(TrackingId trackingId) {
49 49
         Cargo cargo = new Cargo(trackingId, HONGKONG, TOKYO);
@@ -66,23 +66,11 @@ public class CargoTrackingControllerTest extends TestCase {
66 66
           true));
67 67
         return cargoDTO;
68 68
       }
69
-
70
-      public void notify(TrackingId trackingId) {
71
-      }
72 69
     };
73 70
   }
74 71
   
75 72
   private CargoService getCargoServiceNullMock() {
76
-    return new CargoService() {
77
-      public TrackingId registerNew(Location origin, Location destination) {
78
-        return null;
79
-      }
80
-
81
-      public CargoTrackingDTO track(TrackingId trackingId) {
82
-        return null;
83
-      }
84
-      public void notify(TrackingId trackingId) {}
85
-    };
73
+    return new EmptyStubCargoService();
86 74
   }
87 75
 
88 76
   public void testHandleGet() throws Exception {
@@ -130,4 +118,31 @@ public class CargoTrackingControllerTest extends TestCase {
130 118
     assertEquals(command.getTrackingId(), fe.getArguments()[0]);
131 119
   }
132 120
 
121
+  private class EmptyStubCargoService implements CargoService {
122
+    public TrackingId registerNew(UnLocode origin, UnLocode destination) {
123
+      return null;
124
+    }
125
+
126
+    public List<String> shippingLocations() {
127
+      return null;
128
+    }
129
+
130
+    public CargoTrackingDTO track(TrackingId trackingId) {
131
+      return null;
132
+    }
133
+
134
+    public void notify(TrackingId trackingId) {
135
+    }
136
+
137
+    public CargoRoutingDTO loadForRouting(TrackingId trackingId) {
138
+      return null;
139
+    }
140
+
141
+    public List<CargoRoutingDTO> loadAllForRouting() {
142
+      return null;
143
+    }
144
+
145
+    public void assignItinerary(TrackingId trackingId, List<LegDTO> legDTOs) {
146
+    }
147
+  }
133 148
 }

+ 3
- 3
dddsample/src/test/java/se/citerus/dddsample/ws/HandlinEventServiceEndpointTest.java Visa fil

@@ -29,7 +29,7 @@ public class HandlinEventServiceEndpointTest extends TestCase {
29 29
   public void testRegisterValidEvent() throws Exception {
30 30
     Date date = new Date(100);
31 31
 
32
-    handlingEventService.register(date, new TrackingId("FOO"), new CarrierMovementId("CAR_456"), new UnLocode("CN","HKG"), HandlingEvent.Type.LOAD);
32
+    handlingEventService.register(date, new TrackingId("FOO"), new CarrierMovementId("CAR_456"), new UnLocode("CNHKG"), HandlingEvent.Type.LOAD);
33 33
     replay(handlingEventService);
34 34
 
35 35
     // Tested call
@@ -41,7 +41,7 @@ public class HandlinEventServiceEndpointTest extends TestCase {
41 41
     Date date = new Date(100);
42 42
 
43 43
     TrackingId trackingId = new TrackingId("NOTFOUND");
44
-    UnLocode unlocode = new UnLocode("SE","STO");
44
+    UnLocode unlocode = new UnLocode("SESTO");
45 45
 
46 46
     handlingEventService.register(date, trackingId, null, unlocode, HandlingEvent.Type.CLAIM);
47 47
     expectLastCall().andThrow(new UnknownTrackingIdException(trackingId));
@@ -57,7 +57,7 @@ public class HandlinEventServiceEndpointTest extends TestCase {
57 57
       TrackingId trackingId = new TrackingId("XYZ");
58 58
       CarrierMovementId carrierMovementId = new CarrierMovementId("NOTFOUND");
59 59
 
60
-      handlingEventService.register(date, trackingId, carrierMovementId, new UnLocode("AU","MEL"), HandlingEvent.Type.UNLOAD);
60
+      handlingEventService.register(date, trackingId, carrierMovementId, new UnLocode("AUMEL"), HandlingEvent.Type.UNLOAD);
61 61
       expectLastCall().andThrow(new UnknownCarrierMovementIdException(carrierMovementId));
62 62
       replay(handlingEventService);
63 63