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

Refactored creation of Cargo into a CargoFactory.

peter_backlund 17 лет назад
Родитель
Сommit
1a71fe0549

+ 12
- 17
dddsample/src/main/java/se/citerus/dddsample/application/impl/BookingServiceImpl.java Просмотреть файл

@@ -1,5 +1,6 @@
1 1
 package se.citerus.dddsample.application.impl;
2 2
 
3
+import org.apache.commons.lang.Validate;
3 4
 import org.apache.commons.logging.Log;
4 5
 import org.apache.commons.logging.LogFactory;
5 6
 import org.springframework.transaction.annotation.Transactional;
@@ -16,17 +17,20 @@ import java.util.List;
16 17
 
17 18
 public final class BookingServiceImpl implements BookingService {
18 19
 
20
+  private final RoutingService routingService;
21
+  private final CargoFactory cargoFactory;
19 22
   private final CargoRepository cargoRepository;
20 23
   private final LocationRepository locationRepository;
21
-  private final RoutingService routingService;
22 24
   private final Log logger = LogFactory.getLog(getClass());
23 25
 
24
-  public BookingServiceImpl(final CargoRepository cargoRepository,
25
-                            final LocationRepository locationRepository,
26
-                            final RoutingService routingService) {
26
+  public BookingServiceImpl(final RoutingService routingService,
27
+                            final CargoFactory cargoFactory,
28
+                            final CargoRepository cargoRepository,
29
+                            final LocationRepository locationRepository) {
30
+    this.routingService = routingService;
31
+    this.cargoFactory = cargoFactory;
27 32
     this.cargoRepository = cargoRepository;
28 33
     this.locationRepository = locationRepository;
29
-    this.routingService = routingService;
30 34
   }
31 35
 
32 36
   @Override
@@ -34,14 +38,7 @@ public final class BookingServiceImpl implements BookingService {
34 38
   public TrackingId bookNewCargo(final UnLocode originUnLocode,
35 39
                                  final UnLocode destinationUnLocode,
36 40
                                  final Date arrivalDeadline) {
37
-    // TODO modeling this as a cargo factory might be suitable
38
-    final TrackingId trackingId = cargoRepository.nextTrackingId();
39
-    final Location origin = locationRepository.find(originUnLocode);
40
-    final Location destination = locationRepository.find(destinationUnLocode);
41
-    final RouteSpecification routeSpecification = new RouteSpecification(origin, destination, arrivalDeadline);
42
-
43
-    final Cargo cargo = new Cargo(trackingId, routeSpecification);
44
-
41
+    final Cargo cargo = cargoFactory.newCargo(originUnLocode, destinationUnLocode, arrivalDeadline);
45 42
     cargoRepository.store(cargo);
46 43
     logger.info("Booked new cargo with tracking id " + cargo.trackingId().idString());
47 44
 
@@ -64,10 +61,7 @@ public final class BookingServiceImpl implements BookingService {
64 61
   @Transactional
65 62
   public void assignCargoToRoute(final Itinerary itinerary, final TrackingId trackingId) {
66 63
     final Cargo cargo = cargoRepository.find(trackingId);
67
-    if (cargo == null) {
68
-      throw new IllegalArgumentException("Can't assign itinerary to non-existing cargo " + trackingId);
69
-    }
70
-
64
+    Validate.notNull(cargo, "Can't assign itinerary to non-existing cargo " + trackingId);
71 65
     cargo.assignToRoute(itinerary);
72 66
     cargoRepository.store(cargo);
73 67
 
@@ -78,6 +72,7 @@ public final class BookingServiceImpl implements BookingService {
78 72
   @Transactional
79 73
   public void changeDestination(final TrackingId trackingId, final UnLocode unLocode) {
80 74
     final Cargo cargo = cargoRepository.find(trackingId);
75
+    Validate.notNull(cargo, "Can't change destination of non-existing cargo " + trackingId);
81 76
     final Location newDestination = locationRepository.find(unLocode);
82 77
 
83 78
     final RouteSpecification routeSpecification = cargo.routeSpecification().withDestination(newDestination);

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

@@ -0,0 +1,34 @@
1
+/**
2
+ * Purpose
3
+ * @author peter
4
+ * @created 2009-jun-14
5
+ * $Id$
6
+ */
7
+package se.citerus.dddsample.domain.model.cargo;
8
+
9
+import se.citerus.dddsample.domain.model.location.Location;
10
+import se.citerus.dddsample.domain.model.location.LocationRepository;
11
+import se.citerus.dddsample.domain.model.location.UnLocode;
12
+
13
+import java.util.Date;
14
+
15
+public class CargoFactory {
16
+
17
+  private final CargoRepository cargoRepository;
18
+  private final LocationRepository locationRepository;
19
+
20
+  public CargoFactory(CargoRepository cargoRepository, LocationRepository locationRepository) {
21
+    this.cargoRepository = cargoRepository;
22
+    this.locationRepository = locationRepository;
23
+  }
24
+
25
+  public Cargo newCargo(UnLocode originUnLocode, UnLocode destinationUnLocode, Date arrivalDeadline) {
26
+    final TrackingId trackingId = cargoRepository.nextTrackingId();
27
+    final Location origin = locationRepository.find(originUnLocode);
28
+    final Location destination = locationRepository.find(destinationUnLocode);
29
+    final RouteSpecification routeSpecification = new RouteSpecification(origin, destination, arrivalDeadline);
30
+
31
+    return new Cargo(trackingId, routeSpecification);
32
+  }
33
+
34
+}

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

@@ -57,6 +57,30 @@ public class RouteSpecification extends AbstractSpecification<Itinerary> impleme
57 57
     return new Date(arrivalDeadline.getTime());
58 58
   }
59 59
 
60
+  /**
61
+   * @param newDestination destination of new route specification
62
+   * @return A copy of this route specification but with new destination
63
+   */
64
+  public RouteSpecification withDestination(Location newDestination) {
65
+	  return new RouteSpecification(origin, newDestination, arrivalDeadline);
66
+  }
67
+
68
+  /**
69
+   * @param newOrigin origin of new route specification
70
+   * @return A copy of this route specification but with the new origin
71
+   */
72
+  public RouteSpecification withOrigin(Location newOrigin) {
73
+    return new RouteSpecification(newOrigin, destination, arrivalDeadline);
74
+  }
75
+
76
+  /**
77
+   * @param newArrivalDeadline arrival deadline of new route specification
78
+   * @return A copy of this route specification but with the new arrival deadline
79
+   */
80
+  public RouteSpecification withArrivalDeadline(Date newArrivalDeadline) {
81
+    return new RouteSpecification(origin, destination, newArrivalDeadline);
82
+  }
83
+
60 84
   @Override
61 85
   public boolean isSatisfiedBy(final Itinerary itinerary) {
62 86
     return itinerary != null &&
@@ -96,11 +120,4 @@ public class RouteSpecification extends AbstractSpecification<Itinerary> impleme
96 120
   RouteSpecification() {
97 121
     // Needed by Hibernate
98 122
   }
99
-
100
-public RouteSpecification withDestination(Location newDestination) {
101
-
102
-	return new RouteSpecification(origin, newDestination, arrivalDeadline);
103
-	
104
-}
105
-  
106 123
 }

+ 29
- 29
dddsample/src/main/java/se/citerus/dddsample/interfaces/tracking/CargoTrackingViewAdapter.java Просмотреть файл

@@ -57,7 +57,7 @@ public final class CargoTrackingViewAdapter {
57 57
   }
58 58
 
59 59
   /**
60
-   * @return A translated string describing the cargo status. 
60
+   * @return A translated string describing the cargo status.
61 61
    */
62 62
   public String getStatusText() {
63 63
     final Delivery delivery = cargo.delivery();
@@ -66,10 +66,10 @@ public final class CargoTrackingViewAdapter {
66 66
     final Object[] args;
67 67
     switch (delivery.transportStatus()) {
68 68
       case IN_PORT:
69
-        args = new Object[] {getDisplayText(delivery.lastKnownLocation())};
69
+        args = new Object[]{getDisplayText(delivery.lastKnownLocation())};
70 70
         break;
71 71
       case ONBOARD_CARRIER:
72
-        args = new Object[] {delivery.currentVoyage().voyageNumber().idString()};
72
+        args = new Object[]{delivery.currentVoyage().voyageNumber().idString()};
73 73
         break;
74 74
       case CLAIMED:
75 75
       case NOT_RECEIVED:
@@ -78,7 +78,7 @@ public final class CargoTrackingViewAdapter {
78 78
         args = null;
79 79
         break;
80 80
     }
81
-    
81
+
82 82
     return messageSource.getMessage(code, args, "[Unknown status]", locale);
83 83
   }
84 84
 
@@ -107,33 +107,33 @@ public final class CargoTrackingViewAdapter {
107 107
     Date eta = cargo.delivery().estimatedTimeOfArrival();
108 108
 
109 109
     if (eta == null) return "?";
110
-	else {
111
-		Location destination = cargo.routeSpecification().destination();
112
-		SimpleDateFormat dateFormat = new SimpleDateFormat(FORMAT);
113
-		dateFormat.setTimeZone(destination.timeZone());
114
-		return dateFormat.format(eta);
115
-	}
110
+    else {
111
+      Location destination = cargo.routeSpecification().destination();
112
+      SimpleDateFormat dateFormat = new SimpleDateFormat(FORMAT);
113
+      dateFormat.setTimeZone(destination.timeZone());
114
+      return dateFormat.format(eta);
115
+    }
116 116
   }
117 117
 
118 118
   public String getNextExpectedActivity() {
119
-      HandlingActivity activity = cargo.delivery().nextExpectedActivity();
120
-      if (activity == null) {
121
-        return "";
122
-      }
119
+    HandlingActivity activity = cargo.delivery().nextExpectedActivity();
120
+    if (activity == null) {
121
+      return "";
122
+    }
123 123
 
124 124
     String text = "Next expected activity is to ";
125 125
     HandlingEvent.Type type = activity.type();
126 126
     if (type.sameValueAs(HandlingEvent.Type.LOAD)) {
127
-        return
128
-          text + type.name().toLowerCase() + " cargo onto voyage " + activity.voyage().voyageNumber() +
127
+      return
128
+        text + type.name().toLowerCase() + " cargo onto voyage " + activity.voyage().voyageNumber() +
129 129
           " in " + activity.location().name();
130
-      } else if (type.sameValueAs(HandlingEvent.Type.UNLOAD)) {
131
-        return
132
-          text + type.name().toLowerCase() + " cargo off of " + activity.voyage().voyageNumber() +
130
+    } else if (type.sameValueAs(HandlingEvent.Type.UNLOAD)) {
131
+      return
132
+        text + type.name().toLowerCase() + " cargo off of " + activity.voyage().voyageNumber() +
133 133
           " in " + activity.location().name();
134
-      } else {
135
-        return text + type.name().toLowerCase() + " cargo in " + activity.location().name();
136
-      }
134
+    } else {
135
+      return text + type.name().toLowerCase() + " cargo in " + activity.location().name();
136
+    }
137 137
   }
138 138
 
139 139
   /**
@@ -170,8 +170,8 @@ public final class CargoTrackingViewAdapter {
170 170
      * @return Time when the event was completed.
171 171
      */
172 172
     public String getTime() {
173
-		SimpleDateFormat dateFormat = new SimpleDateFormat(FORMAT);
174
-		dateFormat.setTimeZone(handlingEvent.location().timeZone());
173
+      SimpleDateFormat dateFormat = new SimpleDateFormat(FORMAT);
174
+      dateFormat.setTimeZone(handlingEvent.location().timeZone());
175 175
 
176 176
       return dateFormat.format(handlingEvent.completionTime());
177 177
     }
@@ -204,7 +204,7 @@ public final class CargoTrackingViewAdapter {
204 204
       switch (handlingEvent.type()) {
205 205
         case LOAD:
206 206
         case UNLOAD:
207
-          args = new Object[] {
207
+          args = new Object[]{
208 208
             handlingEvent.voyage().voyageNumber().idString(),
209 209
             handlingEvent.location().name(),
210 210
             handlingEvent.completionTime()
@@ -213,21 +213,21 @@ public final class CargoTrackingViewAdapter {
213 213
 
214 214
         case RECEIVE:
215 215
         case CLAIM:
216
-          args = new Object[] {
216
+          args = new Object[]{
217 217
             handlingEvent.location().name(),
218 218
             handlingEvent.completionTime()
219 219
           };
220 220
           break;
221 221
 
222 222
         default:
223
-          args = new Object[] {};
223
+          args = new Object[]{};
224 224
       }
225 225
 
226 226
       String key = "deliveryHistory.eventDescription." + handlingEvent.type().name();
227 227
 
228
-      return messageSource.getMessage(key,args,locale);
228
+      return messageSource.getMessage(key, args, locale);
229 229
     }
230 230
 
231 231
   }
232
-  
232
+
233 233
 }

+ 2
- 1
dddsample/src/main/resources/context-application.xml Просмотреть файл

@@ -5,9 +5,10 @@
5 5
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
6 6
 
7 7
   <bean id="bookingService" class="se.citerus.dddsample.application.impl.BookingServiceImpl">
8
+    <constructor-arg ref="cargoFactory"/>
9
+    <constructor-arg ref="routingService"/>
8 10
     <constructor-arg ref="cargoRepository"/>
9 11
     <constructor-arg ref="locationRepository"/>
10
-    <constructor-arg ref="routingService"/>
11 12
   </bean>
12 13
 
13 14
   <bean id="cargoInspectionService" class="se.citerus.dddsample.application.impl.CargoInspectionServiceImpl">

+ 5
- 0
dddsample/src/main/resources/context-domain.xml Просмотреть файл

@@ -10,4 +10,9 @@
10 10
     <constructor-arg ref="locationRepository"/>
11 11
   </bean>
12 12
 
13
+  <bean id="cargoFactory" class="se.citerus.dddsample.domain.model.cargo.CargoFactory">
14
+    <constructor-arg ref="cargoRepository"/>
15
+    <constructor-arg ref="locationRepository"/>
16
+  </bean>
17
+
13 18
 </beans>

+ 2
- 1
dddsample/src/test/java/se/citerus/dddsample/application/BookingServiceTest.java Просмотреть файл

@@ -4,6 +4,7 @@ import junit.framework.TestCase;
4 4
 import static org.easymock.EasyMock.*;
5 5
 import se.citerus.dddsample.application.impl.BookingServiceImpl;
6 6
 import se.citerus.dddsample.domain.model.cargo.Cargo;
7
+import se.citerus.dddsample.domain.model.cargo.CargoFactory;
7 8
 import se.citerus.dddsample.domain.model.cargo.CargoRepository;
8 9
 import se.citerus.dddsample.domain.model.cargo.TrackingId;
9 10
 import se.citerus.dddsample.domain.model.location.LocationRepository;
@@ -25,7 +26,7 @@ public class BookingServiceTest extends TestCase {
25 26
     cargoRepository = createMock(CargoRepository.class);
26 27
     locationRepository = createMock(LocationRepository.class);
27 28
     routingService = createMock(RoutingService.class);
28
-    bookingService = new BookingServiceImpl(cargoRepository, locationRepository, routingService);
29
+    bookingService = new BookingServiceImpl(routingService, new CargoFactory(cargoRepository, locationRepository), cargoRepository, locationRepository);
29 30
   }
30 31
 
31 32
   public void testRegisterNew() {