Просмотр исходного кода

Implemented cargo.nextExpectedActivity using lifecycle scenario test.

peter_backlund 17 лет назад
Родитель
Сommit
4fc923eb91

+ 54
- 2
dddsample/src/main/java/se/citerus/dddsample/domain/model/cargo/Cargo.java Просмотреть файл

4
 import se.citerus.dddsample.domain.model.Entity;
4
 import se.citerus.dddsample.domain.model.Entity;
5
 import static se.citerus.dddsample.domain.model.cargo.RoutingStatus.*;
5
 import static se.citerus.dddsample.domain.model.cargo.RoutingStatus.*;
6
 import se.citerus.dddsample.domain.model.handling.HandlingEvent;
6
 import se.citerus.dddsample.domain.model.handling.HandlingEvent;
7
+import static se.citerus.dddsample.domain.model.handling.HandlingEvent.Type.*;
7
 import se.citerus.dddsample.domain.model.location.Location;
8
 import se.citerus.dddsample.domain.model.location.Location;
8
 import se.citerus.dddsample.domain.shared.DomainObjectUtils;
9
 import se.citerus.dddsample.domain.shared.DomainObjectUtils;
9
 
10
 
10
 import java.util.Collections;
11
 import java.util.Collections;
11
 import java.util.Date;
12
 import java.util.Date;
13
+import java.util.Iterator;
12
 import java.util.List;
14
 import java.util.List;
13
 
15
 
14
 /**
16
 /**
158
   public boolean isUnloadedAtDestination() {
160
   public boolean isUnloadedAtDestination() {
159
     final HandlingEvent lastEvent = delivery.lastEvent();
161
     final HandlingEvent lastEvent = delivery.lastEvent();
160
     return lastEvent != null &&
162
     return lastEvent != null &&
161
-      HandlingEvent.Type.UNLOAD.sameValueAs(lastEvent.type()) &&
163
+      UNLOAD.sameValueAs(lastEvent.type()) &&
162
       routeSpecification.destination().sameIdentityAs(lastEvent.location());
164
       routeSpecification.destination().sameIdentityAs(lastEvent.location());
163
   }
165
   }
164
 
166
 
166
    * @return estimated time of arrival
168
    * @return estimated time of arrival
167
    */
169
    */
168
   public Date estimatedTimeOfArrival() {
170
   public Date estimatedTimeOfArrival() {
169
-    return new Date(eta.getTime());
171
+    if (eta != ETA_UNKOWN) {
172
+      return new Date(eta.getTime());
173
+    } else {
174
+      return ETA_UNKOWN;
175
+    }
176
+  }
177
+
178
+  /**
179
+   * @return the next expected activity
180
+   */
181
+  public HandlingActivity nextExpectedActivity() {
182
+    if (!onTrack()) return HandlingActivity.NONE;
183
+
184
+    final HandlingEvent lastEvent = delivery().lastEvent();
185
+
186
+    if (lastEvent == null) return new HandlingActivity(RECEIVE, origin());
187
+
188
+    switch (lastEvent.type()) {
189
+
190
+      case LOAD:
191
+        for (Leg leg : itinerary().legs()) {
192
+          if (leg.loadLocation().sameIdentityAs(lastEvent.location())) {
193
+            return new HandlingActivity(UNLOAD, leg.unloadLocation());
194
+          }
195
+        }
196
+
197
+        return HandlingActivity.NONE;
198
+
199
+      case UNLOAD:
200
+        for (Iterator<Leg> it = itinerary().legs().iterator(); it.hasNext();) {
201
+          final Leg leg = it.next();
202
+          if (leg.unloadLocation().sameIdentityAs(lastEvent.location())) {
203
+            if (it.hasNext()) {
204
+              final Leg nextLeg = it.next();
205
+              return new HandlingActivity(LOAD, nextLeg.loadLocation());
206
+            } else {
207
+              return new HandlingActivity(CLAIM, leg.unloadLocation());
208
+            }
209
+          }
210
+        }
211
+
212
+        return HandlingActivity.NONE;
213
+
214
+      case RECEIVE:
215
+        final Leg firstLeg = itinerary().legs().iterator().next();
216
+        return new HandlingActivity(LOAD, firstLeg.loadLocation());
217
+
218
+      case CLAIM:
219
+      default:
220
+        return HandlingActivity.NONE;
221
+    }
170
   }
222
   }
171
 
223
 
172
   /**
224
   /**

+ 74
- 0
dddsample/src/main/java/se/citerus/dddsample/domain/model/cargo/HandlingActivity.java Просмотреть файл

1
+package se.citerus.dddsample.domain.model.cargo;
2
+
3
+import org.apache.commons.lang.Validate;
4
+import org.apache.commons.lang.builder.EqualsBuilder;
5
+import org.apache.commons.lang.builder.HashCodeBuilder;
6
+import se.citerus.dddsample.domain.model.ValueObject;
7
+import se.citerus.dddsample.domain.model.handling.HandlingEvent;
8
+import se.citerus.dddsample.domain.model.location.Location;
9
+
10
+/**
11
+ * A handling activity represents how and where a cargo can be handled,
12
+ * and can be used to express predictions about what is expected to
13
+ * happen to a cargo in the future.
14
+ *
15
+ */
16
+public class HandlingActivity implements ValueObject<HandlingActivity> {
17
+
18
+  private HandlingEvent.Type type;
19
+  private Location location;
20
+  public static final HandlingActivity NONE = createNoneInstance();
21
+
22
+  HandlingActivity() {
23
+  }
24
+
25
+  private static HandlingActivity createNoneInstance() {
26
+    HandlingActivity none = new HandlingActivity();
27
+    none.location = Location.UNKNOWN;
28
+    return none;
29
+  }
30
+
31
+  public HandlingActivity(final HandlingEvent.Type type, final Location location) {
32
+    Validate.notNull(type, "Handling event type is required");
33
+    Validate.notNull(location, "Location is required");
34
+
35
+    this.type = type;
36
+    this.location = location;
37
+  }
38
+
39
+
40
+  @Override
41
+  public boolean sameValueAs(final HandlingActivity other) {
42
+    return other != null && new EqualsBuilder().
43
+      append(this.type, other.type).
44
+      append(this.location, other.location).
45
+      isEquals();
46
+  }
47
+
48
+  @Override
49
+  public int hashCode() {
50
+    return new HashCodeBuilder().
51
+      append(this.type).
52
+      append(this.location).
53
+      toHashCode();
54
+  }
55
+
56
+  @Override
57
+  public boolean equals(final Object obj) {
58
+    if (obj == this) return true;
59
+    if (obj == null) return false;
60
+    if (obj.getClass() != this.getClass()) return false;
61
+
62
+    HandlingActivity other = (HandlingActivity) obj;
63
+
64
+    return sameValueAs(other);
65
+  }
66
+
67
+  @Override
68
+  public String toString() {
69
+    if (this == NONE) return "No activity";
70
+
71
+    return type + " in " + location;
72
+  }
73
+
74
+}

+ 48
- 31
dddsample/src/test/java/se/citerus/dddsample/scenario/CargoLifecycleScenarioTest.java Просмотреть файл

1
 package se.citerus.dddsample.scenario;
1
 package se.citerus.dddsample.scenario;
2
 
2
 
3
 import junit.framework.TestCase;
3
 import junit.framework.TestCase;
4
-import se.citerus.dddsample.application.*;
4
+import se.citerus.dddsample.application.ApplicationEvents;
5
+import se.citerus.dddsample.application.BookingService;
6
+import se.citerus.dddsample.application.CargoInspectionService;
7
+import se.citerus.dddsample.application.HandlingEventService;
5
 import se.citerus.dddsample.application.impl.BookingServiceImpl;
8
 import se.citerus.dddsample.application.impl.BookingServiceImpl;
6
 import se.citerus.dddsample.application.impl.CargoInspectionServiceImpl;
9
 import se.citerus.dddsample.application.impl.CargoInspectionServiceImpl;
7
 import se.citerus.dddsample.application.impl.HandlingEventServiceImpl;
10
 import se.citerus.dddsample.application.impl.HandlingEventServiceImpl;
102
     assertEquals(NOT_RECEIVED, cargo.delivery().transportStatus());
105
     assertEquals(NOT_RECEIVED, cargo.delivery().transportStatus());
103
     assertEquals(RoutingStatus.NOT_ROUTED, cargo.routingStatus());
106
     assertEquals(RoutingStatus.NOT_ROUTED, cargo.routingStatus());
104
     assertFalse(cargo.isMisdirected());
107
     assertFalse(cargo.isMisdirected());
105
-
108
+    assertNull(cargo.estimatedTimeOfArrival());
109
+    assertEquals(HandlingActivity.NONE, cargo.nextExpectedActivity());
106
 
110
 
107
     /* Use case 2: routing
111
     /* Use case 2: routing
108
 
112
 
117
     cargo.assignToRoute(itinerary);
121
     cargo.assignToRoute(itinerary);
118
 
122
 
119
     assertEquals(RoutingStatus.ROUTED, cargo.routingStatus());
123
     assertEquals(RoutingStatus.ROUTED, cargo.routingStatus());
124
+    assertNotNull(cargo.estimatedTimeOfArrival());
125
+    assertEquals(new HandlingActivity(RECEIVE, HONGKONG), cargo.nextExpectedActivity());
120
 
126
 
121
     /*
127
     /*
122
       Use case 3: handling
128
       Use case 3: handling
132
 
138
 
133
       Handling begins: cargo is received in Hongkong.
139
       Handling begins: cargo is received in Hongkong.
134
       */
140
       */
135
-    HandlingEventRegistrationAttempt attempt1 = new HandlingEventRegistrationAttempt(
136
-      new Date(), new Date(100), trackingId, null, RECEIVE, HONGKONG.unLocode()
141
+    handlingEventService.registerHandlingEvent(
142
+      new Date(100), trackingId, null, HONGKONG.unLocode(), RECEIVE
137
     );
143
     );
138
-    handlingEventService.registerHandlingEvent(attempt1.getCompletionTime(), attempt1.getTrackingId(), attempt1.getVoyageNumber(), attempt1.getUnLocode(), attempt1.getType());
139
 
144
 
140
     // Next event: Load onto voyage CM003 in Hongkong
145
     // Next event: Load onto voyage CM003 in Hongkong
141
-    final HandlingEventRegistrationAttempt attempt = new HandlingEventRegistrationAttempt(
142
-      new Date(), new Date(200), trackingId, CM003.voyageNumber(), LOAD, HONGKONG.unLocode()
146
+    handlingEventService.registerHandlingEvent(
147
+      new Date(200), trackingId, CM003.voyageNumber(), HONGKONG.unLocode(), LOAD
143
     );
148
     );
144
-    handlingEventService.registerHandlingEvent(attempt.getCompletionTime(), attempt.getTrackingId(), attempt.getVoyageNumber(), attempt.getUnLocode(), attempt.getType());
145
 
149
 
146
     // Check current state - should be ok
150
     // Check current state - should be ok
147
     assertEquals(CM003, cargo.delivery().currentVoyage());
151
     assertEquals(CM003, cargo.delivery().currentVoyage());
148
     assertEquals(HONGKONG, cargo.delivery().lastKnownLocation());
152
     assertEquals(HONGKONG, cargo.delivery().lastKnownLocation());
149
     assertEquals(ONBOARD_CARRIER, cargo.delivery().transportStatus());
153
     assertEquals(ONBOARD_CARRIER, cargo.delivery().transportStatus());
150
     assertFalse(cargo.isMisdirected());
154
     assertFalse(cargo.isMisdirected());
155
+    assertEquals(new HandlingActivity(UNLOAD, NEWYORK), cargo.nextExpectedActivity());
156
+
151
 
157
 
152
     /*
158
     /*
153
       Here's an attempt to register a handling event that's not valid
159
       Here's an attempt to register a handling event that's not valid
156
 
162
 
157
       This attempt will be rejected and will not affet the cargo delivery in any way.
163
       This attempt will be rejected and will not affet the cargo delivery in any way.
158
      */
164
      */
159
-    VoyageNumber noSuchVoyageNumber = new VoyageNumber("XX000");
160
-    UnLocode noSuchUnLocode = new UnLocode("ZZZZZ");
161
-    HandlingEventRegistrationAttempt failingAttempt = new HandlingEventRegistrationAttempt(
162
-      new Date(), new Date(300), trackingId, noSuchVoyageNumber, LOAD, noSuchUnLocode
165
+    final VoyageNumber noSuchVoyageNumber = new VoyageNumber("XX000");
166
+    final UnLocode noSuchUnLocode = new UnLocode("ZZZZZ");
167
+    handlingEventService.registerHandlingEvent(
168
+      new Date(300), trackingId, noSuchVoyageNumber, noSuchUnLocode, LOAD
163
     );
169
     );
164
-    handlingEventService.registerHandlingEvent(failingAttempt.getCompletionTime(), failingAttempt.getTrackingId(), failingAttempt.getVoyageNumber(), failingAttempt.getUnLocode(), failingAttempt.getType());
165
 
170
 
166
 
171
 
167
     // Cargo is now (incorrectly) unloaded in Tokyo
172
     // Cargo is now (incorrectly) unloaded in Tokyo
168
-    final HandlingEventRegistrationAttempt attempt7 = new HandlingEventRegistrationAttempt(
169
-      new Date(), new Date(400), trackingId, CM003.voyageNumber(), UNLOAD, TOKYO.unLocode()
173
+    handlingEventService.registerHandlingEvent(
174
+      new Date(400), trackingId, CM003.voyageNumber(), TOKYO.unLocode(), UNLOAD
170
     );
175
     );
171
-    handlingEventService.registerHandlingEvent(attempt7.getCompletionTime(), attempt7.getTrackingId(), attempt7.getVoyageNumber(), attempt7.getUnLocode(), attempt7.getType());
172
 
176
 
173
     // Check current state - cargo is misdirected!
177
     // Check current state - cargo is misdirected!
174
     assertEquals(NONE, cargo.delivery().currentVoyage());
178
     assertEquals(NONE, cargo.delivery().currentVoyage());
175
     assertEquals(TOKYO, cargo.delivery().lastKnownLocation());
179
     assertEquals(TOKYO, cargo.delivery().lastKnownLocation());
176
     assertEquals(IN_PORT, cargo.delivery().transportStatus());
180
     assertEquals(IN_PORT, cargo.delivery().transportStatus());
177
     assertTrue(cargo.isMisdirected());
181
     assertTrue(cargo.isMisdirected());
182
+    assertEquals(HandlingActivity.NONE, cargo.nextExpectedActivity());
178
 
183
 
179
 
184
 
180
     // -- Cargo needs to be rerouted --
185
     // -- Cargo needs to be rerouted --
186
 
191
 
187
     // The old itinerary does not satisfy the new specification
192
     // The old itinerary does not satisfy the new specification
188
     assertEquals(RoutingStatus.MISROUTED, cargo.routingStatus());
193
     assertEquals(RoutingStatus.MISROUTED, cargo.routingStatus());
194
+    assertEquals(HandlingActivity.NONE, cargo.nextExpectedActivity());
189
 
195
 
190
     // Repeat procedure of selecting one out of a number of possible routes satisfying the route spec
196
     // Repeat procedure of selecting one out of a number of possible routes satisfying the route spec
191
     List<Itinerary> newItineraries = bookingService.requestPossibleRoutesForCargo(cargo.trackingId());
197
     List<Itinerary> newItineraries = bookingService.requestPossibleRoutesForCargo(cargo.trackingId());
195
     // New itinerary should satisfy new route
201
     // New itinerary should satisfy new route
196
     assertEquals(RoutingStatus.ROUTED, cargo.routingStatus());
202
     assertEquals(RoutingStatus.ROUTED, cargo.routingStatus());
197
 
203
 
204
+    // TODO we can't handle the face that after a reroute, the cargo isn't misdirected anymore
205
+    //assertFalse(cargo.isMisdirected());
206
+    //assertEquals(new HandlingActivity(LOAD, TOKYO), cargo.nextExpectedActivity());
207
+
198
 
208
 
199
     // -- Cargo has been rerouted, shipping continues --
209
     // -- Cargo has been rerouted, shipping continues --
200
 
210
 
201
 
211
 
202
     // Load in Tokyo
212
     // Load in Tokyo
203
-    HandlingEventRegistrationAttempt attempt2 = new HandlingEventRegistrationAttempt(
204
-      new Date(), new Date(500), trackingId, CM003.voyageNumber(), LOAD, TOKYO.unLocode()
213
+    handlingEventService.registerHandlingEvent(
214
+      new Date(500), trackingId, CM003.voyageNumber(), TOKYO.unLocode(), LOAD
205
     );
215
     );
206
-    handlingEventService.registerHandlingEvent(attempt2.getCompletionTime(), attempt2.getTrackingId(), attempt2.getVoyageNumber(), attempt2.getUnLocode(), attempt2.getType());
207
 
216
 
208
     // Check current state - should be ok
217
     // Check current state - should be ok
209
     assertEquals(CM003, cargo.delivery().currentVoyage());
218
     assertEquals(CM003, cargo.delivery().currentVoyage());
210
     assertEquals(TOKYO, cargo.delivery().lastKnownLocation());
219
     assertEquals(TOKYO, cargo.delivery().lastKnownLocation());
211
     assertEquals(ONBOARD_CARRIER, cargo.delivery().transportStatus());
220
     assertEquals(ONBOARD_CARRIER, cargo.delivery().transportStatus());
212
     assertFalse(cargo.isMisdirected());
221
     assertFalse(cargo.isMisdirected());
222
+    assertEquals(new HandlingActivity(UNLOAD, HAMBURG), cargo.nextExpectedActivity());
213
 
223
 
214
     // Unload in Hamburg
224
     // Unload in Hamburg
215
-    HandlingEventRegistrationAttempt attempt3 = new HandlingEventRegistrationAttempt(
216
-      new Date(), new Date(600), trackingId, CM003.voyageNumber(), UNLOAD, HAMBURG.unLocode()
225
+    handlingEventService.registerHandlingEvent(
226
+      new Date(600), trackingId, CM003.voyageNumber(), HAMBURG.unLocode(), UNLOAD
217
     );
227
     );
218
-    handlingEventService.registerHandlingEvent(attempt3.getCompletionTime(), attempt3.getTrackingId(), attempt3.getVoyageNumber(), attempt3.getUnLocode(), attempt3.getType());
219
 
228
 
220
     // Check current state - should be ok
229
     // Check current state - should be ok
221
     assertEquals(NONE, cargo.delivery().currentVoyage());
230
     assertEquals(NONE, cargo.delivery().currentVoyage());
222
     assertEquals(HAMBURG, cargo.delivery().lastKnownLocation());
231
     assertEquals(HAMBURG, cargo.delivery().lastKnownLocation());
223
     assertEquals(IN_PORT, cargo.delivery().transportStatus());
232
     assertEquals(IN_PORT, cargo.delivery().transportStatus());
224
     assertFalse(cargo.isMisdirected());
233
     assertFalse(cargo.isMisdirected());
234
+    assertEquals(new HandlingActivity(LOAD, HAMBURG), cargo.nextExpectedActivity());
235
+
225
 
236
 
226
     // Load in Hamburg
237
     // Load in Hamburg
227
-    HandlingEventRegistrationAttempt attempt4 = new HandlingEventRegistrationAttempt(
228
-      new Date(), new Date(700), trackingId, CM005.voyageNumber(), LOAD, HAMBURG.unLocode()
238
+    handlingEventService.registerHandlingEvent(
239
+      new Date(700), trackingId, CM005.voyageNumber(), HAMBURG.unLocode(), LOAD
229
     );
240
     );
230
-    handlingEventService.registerHandlingEvent(attempt4.getCompletionTime(), attempt4.getTrackingId(), attempt4.getVoyageNumber(), attempt4.getUnLocode(), attempt4.getType());
231
 
241
 
232
     // Check current state - should be ok
242
     // Check current state - should be ok
233
     assertEquals(CM005, cargo.delivery().currentVoyage());
243
     assertEquals(CM005, cargo.delivery().currentVoyage());
234
     assertEquals(HAMBURG, cargo.delivery().lastKnownLocation());
244
     assertEquals(HAMBURG, cargo.delivery().lastKnownLocation());
235
     assertEquals(ONBOARD_CARRIER, cargo.delivery().transportStatus());
245
     assertEquals(ONBOARD_CARRIER, cargo.delivery().transportStatus());
236
     assertFalse(cargo.isMisdirected());
246
     assertFalse(cargo.isMisdirected());
247
+    assertEquals(new HandlingActivity(UNLOAD, STOCKHOLM), cargo.nextExpectedActivity());
248
+
237
 
249
 
238
     // Unload in Stockholm
250
     // Unload in Stockholm
239
-    HandlingEventRegistrationAttempt attempt5 = new HandlingEventRegistrationAttempt(
240
-      new Date(), new Date(800), trackingId, CM005.voyageNumber(), UNLOAD, STOCKHOLM.unLocode()
251
+    handlingEventService.registerHandlingEvent(
252
+      new Date(800), trackingId, CM005.voyageNumber(), STOCKHOLM.unLocode(), UNLOAD
241
     );
253
     );
242
-    handlingEventService.registerHandlingEvent(attempt5.getCompletionTime(), attempt5.getTrackingId(), attempt5.getVoyageNumber(), attempt5.getUnLocode(), attempt5.getType());
243
 
254
 
244
     // Check current state - should be ok
255
     // Check current state - should be ok
245
     assertEquals(NONE, cargo.delivery().currentVoyage());
256
     assertEquals(NONE, cargo.delivery().currentVoyage());
246
     assertEquals(STOCKHOLM, cargo.delivery().lastKnownLocation());
257
     assertEquals(STOCKHOLM, cargo.delivery().lastKnownLocation());
247
     assertEquals(IN_PORT, cargo.delivery().transportStatus());
258
     assertEquals(IN_PORT, cargo.delivery().transportStatus());
248
     assertFalse(cargo.isMisdirected());
259
     assertFalse(cargo.isMisdirected());
260
+    assertEquals(new HandlingActivity(CLAIM, STOCKHOLM), cargo.nextExpectedActivity());
249
 
261
 
250
     // Finally, cargo is claimed in Stockholm. This ends the cargo lifecycle from our perspective.
262
     // Finally, cargo is claimed in Stockholm. This ends the cargo lifecycle from our perspective.
251
-    HandlingEventRegistrationAttempt attempt6 = new HandlingEventRegistrationAttempt(
252
-      new Date(), new Date(900), trackingId, null, CLAIM, STOCKHOLM.unLocode()
263
+    handlingEventService.registerHandlingEvent(
264
+      new Date(900), trackingId, null, STOCKHOLM.unLocode(), CLAIM
253
     );
265
     );
254
-    handlingEventService.registerHandlingEvent(attempt6.getCompletionTime(), attempt6.getTrackingId(), attempt6.getVoyageNumber(), attempt6.getUnLocode(), attempt6.getType());
255
 
266
 
256
     // Check current state - should be ok
267
     // Check current state - should be ok
257
     assertEquals(NONE, cargo.delivery().currentVoyage());
268
     assertEquals(NONE, cargo.delivery().currentVoyage());
258
     assertEquals(STOCKHOLM, cargo.delivery().lastKnownLocation());
269
     assertEquals(STOCKHOLM, cargo.delivery().lastKnownLocation());
259
     assertEquals(CLAIMED, cargo.delivery().transportStatus());
270
     assertEquals(CLAIMED, cargo.delivery().transportStatus());
260
     assertFalse(cargo.isMisdirected());
271
     assertFalse(cargo.isMisdirected());
272
+    assertEquals(HandlingActivity.NONE, cargo.nextExpectedActivity());
261
   }
273
   }
262
 
274
 
275
+
276
+
277
+
278
+
279
+
263
   /*
280
   /*
264
   * Utility stubs below.
281
   * Utility stubs below.
265
   */
282
   */