View Javadoc

1   package se.citerus.dddsample.application.util;
2   
3   import org.hibernate.SessionFactory;
4   import org.hibernate.classic.Session;
5   import org.springframework.beans.factory.BeanFactoryUtils;
6   import org.springframework.jdbc.core.JdbcTemplate;
7   import org.springframework.transaction.PlatformTransactionManager;
8   import org.springframework.transaction.TransactionStatus;
9   import org.springframework.transaction.support.TransactionCallbackWithoutResult;
10  import org.springframework.transaction.support.TransactionTemplate;
11  import org.springframework.web.context.WebApplicationContext;
12  import org.springframework.web.context.support.WebApplicationContextUtils;
13  import static se.citerus.dddsample.application.util.DateTestUtil.toDate;
14  import se.citerus.dddsample.domain.model.cargo.*;
15  import se.citerus.dddsample.domain.model.handling.*;
16  import se.citerus.dddsample.domain.model.location.Location;
17  import se.citerus.dddsample.domain.model.location.LocationRepository;
18  import se.citerus.dddsample.domain.model.location.SampleLocations;
19  import static se.citerus.dddsample.domain.model.location.SampleLocations.*;
20  import static se.citerus.dddsample.domain.model.voyage.SampleVoyages.*;
21  import se.citerus.dddsample.domain.model.voyage.VoyageRepository;
22  
23  import javax.servlet.ServletContextEvent;
24  import javax.servlet.ServletContextListener;
25  import javax.sql.DataSource;
26  import java.sql.Timestamp;
27  import java.text.ParseException;
28  import java.text.SimpleDateFormat;
29  import static java.util.Arrays.asList;
30  import java.util.Date;
31  
32  /**
33   * Provides sample data.
34   */
35  public class SampleDataGenerator implements ServletContextListener {
36  
37    private static final Timestamp base; 
38    static {
39      try {
40        Date date = new SimpleDateFormat("yyyy-MM-dd").parse("2008-01-01");
41        base = new Timestamp(date.getTime() - 1000L * 60 * 60 * 24 * 100);
42      } catch (ParseException e) {
43        throw new RuntimeException(e);
44      }
45    }
46  
47    private static void loadHandlingEventData(JdbcTemplate jdbcTemplate) {
48      String handlingEventSql =
49        "insert into HandlingEvent (completionTime, registrationTime, type, location_id, voyage_id, cargo_id) " +
50        "values (?, ?, ?, ?, ?, ?)";
51  
52      Object[][] handlingEventArgs = {
53          //XYZ (SESTO-FIHEL-DEHAM-CNHKG-JPTOK-AUMEL)
54          {ts(0),     ts((0)),    "RECEIVE",  1,  null,  1},
55          {ts((4)),   ts((5)),    "LOAD",     1,  1,     1},
56          {ts((14)),  ts((14)),   "UNLOAD",   5,  1,     1},
57          {ts((15)),  ts((15)),   "LOAD",     5,  1,     1},
58          {ts((30)),  ts((30)),   "UNLOAD",   6,  1,     1},
59          {ts((33)),  ts((33)),   "LOAD",     6,  1,     1},
60          {ts((34)),  ts((34)),   "UNLOAD",   3,  1,     1},
61          {ts((60)),  ts((60)),   "LOAD",     3,  1,     1},
62          {ts((70)),  ts((71)),   "UNLOAD",   4,  1,     1},
63          {ts((75)),  ts((75)),   "LOAD",     4,  1,     1},
64          {ts((88)),  ts((88)),   "UNLOAD",   2,  1,     1},
65          {ts((100)), ts((102)),  "CLAIM",    2,  null,  1},
66  
67          //ZYX (AUMEL - USCHI - DEHAM -)
68          {ts((200)),   ts((201)),  "RECEIVE",  2,  null,  3},
69          {ts((202)),   ts((202)),  "LOAD",     2,  2,     3},
70          {ts((208)),   ts((208)),  "UNLOAD",   7,  2,     3},
71          {ts((212)),   ts((212)),  "LOAD",     7,  2,     3},
72          {ts((230)),   ts((230)),  "UNLOAD",   6,  2,     3},
73          {ts((235)),   ts((235)),  "LOAD",     6,  2,     3},
74  
75          //ABC
76          {ts((20)),  ts((21)),   "CLAIM",    2,  null,  2},
77  
78          //CBA
79          {ts((0)),   ts((1)),    "RECEIVE",  2,  null,  4},
80          {ts((10)),  ts((11)),   "LOAD",     2,  2,     4},
81          {ts((20)),  ts((21)),   "UNLOAD",   7,  2,     4},
82  
83          //FGH
84          {ts(100),   ts(160),    "RECEIVE",  3,  null,   5},
85          {ts(150),   ts(110),    "LOAD",     3,  3,     5},
86  
87          // JKL
88          {ts(200),   ts(220),    "RECEIVE",  6,  null,   6},
89          {ts(300),   ts(330),    "LOAD",     6,  3,     6},
90          {ts(400),   ts(440),    "UNLOAD",   5,  3,     6}  // Unexpected event
91      };
92      executeUpdate(jdbcTemplate, handlingEventSql, handlingEventArgs);
93    }
94  
95    private static void loadCarrierMovementData(JdbcTemplate jdbcTemplate) {
96      String voyageSql =
97        "insert into Voyage (id, voyage_number) values (?, ?)";
98      Object[][] voyageArgs = {
99        {1,"0101"},
100       {2,"0202"},
101       {3,"0303"}
102     };
103     executeUpdate(jdbcTemplate, voyageSql, voyageArgs);
104 
105     String carrierMovementSql =
106       "insert into CarrierMovement (id, voyage_id, departure_location_id, arrival_location_id, departure_time, arrival_time, cm_index) " +
107       "values (?,?,?,?,?,?,?)";
108 
109     Object[][] carrierMovementArgs = {
110       // SESTO - FIHEL - DEHAM - CNHKG - JPTOK - AUMEL (voyage 0101)
111       {1,1,1,5,ts(1),ts(2),0},
112       {2,1,5,6,ts(1),ts(2),1},
113       {3,1,6,3,ts(1),ts(2),2},
114       {4,1,3,4,ts(1),ts(2),3},
115       {5,1,4,2,ts(1),ts(2),4},
116 
117       // AUMEL - USCHI - DEHAM - SESTO - FIHEL (voyage 0202)
118       {7,2,2,7,ts(1),ts(2),0},
119       {8,2,7,6,ts(1),ts(2),1},
120       {9,2,6,1,ts(1),ts(2),2},
121       {6,2,1,5,ts(1),ts(2),3},
122 
123       // CNHKG - AUMEL - FIHEL - DEHAM - SESTO - USCHI - JPTKO (voyage 0303)
124       {10,3,3,2,ts(1),ts(2),0},
125       {11,3,2,5,ts(1),ts(2),1},
126       {12,3,6,1,ts(1),ts(2),2},
127       {13,3,1,7,ts(1),ts(2),3},
128       {14,3,7,4,ts(1),ts(2),4}
129     };
130     executeUpdate(jdbcTemplate, carrierMovementSql, carrierMovementArgs);
131   }
132 
133   private static void loadCargoData(JdbcTemplate jdbcTemplate) {
134     String cargoSql =
135       "insert into Cargo (id, tracking_id, origin_id, spec_origin_id, spec_destination_id, spec_arrival_deadline, transport_status, current_voyage_id, last_known_location_id, is_misdirected, routing_status, calculated_at, unloaded_at_dest) " +
136       "values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
137 
138     Object[][] cargoArgs = {
139       {1, "XYZ", 1, 1, 2, ts(10), "IN_PORT", null, 1, false, "ROUTED", ts(100), false},
140       {2, "ABC", 1, 1, 5, ts(20), "IN_PORT", null, 1, false, "ROUTED", ts(100), false},
141       {3, "ZYX", 2, 2, 1, ts(30), "IN_PORT", null, 1, false, "NOT_ROUTED", ts(100), false},
142       {4, "CBA", 5, 5, 1, ts(40), "IN_PORT", null, 1, false, "MISROUTED", ts(100), false},
143       {5, "FGH", 1, 3, 5, ts(50), "IN_PORT", null, 1, false, "ROUTED", ts(100), false},  // Cargo origin differs from spec origin
144       {6, "JKL", 6, 6, 4, ts(60), "IN_PORT", null, 1, true, "ROUTED", ts(100), false}
145     };
146     executeUpdate(jdbcTemplate, cargoSql, cargoArgs);
147   }
148 
149   private static void loadLocationData(JdbcTemplate jdbcTemplate) {
150     String locationSql =
151       "insert into Location (id, unlocode, name) " +
152       "values (?, ?, ?)";
153 
154     Object[][] locationArgs = {
155       {1, "SESTO", "Stockholm"},
156       {2, "AUMEL", "Melbourne"},
157       {3, "CNHKG", "Hongkong"},
158       {4, "JPTOK", "Tokyo"},
159       {5, "FIHEL", "Helsinki"},
160       {6, "DEHAM", "Hamburg"},
161       {7, "USCHI", "Chicago"}
162     };
163     executeUpdate(jdbcTemplate, locationSql, locationArgs);
164   }
165 
166   private static void loadItineraryData(JdbcTemplate jdbcTemplate) {
167     String legSql =
168       "insert into Leg (id, cargo_id, voyage_id, load_location_id, unload_location_id, load_time, unload_time, leg_index) " +
169       "values (?,?,?,?,?,?,?,?)";
170 
171     Object [][] legArgs = {
172       // Cargo 5: Hongkong - Melbourne - Stockholm - Helsinki
173       {1,5,1,3,2,ts(1),ts(2),0},
174       {2,5,1,2,1,ts(3),ts(4),1},
175       {3,5,1,1,5,ts(4),ts(5),2},
176       // Cargo 6: Hamburg - Stockholm - Chicago - Tokyo
177       {4,6,2,6,1,ts(1),ts(2),0},
178       {5,6,2,1,7,ts(3),ts(4),1},
179       {6,6,2,7,4,ts(5),ts(6),2}
180     };
181     executeUpdate(jdbcTemplate, legSql, legArgs);
182   }
183 
184   public void contextInitialized(ServletContextEvent event) {
185     WebApplicationContext context = WebApplicationContextUtils.getRequiredWebApplicationContext(event.getServletContext());
186     DataSource dataSource = (DataSource) BeanFactoryUtils.beanOfType(context, DataSource.class);
187     PlatformTransactionManager transactionManager = (PlatformTransactionManager) BeanFactoryUtils.beanOfType(context, PlatformTransactionManager.class);
188     TransactionTemplate tt = new TransactionTemplate(transactionManager);
189     //loadSampleData(new JdbcTemplate(dataSource), tt);
190 
191 
192     SessionFactory sf = (SessionFactory) BeanFactoryUtils.beanOfType(context, SessionFactory.class);
193     HandlingEventFactory handlingEventFactory = new HandlingEventFactory(
194       getBean(context, CargoRepository.class),
195       getBean(context, VoyageRepository.class),
196       getBean(context, LocationRepository.class));
197     loadHibernateData(tt, sf, handlingEventFactory, getBean(context, HandlingEventRepository.class));
198   }
199 
200   private <T> T getBean(WebApplicationContext context, Class<T> cls) {
201     return (T) BeanFactoryUtils.beanOfType(context, cls);
202   }
203 
204   public static void loadHibernateData(TransactionTemplate tt, final SessionFactory sf, final HandlingEventFactory handlingEventFactory, final HandlingEventRepository handlingEventRepository) {
205     System.out.println("*** Loading Hibernate data ***");
206     tt.execute(new TransactionCallbackWithoutResult() {
207       @Override
208       protected void doInTransactionWithoutResult(TransactionStatus status) {
209         Session session = sf.getCurrentSession();
210 
211         for (Location location : SampleLocations.getAll()) {
212           session.save(location);
213         }
214 
215         session.save(HONGKONG_TO_NEW_YORK);
216         session.save(NEW_YORK_TO_DALLAS);
217         session.save(DALLAS_TO_HELSINKI);
218         session.save(HELSINKI_TO_HONGKONG);
219         session.save(DALLAS_TO_HELSINKI_ALT);
220 
221         RouteSpecification routeSpecification = new RouteSpecification(HONGKONG, HELSINKI, toDate("2009-03-15"));
222         TrackingId trackingId = new TrackingId("ABC123");
223         Cargo abc123 = new Cargo(trackingId, routeSpecification);
224 
225         Itinerary itinerary = new Itinerary(asList(
226           new Leg(HONGKONG_TO_NEW_YORK, HONGKONG, NEWYORK, toDate("2009-03-02"), toDate("2009-03-05")),
227           new Leg(NEW_YORK_TO_DALLAS, NEWYORK, DALLAS, toDate("2009-03-06"), toDate("2009-03-08")),
228           new Leg(DALLAS_TO_HELSINKI, DALLAS, HELSINKI, toDate("2009-03-09"), toDate("2009-03-12"))
229         ));
230         abc123.assignToRoute(itinerary);
231 
232         session.save(abc123);
233         
234         try {
235           HandlingEvent event1 = handlingEventFactory.createHandlingEvent(
236             new Date(), toDate("2009-03-01"), trackingId, null, HONGKONG.unLocode(), HandlingEvent.Type.RECEIVE
237           );
238           session.save(event1);
239 
240           HandlingEvent event2 = handlingEventFactory.createHandlingEvent(
241             new Date(), toDate("2009-03-02"), trackingId, HONGKONG_TO_NEW_YORK.voyageNumber(), HONGKONG.unLocode(), HandlingEvent.Type.LOAD
242           );
243           session.save(event2);
244 
245           HandlingEvent event3 = handlingEventFactory.createHandlingEvent(
246             new Date(), toDate("2009-03-05"), trackingId, HONGKONG_TO_NEW_YORK.voyageNumber(), NEWYORK.unLocode(), HandlingEvent.Type.UNLOAD
247           );
248           session.save(event3);
249         } catch (CannotCreateHandlingEventException e) {
250           throw new RuntimeException(e);
251         }
252 
253         HandlingHistory handlingHistory = handlingEventRepository.lookupHandlingHistoryOfCargo(trackingId);
254         abc123.deriveDeliveryProgress(handlingHistory);
255 
256         session.update(abc123);
257 
258         // Cargo JKL567
259 
260         RouteSpecification routeSpecification1 = new RouteSpecification(HANGZOU, STOCKHOLM, toDate("2009-03-18"));
261         TrackingId trackingId1 = new TrackingId("JKL567");
262         Cargo jkl567 = new Cargo(trackingId1, routeSpecification1);
263 
264         Itinerary itinerary1 = new Itinerary(asList(
265           new Leg(HONGKONG_TO_NEW_YORK, HANGZOU, NEWYORK, toDate("2009-03-03"), toDate("2009-03-05")),
266           new Leg(NEW_YORK_TO_DALLAS, NEWYORK, DALLAS, toDate("2009-03-06"), toDate("2009-03-08")),
267           new Leg(DALLAS_TO_HELSINKI, DALLAS, STOCKHOLM, toDate("2009-03-09"), toDate("2009-03-11"))
268         ));
269         jkl567.assignToRoute(itinerary1);
270 
271         session.save(jkl567);
272 
273         try {
274           HandlingEvent event1 = handlingEventFactory.createHandlingEvent(
275             new Date(), toDate("2009-03-01"), trackingId1, null, HANGZOU.unLocode(), HandlingEvent.Type.RECEIVE
276           );
277           session.save(event1);
278 
279           HandlingEvent event2 = handlingEventFactory.createHandlingEvent(
280             new Date(), toDate("2009-03-03"), trackingId1, HONGKONG_TO_NEW_YORK.voyageNumber(), HANGZOU.unLocode(), HandlingEvent.Type.LOAD
281           );
282           session.save(event2);
283 
284           HandlingEvent event3 = handlingEventFactory.createHandlingEvent(
285             new Date(), toDate("2009-03-05"), trackingId1, HONGKONG_TO_NEW_YORK.voyageNumber(), NEWYORK.unLocode(), HandlingEvent.Type.UNLOAD
286           );
287           session.save(event3);
288 
289           HandlingEvent event4 = handlingEventFactory.createHandlingEvent(
290             new Date(), toDate("2009-03-06"), trackingId1, HONGKONG_TO_NEW_YORK.voyageNumber(), NEWYORK.unLocode(), HandlingEvent.Type.LOAD
291           );
292           session.save(event4);
293 
294         } catch (CannotCreateHandlingEventException e) {
295           throw new RuntimeException(e);
296         }
297 
298         HandlingHistory handlingHistory1 = handlingEventRepository.lookupHandlingHistoryOfCargo(trackingId1);
299         jkl567.deriveDeliveryProgress(handlingHistory1);
300 
301         session.update(jkl567);
302       }
303     });
304   }
305 
306   public void contextDestroyed(ServletContextEvent event) {}
307 
308   public static void loadSampleData(final JdbcTemplate jdbcTemplate, TransactionTemplate transactionTemplate) {
309     transactionTemplate.execute(new TransactionCallbackWithoutResult() {
310       protected void doInTransactionWithoutResult(TransactionStatus status) {
311         loadLocationData(jdbcTemplate);
312         loadCarrierMovementData(jdbcTemplate);
313         loadCargoData(jdbcTemplate);
314         loadItineraryData(jdbcTemplate);
315         loadHandlingEventData(jdbcTemplate);
316       }
317     });
318   }
319 
320   private static void executeUpdate(JdbcTemplate jdbcTemplate, String sql, Object[][] args) {
321     for (Object[] arg : args) {
322       jdbcTemplate.update(sql, arg);
323     }
324   }
325 
326   private static Timestamp ts(int hours) {
327     return new Timestamp(base.getTime() + 1000L * 60 * 60 * hours);
328   }
329 
330   public static Date offset(int hours) {
331     return new Date(ts(hours).getTime());
332   }
333 }