From 11d3795a9ace9695523ca16406613e681a0d647b Mon Sep 17 00:00:00 2001 From: Reza Rahman Date: Sun, 17 Jan 2021 09:21:01 -0500 Subject: [PATCH 01/22] Apply Google Java Code Style --- .../application/ApplicationEvents.java | 16 +- .../application/BookingService.java | 30 +- .../application/CargoInspectionService.java | 11 +- .../application/HandlingEventService.java | 17 +- .../internal/DefaultBookingService.java | 151 ++--- .../DefaultCargoInspectionService.java | 55 +- .../internal/DefaultHandlingEventService.java | 71 +-- .../application/util/DateUtil.java | 43 +- .../JsonMoxyConfigurationContextResolver.java | 18 +- .../application/util/LocationUtil.java | 14 +- .../application/util/RestConfiguration.java | 31 +- .../application/util/SampleDataGenerator.java | 571 ++++++++++-------- 12 files changed, 563 insertions(+), 465 deletions(-) diff --git a/src/main/java/org/eclipse/cargotracker/application/ApplicationEvents.java b/src/main/java/org/eclipse/cargotracker/application/ApplicationEvents.java index fb16705d9..4e86aa257 100644 --- a/src/main/java/org/eclipse/cargotracker/application/ApplicationEvents.java +++ b/src/main/java/org/eclipse/cargotracker/application/ApplicationEvents.java @@ -5,18 +5,18 @@ import org.eclipse.cargotracker.interfaces.handling.HandlingEventRegistrationAttempt; /** - * This interface provides a way to let other parts of the system know about - * events that have occurred. - *

- * It may be implemented synchronously or asynchronously, using for example JMS. + * This interface provides a way to let other parts of the system know about events that have + * occurred. + * + *

It may be implemented synchronously or asynchronously, using for example JMS. */ public interface ApplicationEvents { - void cargoWasHandled(HandlingEvent event); + void cargoWasHandled(HandlingEvent event); - void cargoWasMisdirected(Cargo cargo); + void cargoWasMisdirected(Cargo cargo); - void cargoHasArrived(Cargo cargo); + void cargoHasArrived(Cargo cargo); - void receivedHandlingEventRegistrationAttempt(HandlingEventRegistrationAttempt attempt); + void receivedHandlingEventRegistrationAttempt(HandlingEventRegistrationAttempt attempt); } diff --git a/src/main/java/org/eclipse/cargotracker/application/BookingService.java b/src/main/java/org/eclipse/cargotracker/application/BookingService.java index da3187246..72d12b160 100644 --- a/src/main/java/org/eclipse/cargotracker/application/BookingService.java +++ b/src/main/java/org/eclipse/cargotracker/application/BookingService.java @@ -7,28 +7,24 @@ import org.eclipse.cargotracker.domain.model.cargo.TrackingId; import org.eclipse.cargotracker.domain.model.location.UnLocode; -/** - * Cargo booking service. - */ +/** Cargo booking service. */ // TODO [Jakarta EE 8] Adopt the Date-Time API. public interface BookingService { - /** - * Registers a new cargo in the tracking system, not yet routed. - */ - TrackingId bookNewCargo(UnLocode origin, UnLocode destination, Date arrivalDeadline); + /** Registers a new cargo in the tracking system, not yet routed. */ + TrackingId bookNewCargo(UnLocode origin, UnLocode destination, Date arrivalDeadline); - /** - * Requests a list of itineraries describing possible routes for this cargo. - * - * @param trackingId Cargo tracking ID - * @return A list of possible itineraries for this cargo - */ - List requestPossibleRoutesForCargo(TrackingId trackingId); + /** + * Requests a list of itineraries describing possible routes for this cargo. + * + * @param trackingId Cargo tracking ID + * @return A list of possible itineraries for this cargo + */ + List requestPossibleRoutesForCargo(TrackingId trackingId); - void assignCargoToRoute(Itinerary itinerary, TrackingId trackingId); + void assignCargoToRoute(Itinerary itinerary, TrackingId trackingId); - void changeDestination(TrackingId trackingId, UnLocode unLocode); + void changeDestination(TrackingId trackingId, UnLocode unLocode); - void changeDeadline(TrackingId trackingId, Date deadline); + void changeDeadline(TrackingId trackingId, Date deadline); } diff --git a/src/main/java/org/eclipse/cargotracker/application/CargoInspectionService.java b/src/main/java/org/eclipse/cargotracker/application/CargoInspectionService.java index f2c8f04ac..a07b637e0 100644 --- a/src/main/java/org/eclipse/cargotracker/application/CargoInspectionService.java +++ b/src/main/java/org/eclipse/cargotracker/application/CargoInspectionService.java @@ -6,10 +6,9 @@ public interface CargoInspectionService { - /** - * Inspect cargo and send relevant notifications to interested parties, for - * example if a cargo has been misdirected, or unloaded at the final - * destination. - */ - public void inspectCargo(@NotNull(message = "Tracking ID is required") TrackingId trackingId); + /** + * Inspect cargo and send relevant notifications to interested parties, for example if a cargo has + * been misdirected, or unloaded at the final destination. + */ + public void inspectCargo(@NotNull(message = "Tracking ID is required") TrackingId trackingId); } diff --git a/src/main/java/org/eclipse/cargotracker/application/HandlingEventService.java b/src/main/java/org/eclipse/cargotracker/application/HandlingEventService.java index 6f06efb13..f30e30fbc 100644 --- a/src/main/java/org/eclipse/cargotracker/application/HandlingEventService.java +++ b/src/main/java/org/eclipse/cargotracker/application/HandlingEventService.java @@ -10,10 +10,15 @@ public interface HandlingEventService { - /** - * Registers a handling event in the system, and notifies interested parties - * that a cargo has been handled. - */ - void registerHandlingEvent(Date completionTime, TrackingId trackingId, VoyageNumber voyageNumber, UnLocode unLocode, - HandlingEvent.Type type) throws CannotCreateHandlingEventException; + /** + * Registers a handling event in the system, and notifies interested parties that a cargo has been + * handled. + */ + void registerHandlingEvent( + Date completionTime, + TrackingId trackingId, + VoyageNumber voyageNumber, + UnLocode unLocode, + HandlingEvent.Type type) + throws CannotCreateHandlingEventException; } diff --git a/src/main/java/org/eclipse/cargotracker/application/internal/DefaultBookingService.java b/src/main/java/org/eclipse/cargotracker/application/internal/DefaultBookingService.java index 1a9070a2f..72a6fe348 100644 --- a/src/main/java/org/eclipse/cargotracker/application/internal/DefaultBookingService.java +++ b/src/main/java/org/eclipse/cargotracker/application/internal/DefaultBookingService.java @@ -24,77 +24,82 @@ @Stateless public class DefaultBookingService implements BookingService { - @Inject - private CargoRepository cargoRepository; - @Inject - private LocationRepository locationRepository; - @Inject - private RoutingService routingService; - @Inject - private Logger logger; - - @Override - public TrackingId bookNewCargo(UnLocode originUnLocode, UnLocode destinationUnLocode, Date arrivalDeadline) { - TrackingId trackingId = cargoRepository.nextTrackingId(); - Location origin = locationRepository.find(originUnLocode); - Location destination = locationRepository.find(destinationUnLocode); - RouteSpecification routeSpecification = new RouteSpecification(origin, destination, arrivalDeadline); - - Cargo cargo = new Cargo(trackingId, routeSpecification); - - cargoRepository.store(cargo); - logger.log(Level.INFO, "Booked new cargo with tracking ID {0}", cargo.getTrackingId().getIdString()); - - return cargo.getTrackingId(); - } - - @Override - public List requestPossibleRoutesForCargo(TrackingId trackingId) { - Cargo cargo = cargoRepository.find(trackingId); - - if (cargo == null) { - return Collections.emptyList(); - } - - return routingService.fetchRoutesForSpecification(cargo.getRouteSpecification()); - } - - @Override - public void assignCargoToRoute(Itinerary itinerary, TrackingId trackingId) { - Cargo cargo = cargoRepository.find(trackingId); - - cargo.assignToRoute(itinerary); - cargoRepository.store(cargo); - - logger.log(Level.INFO, "Assigned cargo {0} to new route", trackingId); - } - - @Override - public void changeDestination(TrackingId trackingId, UnLocode unLocode) { - Cargo cargo = cargoRepository.find(trackingId); - Location newDestination = locationRepository.find(unLocode); - - RouteSpecification routeSpecification = new RouteSpecification(cargo.getOrigin(), newDestination, - cargo.getRouteSpecification().getArrivalDeadline()); - cargo.specifyNewRoute(routeSpecification); - - cargoRepository.store(cargo); - - logger.log(Level.INFO, "Changed destination for cargo {0} to {1}", - new Object[] { trackingId, routeSpecification.getDestination() }); - } - - @Override - public void changeDeadline(TrackingId trackingId, Date newDeadline) { - Cargo cargo = cargoRepository.find(trackingId); - - RouteSpecification routeSpecification = new RouteSpecification(cargo.getOrigin(), - cargo.getRouteSpecification().getDestination(), newDeadline); - cargo.specifyNewRoute(routeSpecification); - - cargoRepository.store(cargo); - - logger.log(Level.INFO, "Changed deadline for cargo {0} to {1}", new Object[] { trackingId, newDeadline }); - } - + @Inject private CargoRepository cargoRepository; + @Inject private LocationRepository locationRepository; + @Inject private RoutingService routingService; + @Inject private Logger logger; + + @Override + public TrackingId bookNewCargo( + UnLocode originUnLocode, UnLocode destinationUnLocode, Date arrivalDeadline) { + TrackingId trackingId = cargoRepository.nextTrackingId(); + Location origin = locationRepository.find(originUnLocode); + Location destination = locationRepository.find(destinationUnLocode); + RouteSpecification routeSpecification = + new RouteSpecification(origin, destination, arrivalDeadline); + + Cargo cargo = new Cargo(trackingId, routeSpecification); + + cargoRepository.store(cargo); + logger.log( + Level.INFO, "Booked new cargo with tracking ID {0}", cargo.getTrackingId().getIdString()); + + return cargo.getTrackingId(); + } + + @Override + public List requestPossibleRoutesForCargo(TrackingId trackingId) { + Cargo cargo = cargoRepository.find(trackingId); + + if (cargo == null) { + return Collections.emptyList(); + } + + return routingService.fetchRoutesForSpecification(cargo.getRouteSpecification()); + } + + @Override + public void assignCargoToRoute(Itinerary itinerary, TrackingId trackingId) { + Cargo cargo = cargoRepository.find(trackingId); + + cargo.assignToRoute(itinerary); + cargoRepository.store(cargo); + + logger.log(Level.INFO, "Assigned cargo {0} to new route", trackingId); + } + + @Override + public void changeDestination(TrackingId trackingId, UnLocode unLocode) { + Cargo cargo = cargoRepository.find(trackingId); + Location newDestination = locationRepository.find(unLocode); + + RouteSpecification routeSpecification = + new RouteSpecification( + cargo.getOrigin(), newDestination, cargo.getRouteSpecification().getArrivalDeadline()); + cargo.specifyNewRoute(routeSpecification); + + cargoRepository.store(cargo); + + logger.log( + Level.INFO, + "Changed destination for cargo {0} to {1}", + new Object[] {trackingId, routeSpecification.getDestination()}); + } + + @Override + public void changeDeadline(TrackingId trackingId, Date newDeadline) { + Cargo cargo = cargoRepository.find(trackingId); + + RouteSpecification routeSpecification = + new RouteSpecification( + cargo.getOrigin(), cargo.getRouteSpecification().getDestination(), newDeadline); + cargo.specifyNewRoute(routeSpecification); + + cargoRepository.store(cargo); + + logger.log( + Level.INFO, + "Changed deadline for cargo {0} to {1}", + new Object[] {trackingId, newDeadline}); + } } diff --git a/src/main/java/org/eclipse/cargotracker/application/internal/DefaultCargoInspectionService.java b/src/main/java/org/eclipse/cargotracker/application/internal/DefaultCargoInspectionService.java index 93e4f9555..8d0869d87 100644 --- a/src/main/java/org/eclipse/cargotracker/application/internal/DefaultCargoInspectionService.java +++ b/src/main/java/org/eclipse/cargotracker/application/internal/DefaultCargoInspectionService.java @@ -16,47 +16,42 @@ import org.eclipse.cargotracker.domain.model.handling.HandlingHistory; import org.eclipse.cargotracker.infrastructure.events.cdi.CargoInspected; -//TODO [Jakarta EE 8] Adopt the Date-Time API. +// TODO [Jakarta EE 8] Adopt the Date-Time API. @Stateless public class DefaultCargoInspectionService implements CargoInspectionService { - @Inject - private ApplicationEvents applicationEvents; - @Inject - private CargoRepository cargoRepository; - @Inject - private HandlingEventRepository handlingEventRepository; + @Inject private ApplicationEvents applicationEvents; + @Inject private CargoRepository cargoRepository; + @Inject private HandlingEventRepository handlingEventRepository; - @Inject - @CargoInspected - private Event cargoInspected; + @Inject @CargoInspected private Event cargoInspected; - @Inject - private Logger logger; + @Inject private Logger logger; - @Override - public void inspectCargo(TrackingId trackingId) { - Cargo cargo = cargoRepository.find(trackingId); + @Override + public void inspectCargo(TrackingId trackingId) { + Cargo cargo = cargoRepository.find(trackingId); - if (cargo == null) { - logger.log(Level.WARNING, "Can't inspect non-existing cargo {0}", trackingId); - return; - } + if (cargo == null) { + logger.log(Level.WARNING, "Can't inspect non-existing cargo {0}", trackingId); + return; + } - HandlingHistory handlingHistory = handlingEventRepository.lookupHandlingHistoryOfCargo(trackingId); + HandlingHistory handlingHistory = + handlingEventRepository.lookupHandlingHistoryOfCargo(trackingId); - cargo.deriveDeliveryProgress(handlingHistory); + cargo.deriveDeliveryProgress(handlingHistory); - if (cargo.getDelivery().isMisdirected()) { - applicationEvents.cargoWasMisdirected(cargo); - } + if (cargo.getDelivery().isMisdirected()) { + applicationEvents.cargoWasMisdirected(cargo); + } - if (cargo.getDelivery().isUnloadedAtDestination()) { - applicationEvents.cargoHasArrived(cargo); - } + if (cargo.getDelivery().isUnloadedAtDestination()) { + applicationEvents.cargoHasArrived(cargo); + } - cargoRepository.store(cargo); + cargoRepository.store(cargo); - cargoInspected.fire(cargo); - } + cargoInspected.fire(cargo); + } } diff --git a/src/main/java/org/eclipse/cargotracker/application/internal/DefaultHandlingEventService.java b/src/main/java/org/eclipse/cargotracker/application/internal/DefaultHandlingEventService.java index 26cdff8dd..75fd03bd4 100644 --- a/src/main/java/org/eclipse/cargotracker/application/internal/DefaultHandlingEventService.java +++ b/src/main/java/org/eclipse/cargotracker/application/internal/DefaultHandlingEventService.java @@ -20,39 +20,40 @@ @Stateless public class DefaultHandlingEventService implements HandlingEventService { - @Inject - private ApplicationEvents applicationEvents; - @Inject - private HandlingEventRepository handlingEventRepository; - @Inject - private HandlingEventFactory handlingEventFactory; - @Inject - private Logger logger; - - @Override - public void registerHandlingEvent(Date completionTime, TrackingId trackingId, VoyageNumber voyageNumber, - UnLocode unLocode, HandlingEvent.Type type) throws CannotCreateHandlingEventException { - Date registrationTime = new Date(); - - /* - * Using a factory to create a HandlingEvent (aggregate). This is where it is - * determined wether the incoming data, the attempt, actually is capable of - * representing a real handling event. - */ - HandlingEvent event = handlingEventFactory.createHandlingEvent(registrationTime, completionTime, trackingId, - voyageNumber, unLocode, type); - - /* - * Store the new handling event, which updates the persistent state of the - * handling event aggregate (but not the cargo aggregate - that happens - * asynchronously!) - */ - handlingEventRepository.store(event); - - /* Publish an event stating that a cargo has been handled. */ - applicationEvents.cargoWasHandled(event); - - logger.info("Registered handling event"); - } - + @Inject private ApplicationEvents applicationEvents; + @Inject private HandlingEventRepository handlingEventRepository; + @Inject private HandlingEventFactory handlingEventFactory; + @Inject private Logger logger; + + @Override + public void registerHandlingEvent( + Date completionTime, + TrackingId trackingId, + VoyageNumber voyageNumber, + UnLocode unLocode, + HandlingEvent.Type type) + throws CannotCreateHandlingEventException { + Date registrationTime = new Date(); + + /* + * Using a factory to create a HandlingEvent (aggregate). This is where it is + * determined wether the incoming data, the attempt, actually is capable of + * representing a real handling event. + */ + HandlingEvent event = + handlingEventFactory.createHandlingEvent( + registrationTime, completionTime, trackingId, voyageNumber, unLocode, type); + + /* + * Store the new handling event, which updates the persistent state of the + * handling event aggregate (but not the cargo aggregate - that happens + * asynchronously!) + */ + handlingEventRepository.store(event); + + /* Publish an event stating that a cargo has been handled. */ + applicationEvents.cargoWasHandled(event); + + logger.info("Registered handling event"); + } } diff --git a/src/main/java/org/eclipse/cargotracker/application/util/DateUtil.java b/src/main/java/org/eclipse/cargotracker/application/util/DateUtil.java index 5b737680c..7fcbad1ee 100644 --- a/src/main/java/org/eclipse/cargotracker/application/util/DateUtil.java +++ b/src/main/java/org/eclipse/cargotracker/application/util/DateUtil.java @@ -4,34 +4,31 @@ import java.text.SimpleDateFormat; import java.util.Date; -/** - * A few utils for working with Date. - */ +/** A few utils for working with Date. */ // TODO [Clean Code] Make this a CDI singleton? public class DateUtil { - private DateUtil() { - } + private DateUtil() {} - public static Date toDate(String date) { - return toDate(date, "00:00.00.000"); - } + public static Date toDate(String date) { + return toDate(date, "00:00.00.000"); + } - public static Date toDate(String date, String time) { - try { - return new SimpleDateFormat("yyyy-MM-dd HH:mm").parse(date + " " + time); - } catch (ParseException e) { - throw new RuntimeException(e); - } - } + public static Date toDate(String date, String time) { + try { + return new SimpleDateFormat("yyyy-MM-dd HH:mm").parse(date + " " + time); + } catch (ParseException e) { + throw new RuntimeException(e); + } + } - public static String getDateFromDateTime(String dateTime) { - // 03/15/2014 12:00 AM CET - return dateTime.substring(0, dateTime.indexOf(" ")); - } + public static String getDateFromDateTime(String dateTime) { + // 03/15/2014 12:00 AM CET + return dateTime.substring(0, dateTime.indexOf(" ")); + } - public static String getTimeFromDateTime(String dateTime) { - // 03/15/2014 12:00 AM CET - return dateTime.substring(dateTime.indexOf(" ") + 1); - } + public static String getTimeFromDateTime(String dateTime) { + // 03/15/2014 12:00 AM CET + return dateTime.substring(dateTime.indexOf(" ") + 1); + } } diff --git a/src/main/java/org/eclipse/cargotracker/application/util/JsonMoxyConfigurationContextResolver.java b/src/main/java/org/eclipse/cargotracker/application/util/JsonMoxyConfigurationContextResolver.java index 95e32f330..37fa0f71d 100644 --- a/src/main/java/org/eclipse/cargotracker/application/util/JsonMoxyConfigurationContextResolver.java +++ b/src/main/java/org/eclipse/cargotracker/application/util/JsonMoxyConfigurationContextResolver.java @@ -12,15 +12,15 @@ // TODO [Jakarta EE 8] See if this can be removed. public class JsonMoxyConfigurationContextResolver implements ContextResolver { - @Override - public MoxyJsonConfig getContext(Class objectType) { - MoxyJsonConfig configuration = new MoxyJsonConfig(); + @Override + public MoxyJsonConfig getContext(Class objectType) { + MoxyJsonConfig configuration = new MoxyJsonConfig(); - Map namespacePrefixMapper = new HashMap<>(1); - namespacePrefixMapper.put("http://www.w3.org/2001/XMLSchema-instance", "xsi"); - configuration.setNamespacePrefixMapper(namespacePrefixMapper); - configuration.setNamespaceSeparator(':'); + Map namespacePrefixMapper = new HashMap<>(1); + namespacePrefixMapper.put("http://www.w3.org/2001/XMLSchema-instance", "xsi"); + configuration.setNamespacePrefixMapper(namespacePrefixMapper); + configuration.setNamespaceSeparator(':'); - return configuration; - } + return configuration; + } } diff --git a/src/main/java/org/eclipse/cargotracker/application/util/LocationUtil.java b/src/main/java/org/eclipse/cargotracker/application/util/LocationUtil.java index 2c0dc3e30..c3300cbb9 100644 --- a/src/main/java/org/eclipse/cargotracker/application/util/LocationUtil.java +++ b/src/main/java/org/eclipse/cargotracker/application/util/LocationUtil.java @@ -2,12 +2,12 @@ public class LocationUtil { - public static String getLocationName(String location) { - //Helsinki (FIHEL) - return location.substring(0, location.indexOf("(")); - } + public static String getLocationName(String location) { + // Helsinki (FIHEL) + return location.substring(0, location.indexOf("(")); + } - public static String getLocationCode(String location) { - return location.substring(location.indexOf("(") + 1, location.indexOf(")")); - } + public static String getLocationCode(String location) { + return location.substring(location.indexOf("(") + 1, location.indexOf(")")); + } } diff --git a/src/main/java/org/eclipse/cargotracker/application/util/RestConfiguration.java b/src/main/java/org/eclipse/cargotracker/application/util/RestConfiguration.java index 419108064..c907fc554 100644 --- a/src/main/java/org/eclipse/cargotracker/application/util/RestConfiguration.java +++ b/src/main/java/org/eclipse/cargotracker/application/util/RestConfiguration.java @@ -9,21 +9,24 @@ import org.glassfish.jersey.server.ResourceConfig; import org.glassfish.jersey.server.ServerProperties; -/** - * JAX-RS configuration. - */ +/** JAX-RS configuration. */ @ApplicationPath("rest") public class RestConfiguration extends ResourceConfig { - public RestConfiguration() { - // Resources - packages(new String[] { HandlingReportService.class.getPackage().getName(), - GraphTraversalService.class.getPackage().getName(), - CargoMonitoringService.class.getPackage().getName() }); - // Enable Bean Validation error messages. - property(ServerProperties.BV_SEND_ERROR_IN_RESPONSE, true); - // Providers - JSON. - register(new MoxyJsonFeature()); - register(new JsonMoxyConfigurationContextResolver()); // TODO [Jakarta EE 8] See if this can be removed. - } + public RestConfiguration() { + // Resources + packages( + new String[] { + HandlingReportService.class.getPackage().getName(), + GraphTraversalService.class.getPackage().getName(), + CargoMonitoringService.class.getPackage().getName() + }); + // Enable Bean Validation error messages. + property(ServerProperties.BV_SEND_ERROR_IN_RESPONSE, true); + // Providers - JSON. + register(new MoxyJsonFeature()); + register( + new JsonMoxyConfigurationContextResolver()); // TODO [Jakarta EE 8] See if this can be + // removed. + } } diff --git a/src/main/java/org/eclipse/cargotracker/application/util/SampleDataGenerator.java b/src/main/java/org/eclipse/cargotracker/application/util/SampleDataGenerator.java index 6b9f17bff..8500ba85b 100644 --- a/src/main/java/org/eclipse/cargotracker/application/util/SampleDataGenerator.java +++ b/src/main/java/org/eclipse/cargotracker/application/util/SampleDataGenerator.java @@ -28,245 +28,342 @@ import org.eclipse.cargotracker.domain.model.voyage.SampleVoyages; import org.joda.time.LocalDate; -/** - * Loads sample data for demo. - */ +/** Loads sample data for demo. */ @Singleton @Startup public class SampleDataGenerator { - @Inject - private Logger logger; - - @PersistenceContext - private EntityManager entityManager; - @Inject - private HandlingEventFactory handlingEventFactory; - @Inject - private HandlingEventRepository handlingEventRepository; - - @PostConstruct - @TransactionAttribute(TransactionAttributeType.REQUIRED) - public void loadSampleData() { - logger.info("Loading sample data."); - unLoadAll(); // Fail-safe in case of application restart that does not trigger a JPA schema - // drop. - loadSampleLocations(); - loadSampleVoyages(); - loadSampleCargos(); - } - - private void unLoadAll() { - logger.info("Unloading all existing data."); - // In order to remove handling events, must remove references in cargo. - // Dropping cargo first won't work since handling events have references - // to it. - // TODO [Clean Code] See if there is a better way to do this. - List cargos = entityManager.createQuery("Select c from Cargo c", Cargo.class).getResultList(); - for (Cargo cargo : cargos) { - cargo.getDelivery().setLastEvent(null); - entityManager.merge(cargo); - } - - // Delete all entities - // TODO [Clean Code] See why cascade delete is not working. - entityManager.createQuery("Delete from HandlingEvent").executeUpdate(); - entityManager.createQuery("Delete from Leg").executeUpdate(); - entityManager.createQuery("Delete from Cargo").executeUpdate(); - entityManager.createQuery("Delete from CarrierMovement").executeUpdate(); - entityManager.createQuery("Delete from Voyage").executeUpdate(); - entityManager.createQuery("Delete from Location").executeUpdate(); - } - - private void loadSampleLocations() { - logger.info("Loading sample locations."); - - entityManager.persist(SampleLocations.HONGKONG); - entityManager.persist(SampleLocations.MELBOURNE); - entityManager.persist(SampleLocations.STOCKHOLM); - entityManager.persist(SampleLocations.HELSINKI); - entityManager.persist(SampleLocations.CHICAGO); - entityManager.persist(SampleLocations.TOKYO); - entityManager.persist(SampleLocations.HAMBURG); - entityManager.persist(SampleLocations.SHANGHAI); - entityManager.persist(SampleLocations.ROTTERDAM); - entityManager.persist(SampleLocations.GOTHENBURG); - entityManager.persist(SampleLocations.HANGZOU); - entityManager.persist(SampleLocations.NEWYORK); - entityManager.persist(SampleLocations.DALLAS); - } - - private void loadSampleVoyages() { - logger.info("Loading sample voyages."); - - entityManager.persist(SampleVoyages.HONGKONG_TO_NEW_YORK); - entityManager.persist(SampleVoyages.NEW_YORK_TO_DALLAS); - entityManager.persist(SampleVoyages.DALLAS_TO_HELSINKI); - entityManager.persist(SampleVoyages.HELSINKI_TO_HONGKONG); - entityManager.persist(SampleVoyages.DALLAS_TO_HELSINKI_ALT); - } - - private void loadSampleCargos() { - logger.info("Loading sample cargo data."); - - // Cargo ABC123. This one is en-route. - TrackingId trackingId1 = new TrackingId("ABC123"); - - RouteSpecification routeSpecification1 = new RouteSpecification(SampleLocations.HONGKONG, - SampleLocations.HELSINKI, LocalDate.now().plusDays(15).toDate()); - Cargo abc123 = new Cargo(trackingId1, routeSpecification1); - - Itinerary itinerary1 = new Itinerary(Arrays.asList( - new Leg(SampleVoyages.HONGKONG_TO_NEW_YORK, SampleLocations.HONGKONG, SampleLocations.NEWYORK, - LocalDate.now().minusDays(7).toDate(), LocalDate.now().minusDays(1).toDate()), - new Leg(SampleVoyages.NEW_YORK_TO_DALLAS, SampleLocations.NEWYORK, SampleLocations.DALLAS, - LocalDate.now().plusDays(2).toDate(), LocalDate.now().plusDays(6).toDate()), - new Leg(SampleVoyages.DALLAS_TO_HELSINKI, SampleLocations.DALLAS, SampleLocations.HELSINKI, - LocalDate.now().plusDays(8).toDate(), LocalDate.now().plusDays(14).toDate()))); - abc123.assignToRoute(itinerary1); - - entityManager.persist(abc123); - - try { - HandlingEvent event1 = handlingEventFactory.createHandlingEvent(new Date(), - LocalDate.now().minusDays(10).toDate(), trackingId1, null, SampleLocations.HONGKONG.getUnLocode(), - HandlingEvent.Type.RECEIVE); - entityManager.persist(event1); - - HandlingEvent event2 = handlingEventFactory.createHandlingEvent(new Date(), - LocalDate.now().minusDays(7).toDate(), trackingId1, - SampleVoyages.HONGKONG_TO_NEW_YORK.getVoyageNumber(), SampleLocations.HONGKONG.getUnLocode(), - HandlingEvent.Type.LOAD); - entityManager.persist(event2); - - HandlingEvent event3 = handlingEventFactory.createHandlingEvent(new Date(), - LocalDate.now().minusDays(1).toDate(), trackingId1, - SampleVoyages.HONGKONG_TO_NEW_YORK.getVoyageNumber(), SampleLocations.NEWYORK.getUnLocode(), - HandlingEvent.Type.UNLOAD); - entityManager.persist(event3); - } catch (CannotCreateHandlingEventException e) { - throw new RuntimeException(e); - } - - HandlingHistory handlingHistory1 = handlingEventRepository.lookupHandlingHistoryOfCargo(trackingId1); - abc123.deriveDeliveryProgress(handlingHistory1); - - entityManager.persist(abc123); - - // Cargo JKL567. This one was loaded on the wrong voyage. - TrackingId trackingId2 = new TrackingId("JKL567"); - - RouteSpecification routeSpecification2 = new RouteSpecification(SampleLocations.HANGZOU, - SampleLocations.STOCKHOLM, LocalDate.now().plusDays(18).toDate()); - Cargo jkl567 = new Cargo(trackingId2, routeSpecification2); - - Itinerary itinerary2 = new Itinerary(Arrays.asList( - new Leg(SampleVoyages.HONGKONG_TO_NEW_YORK, SampleLocations.HANGZOU, SampleLocations.NEWYORK, - LocalDate.now().minusDays(10).toDate(), LocalDate.now().minusDays(3).toDate()), - new Leg(SampleVoyages.NEW_YORK_TO_DALLAS, SampleLocations.NEWYORK, SampleLocations.DALLAS, - LocalDate.now().minusDays(2).toDate(), LocalDate.now().plusDays(2).toDate()), - new Leg(SampleVoyages.DALLAS_TO_HELSINKI, SampleLocations.DALLAS, SampleLocations.STOCKHOLM, - LocalDate.now().plusDays(6).toDate(), LocalDate.now().plusDays(15).toDate()))); - jkl567.assignToRoute(itinerary2); - - entityManager.persist(jkl567); - - try { - HandlingEvent event1 = handlingEventFactory.createHandlingEvent(new Date(), - LocalDate.now().minusDays(15).toDate(), trackingId2, null, SampleLocations.HANGZOU.getUnLocode(), - HandlingEvent.Type.RECEIVE); - entityManager.persist(event1); - - HandlingEvent event2 = handlingEventFactory.createHandlingEvent(new Date(), - LocalDate.now().minusDays(10).toDate(), trackingId2, - SampleVoyages.HONGKONG_TO_NEW_YORK.getVoyageNumber(), SampleLocations.HANGZOU.getUnLocode(), - HandlingEvent.Type.LOAD); - entityManager.persist(event2); - - HandlingEvent event3 = handlingEventFactory.createHandlingEvent(new Date(), - LocalDate.now().minusDays(3).toDate(), trackingId2, - SampleVoyages.HONGKONG_TO_NEW_YORK.getVoyageNumber(), SampleLocations.NEWYORK.getUnLocode(), - HandlingEvent.Type.UNLOAD); - entityManager.persist(event3); - - // The wrong voyage! - HandlingEvent event4 = handlingEventFactory.createHandlingEvent(new Date(), - LocalDate.now().minusDays(2).toDate(), trackingId2, - SampleVoyages.HONGKONG_TO_NEW_YORK.getVoyageNumber(), SampleLocations.NEWYORK.getUnLocode(), - HandlingEvent.Type.LOAD); - entityManager.persist(event4); - } catch (CannotCreateHandlingEventException e) { - throw new RuntimeException(e); - } - - HandlingHistory handlingHistory2 = handlingEventRepository.lookupHandlingHistoryOfCargo(trackingId2); - jkl567.deriveDeliveryProgress(handlingHistory2); - - entityManager.persist(jkl567); - - // Cargo definition DEF789. This one will remain un-routed. - TrackingId trackingId3 = new TrackingId("DEF789"); - - RouteSpecification routeSpecification3 = new RouteSpecification(SampleLocations.HONGKONG, - SampleLocations.MELBOURNE, LocalDate.now().plusMonths(2).toDate()); - - Cargo def789 = new Cargo(trackingId3, routeSpecification3); - entityManager.persist(def789); - - // Cargo definition MNO456. This one will be claimed properly. - TrackingId trackingId4 = new TrackingId("MNO456"); - RouteSpecification routeSpecification4 = new RouteSpecification(SampleLocations.NEWYORK, SampleLocations.DALLAS, - LocalDate.now().minusDays(24).toDate()); - - Cargo mno456 = new Cargo(trackingId4, routeSpecification4); - - Itinerary itinerary4 = new Itinerary( - Arrays.asList(new Leg(SampleVoyages.NEW_YORK_TO_DALLAS, SampleLocations.NEWYORK, SampleLocations.DALLAS, - LocalDate.now().minusDays(34).toDate(), LocalDate.now().minusDays(28).toDate()))); - - mno456.assignToRoute(itinerary4); - entityManager.persist(mno456); - - try { - HandlingEvent event1 = handlingEventFactory.createHandlingEvent(new Date(), - LocalDate.now().minusDays(37).toDate(), trackingId4, null, SampleLocations.NEWYORK.getUnLocode(), - HandlingEvent.Type.RECEIVE); - - entityManager.persist(event1); - - HandlingEvent event2 = handlingEventFactory.createHandlingEvent(new Date(), - LocalDate.now().minusDays(34).toDate(), trackingId4, - SampleVoyages.NEW_YORK_TO_DALLAS.getVoyageNumber(), SampleLocations.NEWYORK.getUnLocode(), - HandlingEvent.Type.LOAD); - - entityManager.persist(event2); - - HandlingEvent event3 = handlingEventFactory.createHandlingEvent(new Date(), - LocalDate.now().minusDays(28).toDate(), trackingId4, - SampleVoyages.NEW_YORK_TO_DALLAS.getVoyageNumber(), SampleLocations.DALLAS.getUnLocode(), - HandlingEvent.Type.UNLOAD); - - entityManager.persist(event3); - - HandlingEvent event4 = handlingEventFactory.createHandlingEvent(new Date(), - LocalDate.now().minusDays(27).toDate(), trackingId4, null, SampleLocations.DALLAS.getUnLocode(), - HandlingEvent.Type.CUSTOMS); - - entityManager.persist(event4); - - HandlingEvent event5 = handlingEventFactory.createHandlingEvent(new Date(), - LocalDate.now().minusDays(26).toDate(), trackingId4, null, SampleLocations.DALLAS.getUnLocode(), - HandlingEvent.Type.CLAIM); - - entityManager.persist(event5); - - HandlingHistory handlingHistory3 = handlingEventRepository.lookupHandlingHistoryOfCargo(trackingId4); - - mno456.deriveDeliveryProgress(handlingHistory3); - - entityManager.persist(mno456); - } catch (CannotCreateHandlingEventException e) { - throw new RuntimeException(e); - } - } + @Inject private Logger logger; + + @PersistenceContext private EntityManager entityManager; + @Inject private HandlingEventFactory handlingEventFactory; + @Inject private HandlingEventRepository handlingEventRepository; + + @PostConstruct + @TransactionAttribute(TransactionAttributeType.REQUIRED) + public void loadSampleData() { + logger.info("Loading sample data."); + unLoadAll(); // Fail-safe in case of application restart that does not trigger a JPA schema + // drop. + loadSampleLocations(); + loadSampleVoyages(); + loadSampleCargos(); + } + + private void unLoadAll() { + logger.info("Unloading all existing data."); + // In order to remove handling events, must remove references in cargo. + // Dropping cargo first won't work since handling events have references + // to it. + // TODO [Clean Code] See if there is a better way to do this. + List cargos = + entityManager.createQuery("Select c from Cargo c", Cargo.class).getResultList(); + for (Cargo cargo : cargos) { + cargo.getDelivery().setLastEvent(null); + entityManager.merge(cargo); + } + + // Delete all entities + // TODO [Clean Code] See why cascade delete is not working. + entityManager.createQuery("Delete from HandlingEvent").executeUpdate(); + entityManager.createQuery("Delete from Leg").executeUpdate(); + entityManager.createQuery("Delete from Cargo").executeUpdate(); + entityManager.createQuery("Delete from CarrierMovement").executeUpdate(); + entityManager.createQuery("Delete from Voyage").executeUpdate(); + entityManager.createQuery("Delete from Location").executeUpdate(); + } + + private void loadSampleLocations() { + logger.info("Loading sample locations."); + + entityManager.persist(SampleLocations.HONGKONG); + entityManager.persist(SampleLocations.MELBOURNE); + entityManager.persist(SampleLocations.STOCKHOLM); + entityManager.persist(SampleLocations.HELSINKI); + entityManager.persist(SampleLocations.CHICAGO); + entityManager.persist(SampleLocations.TOKYO); + entityManager.persist(SampleLocations.HAMBURG); + entityManager.persist(SampleLocations.SHANGHAI); + entityManager.persist(SampleLocations.ROTTERDAM); + entityManager.persist(SampleLocations.GOTHENBURG); + entityManager.persist(SampleLocations.HANGZOU); + entityManager.persist(SampleLocations.NEWYORK); + entityManager.persist(SampleLocations.DALLAS); + } + + private void loadSampleVoyages() { + logger.info("Loading sample voyages."); + + entityManager.persist(SampleVoyages.HONGKONG_TO_NEW_YORK); + entityManager.persist(SampleVoyages.NEW_YORK_TO_DALLAS); + entityManager.persist(SampleVoyages.DALLAS_TO_HELSINKI); + entityManager.persist(SampleVoyages.HELSINKI_TO_HONGKONG); + entityManager.persist(SampleVoyages.DALLAS_TO_HELSINKI_ALT); + } + + private void loadSampleCargos() { + logger.info("Loading sample cargo data."); + + // Cargo ABC123. This one is en-route. + TrackingId trackingId1 = new TrackingId("ABC123"); + + RouteSpecification routeSpecification1 = + new RouteSpecification( + SampleLocations.HONGKONG, + SampleLocations.HELSINKI, + LocalDate.now().plusDays(15).toDate()); + Cargo abc123 = new Cargo(trackingId1, routeSpecification1); + + Itinerary itinerary1 = + new Itinerary( + Arrays.asList( + new Leg( + SampleVoyages.HONGKONG_TO_NEW_YORK, + SampleLocations.HONGKONG, + SampleLocations.NEWYORK, + LocalDate.now().minusDays(7).toDate(), + LocalDate.now().minusDays(1).toDate()), + new Leg( + SampleVoyages.NEW_YORK_TO_DALLAS, + SampleLocations.NEWYORK, + SampleLocations.DALLAS, + LocalDate.now().plusDays(2).toDate(), + LocalDate.now().plusDays(6).toDate()), + new Leg( + SampleVoyages.DALLAS_TO_HELSINKI, + SampleLocations.DALLAS, + SampleLocations.HELSINKI, + LocalDate.now().plusDays(8).toDate(), + LocalDate.now().plusDays(14).toDate()))); + abc123.assignToRoute(itinerary1); + + entityManager.persist(abc123); + + try { + HandlingEvent event1 = + handlingEventFactory.createHandlingEvent( + new Date(), + LocalDate.now().minusDays(10).toDate(), + trackingId1, + null, + SampleLocations.HONGKONG.getUnLocode(), + HandlingEvent.Type.RECEIVE); + entityManager.persist(event1); + + HandlingEvent event2 = + handlingEventFactory.createHandlingEvent( + new Date(), + LocalDate.now().minusDays(7).toDate(), + trackingId1, + SampleVoyages.HONGKONG_TO_NEW_YORK.getVoyageNumber(), + SampleLocations.HONGKONG.getUnLocode(), + HandlingEvent.Type.LOAD); + entityManager.persist(event2); + + HandlingEvent event3 = + handlingEventFactory.createHandlingEvent( + new Date(), + LocalDate.now().minusDays(1).toDate(), + trackingId1, + SampleVoyages.HONGKONG_TO_NEW_YORK.getVoyageNumber(), + SampleLocations.NEWYORK.getUnLocode(), + HandlingEvent.Type.UNLOAD); + entityManager.persist(event3); + } catch (CannotCreateHandlingEventException e) { + throw new RuntimeException(e); + } + + HandlingHistory handlingHistory1 = + handlingEventRepository.lookupHandlingHistoryOfCargo(trackingId1); + abc123.deriveDeliveryProgress(handlingHistory1); + + entityManager.persist(abc123); + + // Cargo JKL567. This one was loaded on the wrong voyage. + TrackingId trackingId2 = new TrackingId("JKL567"); + + RouteSpecification routeSpecification2 = + new RouteSpecification( + SampleLocations.HANGZOU, + SampleLocations.STOCKHOLM, + LocalDate.now().plusDays(18).toDate()); + Cargo jkl567 = new Cargo(trackingId2, routeSpecification2); + + Itinerary itinerary2 = + new Itinerary( + Arrays.asList( + new Leg( + SampleVoyages.HONGKONG_TO_NEW_YORK, + SampleLocations.HANGZOU, + SampleLocations.NEWYORK, + LocalDate.now().minusDays(10).toDate(), + LocalDate.now().minusDays(3).toDate()), + new Leg( + SampleVoyages.NEW_YORK_TO_DALLAS, + SampleLocations.NEWYORK, + SampleLocations.DALLAS, + LocalDate.now().minusDays(2).toDate(), + LocalDate.now().plusDays(2).toDate()), + new Leg( + SampleVoyages.DALLAS_TO_HELSINKI, + SampleLocations.DALLAS, + SampleLocations.STOCKHOLM, + LocalDate.now().plusDays(6).toDate(), + LocalDate.now().plusDays(15).toDate()))); + jkl567.assignToRoute(itinerary2); + + entityManager.persist(jkl567); + + try { + HandlingEvent event1 = + handlingEventFactory.createHandlingEvent( + new Date(), + LocalDate.now().minusDays(15).toDate(), + trackingId2, + null, + SampleLocations.HANGZOU.getUnLocode(), + HandlingEvent.Type.RECEIVE); + entityManager.persist(event1); + + HandlingEvent event2 = + handlingEventFactory.createHandlingEvent( + new Date(), + LocalDate.now().minusDays(10).toDate(), + trackingId2, + SampleVoyages.HONGKONG_TO_NEW_YORK.getVoyageNumber(), + SampleLocations.HANGZOU.getUnLocode(), + HandlingEvent.Type.LOAD); + entityManager.persist(event2); + + HandlingEvent event3 = + handlingEventFactory.createHandlingEvent( + new Date(), + LocalDate.now().minusDays(3).toDate(), + trackingId2, + SampleVoyages.HONGKONG_TO_NEW_YORK.getVoyageNumber(), + SampleLocations.NEWYORK.getUnLocode(), + HandlingEvent.Type.UNLOAD); + entityManager.persist(event3); + + // The wrong voyage! + HandlingEvent event4 = + handlingEventFactory.createHandlingEvent( + new Date(), + LocalDate.now().minusDays(2).toDate(), + trackingId2, + SampleVoyages.HONGKONG_TO_NEW_YORK.getVoyageNumber(), + SampleLocations.NEWYORK.getUnLocode(), + HandlingEvent.Type.LOAD); + entityManager.persist(event4); + } catch (CannotCreateHandlingEventException e) { + throw new RuntimeException(e); + } + + HandlingHistory handlingHistory2 = + handlingEventRepository.lookupHandlingHistoryOfCargo(trackingId2); + jkl567.deriveDeliveryProgress(handlingHistory2); + + entityManager.persist(jkl567); + + // Cargo definition DEF789. This one will remain un-routed. + TrackingId trackingId3 = new TrackingId("DEF789"); + + RouteSpecification routeSpecification3 = + new RouteSpecification( + SampleLocations.HONGKONG, + SampleLocations.MELBOURNE, + LocalDate.now().plusMonths(2).toDate()); + + Cargo def789 = new Cargo(trackingId3, routeSpecification3); + entityManager.persist(def789); + + // Cargo definition MNO456. This one will be claimed properly. + TrackingId trackingId4 = new TrackingId("MNO456"); + RouteSpecification routeSpecification4 = + new RouteSpecification( + SampleLocations.NEWYORK, + SampleLocations.DALLAS, + LocalDate.now().minusDays(24).toDate()); + + Cargo mno456 = new Cargo(trackingId4, routeSpecification4); + + Itinerary itinerary4 = + new Itinerary( + Arrays.asList( + new Leg( + SampleVoyages.NEW_YORK_TO_DALLAS, + SampleLocations.NEWYORK, + SampleLocations.DALLAS, + LocalDate.now().minusDays(34).toDate(), + LocalDate.now().minusDays(28).toDate()))); + + mno456.assignToRoute(itinerary4); + entityManager.persist(mno456); + + try { + HandlingEvent event1 = + handlingEventFactory.createHandlingEvent( + new Date(), + LocalDate.now().minusDays(37).toDate(), + trackingId4, + null, + SampleLocations.NEWYORK.getUnLocode(), + HandlingEvent.Type.RECEIVE); + + entityManager.persist(event1); + + HandlingEvent event2 = + handlingEventFactory.createHandlingEvent( + new Date(), + LocalDate.now().minusDays(34).toDate(), + trackingId4, + SampleVoyages.NEW_YORK_TO_DALLAS.getVoyageNumber(), + SampleLocations.NEWYORK.getUnLocode(), + HandlingEvent.Type.LOAD); + + entityManager.persist(event2); + + HandlingEvent event3 = + handlingEventFactory.createHandlingEvent( + new Date(), + LocalDate.now().minusDays(28).toDate(), + trackingId4, + SampleVoyages.NEW_YORK_TO_DALLAS.getVoyageNumber(), + SampleLocations.DALLAS.getUnLocode(), + HandlingEvent.Type.UNLOAD); + + entityManager.persist(event3); + + HandlingEvent event4 = + handlingEventFactory.createHandlingEvent( + new Date(), + LocalDate.now().minusDays(27).toDate(), + trackingId4, + null, + SampleLocations.DALLAS.getUnLocode(), + HandlingEvent.Type.CUSTOMS); + + entityManager.persist(event4); + + HandlingEvent event5 = + handlingEventFactory.createHandlingEvent( + new Date(), + LocalDate.now().minusDays(26).toDate(), + trackingId4, + null, + SampleLocations.DALLAS.getUnLocode(), + HandlingEvent.Type.CLAIM); + + entityManager.persist(event5); + + HandlingHistory handlingHistory3 = + handlingEventRepository.lookupHandlingHistoryOfCargo(trackingId4); + + mno456.deriveDeliveryProgress(handlingHistory3); + + entityManager.persist(mno456); + } catch (CannotCreateHandlingEventException e) { + throw new RuntimeException(e); + } + } } From 9792e35b5558ae602c0f5db7437eaf49f1d396f4 Mon Sep 17 00:00:00 2001 From: Reza Rahman Date: Sun, 17 Jan 2021 09:24:47 -0500 Subject: [PATCH 02/22] Apply Google Java Code Style --- .../domain/model/cargo/Cargo.java | 342 +++++---- .../domain/model/cargo/CargoRepository.java | 10 +- .../domain/model/cargo/Delivery.java | 668 +++++++++--------- .../domain/model/cargo/HandlingActivity.java | 179 ++--- .../domain/model/cargo/Itinerary.java | 303 ++++---- .../cargotracker/domain/model/cargo/Leg.java | 211 +++--- .../model/cargo/RouteSpecification.java | 163 +++-- .../domain/model/cargo/RoutingStatus.java | 11 +- .../domain/model/cargo/TrackingId.java | 72 +- .../domain/model/cargo/TransportStatus.java | 13 +- .../eclipse/cargotracker/domain/package.html | 8 +- 11 files changed, 1023 insertions(+), 957 deletions(-) diff --git a/src/main/java/org/eclipse/cargotracker/domain/model/cargo/Cargo.java b/src/main/java/org/eclipse/cargotracker/domain/model/cargo/Cargo.java index 965d25850..517910cb9 100644 --- a/src/main/java/org/eclipse/cargotracker/domain/model/cargo/Cargo.java +++ b/src/main/java/org/eclipse/cargotracker/domain/model/cargo/Cargo.java @@ -18,185 +18,175 @@ import org.eclipse.cargotracker.domain.shared.DomainObjectUtils; /** - * A Cargo. This is the central class in the domain model, and it is the root of - * the Cargo-Itinerary-Leg-Delivery-RouteSpecification aggregate. - *

- * A cargo is identified by a unique tracking ID, and it always has an origin - * and a route specification. The life cycle of a cargo begins with the booking - * procedure, when the tracking ID is assigned. During a (short) period of time, - * between booking and initial routing, the cargo has no itinerary. - *

- * The booking clerk requests a list of possible routes, matching the route - * specification, and assigns the cargo to one route. The route to which a cargo - * is assigned is described by an itinerary. - *

- * A cargo can be re-routed during transport, on demand of the customer, in - * which case a new route is specified for the cargo and a new route is - * requested. The old itinerary, being a value object, is discarded and a new - * one is attached. - *

- * It may also happen that a cargo is accidentally misrouted, which should - * notify the proper personnel and also trigger a re-routing procedure. - *

- * When a cargo is handled, the status of the delivery changes. Everything about - * the delivery of the cargo is contained in the Delivery value object, which is - * replaced whenever a cargo is handled by an asynchronous event triggered by - * the registration of the handling event. - *

- * The delivery can also be affected by routing changes, i.e. when a the route - * specification changes, or the cargo is assigned to a new route. In that case, - * the delivery update is performed synchronously within the cargo aggregate. - *

- * The life cycle of a cargo ends when the cargo is claimed by the customer. - *

- * The cargo aggregate, and the entire domain model, is built to solve the - * problem of booking and tracking cargo. All important business rules for - * determining whether or not a cargo is misdirected, what the current status of - * the cargo is (on board carrier, in port etc), are captured in this aggregate. + * A Cargo. This is the central class in the domain model, and it is the root of the + * Cargo-Itinerary-Leg-Delivery-RouteSpecification aggregate. + * + *

A cargo is identified by a unique tracking ID, and it always has an origin and a route + * specification. The life cycle of a cargo begins with the booking procedure, when the tracking ID + * is assigned. During a (short) period of time, between booking and initial routing, the cargo has + * no itinerary. + * + *

The booking clerk requests a list of possible routes, matching the route specification, and + * assigns the cargo to one route. The route to which a cargo is assigned is described by an + * itinerary. + * + *

A cargo can be re-routed during transport, on demand of the customer, in which case a new + * route is specified for the cargo and a new route is requested. The old itinerary, being a value + * object, is discarded and a new one is attached. + * + *

It may also happen that a cargo is accidentally misrouted, which should notify the proper + * personnel and also trigger a re-routing procedure. + * + *

When a cargo is handled, the status of the delivery changes. Everything about the delivery of + * the cargo is contained in the Delivery value object, which is replaced whenever a cargo is + * handled by an asynchronous event triggered by the registration of the handling event. + * + *

The delivery can also be affected by routing changes, i.e. when a the route specification + * changes, or the cargo is assigned to a new route. In that case, the delivery update is performed + * synchronously within the cargo aggregate. + * + *

The life cycle of a cargo ends when the cargo is claimed by the customer. + * + *

The cargo aggregate, and the entire domain model, is built to solve the problem of booking and + * tracking cargo. All important business rules for determining whether or not a cargo is + * misdirected, what the current status of the cargo is (on board carrier, in port etc), are + * captured in this aggregate. */ @Entity // TODO [Jakarta EE 8] Apply repeatable annotations. -@NamedQueries({ @NamedQuery(name = "Cargo.findAll", query = "Select c from Cargo c"), - @NamedQuery(name = "Cargo.findByTrackingId", query = "Select c from Cargo c where c.trackingId = :trackingId") }) +@NamedQueries({ + @NamedQuery(name = "Cargo.findAll", query = "Select c from Cargo c"), + @NamedQuery( + name = "Cargo.findByTrackingId", + query = "Select c from Cargo c where c.trackingId = :trackingId") +}) public class Cargo implements Serializable { - private static final long serialVersionUID = 1L; - - @Id - @GeneratedValue - private Long id; - @Embedded - private TrackingId trackingId; - @ManyToOne - @JoinColumn(name = "origin_id", updatable = false) - private Location origin; - @Embedded - private RouteSpecification routeSpecification; - @Embedded - private Itinerary itinerary; - @Embedded - private Delivery delivery; - - public Cargo() { - // Nothing to initialize. - } - - public Cargo(TrackingId trackingId, RouteSpecification routeSpecification) { - Validate.notNull(trackingId, "Tracking ID is required"); - Validate.notNull(routeSpecification, "Route specification is required"); - - this.trackingId = trackingId; - // Cargo origin never changes, even if the route specification changes. - // However, at creation, cargo origin can be derived from the initial - // route specification. - this.origin = routeSpecification.getOrigin(); - this.routeSpecification = routeSpecification; - - this.delivery = Delivery.derivedFrom(this.routeSpecification, this.itinerary, HandlingHistory.EMPTY); - this.itinerary = Itinerary.EMPTY_ITINERARY; - } - - public TrackingId getTrackingId() { - return trackingId; - } - - public void setOrigin(Location origin) { - this.origin = origin; - } - - public Location getOrigin() { - return origin; - } - - public RouteSpecification getRouteSpecification() { - return routeSpecification; - } - - /** - * @return The delivery. Never null. - */ - public Delivery getDelivery() { - return delivery; - } - - /** - * @return The itinerary. Never null. - */ - public Itinerary getItinerary() { - return DomainObjectUtils.nullSafe(this.itinerary, Itinerary.EMPTY_ITINERARY); - } - - /** - * Specifies a new route for this cargo. - */ - public void specifyNewRoute(RouteSpecification routeSpecification) { - Validate.notNull(routeSpecification, "Route specification is required"); - - this.routeSpecification = routeSpecification; - // Handling consistency within the Cargo aggregate synchronously - this.delivery = delivery.updateOnRouting(this.routeSpecification, this.itinerary); - } - - public void assignToRoute(Itinerary itinerary) { - Validate.notNull(itinerary, "Itinerary is required for assignment"); - - this.itinerary = itinerary; - // Handling consistency within the Cargo aggregate synchronously - this.delivery = delivery.updateOnRouting(this.routeSpecification, this.itinerary); - } - - /** - * Updates all aspects of the cargo aggregate status based on the current route - * specification, itinerary and handling of the cargo. - *

- * When either of those three changes, i.e. when a new route is specified for - * the cargo, the cargo is assigned to a route or when the cargo is handled, the - * status must be re-calculated. - *

- * {@link RouteSpecification} and {@link Itinerary} are both inside the Cargo - * aggregate, so changes to them cause the status to be updated - * synchronously, but changes to the delivery history (when a cargo is - * handled) cause the status update to happen asynchronously since - * {@link HandlingEvent} is in a different aggregate. - * - * @param handlingHistory handling history - */ - public void deriveDeliveryProgress(HandlingHistory handlingHistory) { - this.delivery = Delivery.derivedFrom(getRouteSpecification(), getItinerary(), handlingHistory); - } - - /** - * @param object to compare - * @return True if they have the same identity - * @see #sameIdentityAs(Cargo) - */ - @Override - public boolean equals(Object object) { - if (this == object) { - return true; - } - if (object == null || getClass() != object.getClass()) { - return false; - } - - Cargo other = (Cargo) object; - return sameIdentityAs(other); - } - - private boolean sameIdentityAs(Cargo other) { - return other != null && trackingId.sameValueAs(other.trackingId); - } - - /** - * @return Hash code of tracking id. - */ - @Override - public int hashCode() { - return trackingId.hashCode(); - } - - @Override - public String toString() { - return trackingId.toString(); - } + private static final long serialVersionUID = 1L; + + @Id @GeneratedValue private Long id; + @Embedded private TrackingId trackingId; + + @ManyToOne + @JoinColumn(name = "origin_id", updatable = false) + private Location origin; + + @Embedded private RouteSpecification routeSpecification; + @Embedded private Itinerary itinerary; + @Embedded private Delivery delivery; + + public Cargo() { + // Nothing to initialize. + } + + public Cargo(TrackingId trackingId, RouteSpecification routeSpecification) { + Validate.notNull(trackingId, "Tracking ID is required"); + Validate.notNull(routeSpecification, "Route specification is required"); + + this.trackingId = trackingId; + // Cargo origin never changes, even if the route specification changes. + // However, at creation, cargo origin can be derived from the initial + // route specification. + this.origin = routeSpecification.getOrigin(); + this.routeSpecification = routeSpecification; + + this.delivery = + Delivery.derivedFrom(this.routeSpecification, this.itinerary, HandlingHistory.EMPTY); + this.itinerary = Itinerary.EMPTY_ITINERARY; + } + + public TrackingId getTrackingId() { + return trackingId; + } + + public void setOrigin(Location origin) { + this.origin = origin; + } + + public Location getOrigin() { + return origin; + } + + public RouteSpecification getRouteSpecification() { + return routeSpecification; + } + + /** @return The delivery. Never null. */ + public Delivery getDelivery() { + return delivery; + } + + /** @return The itinerary. Never null. */ + public Itinerary getItinerary() { + return DomainObjectUtils.nullSafe(this.itinerary, Itinerary.EMPTY_ITINERARY); + } + + /** Specifies a new route for this cargo. */ + public void specifyNewRoute(RouteSpecification routeSpecification) { + Validate.notNull(routeSpecification, "Route specification is required"); + + this.routeSpecification = routeSpecification; + // Handling consistency within the Cargo aggregate synchronously + this.delivery = delivery.updateOnRouting(this.routeSpecification, this.itinerary); + } + + public void assignToRoute(Itinerary itinerary) { + Validate.notNull(itinerary, "Itinerary is required for assignment"); + + this.itinerary = itinerary; + // Handling consistency within the Cargo aggregate synchronously + this.delivery = delivery.updateOnRouting(this.routeSpecification, this.itinerary); + } + + /** + * Updates all aspects of the cargo aggregate status based on the current route specification, + * itinerary and handling of the cargo. + * + *

When either of those three changes, i.e. when a new route is specified for the cargo, the + * cargo is assigned to a route or when the cargo is handled, the status must be re-calculated. + * + *

{@link RouteSpecification} and {@link Itinerary} are both inside the Cargo aggregate, so + * changes to them cause the status to be updated synchronously, but changes to the + * delivery history (when a cargo is handled) cause the status update to happen + * asynchronously since {@link HandlingEvent} is in a different aggregate. + * + * @param handlingHistory handling history + */ + public void deriveDeliveryProgress(HandlingHistory handlingHistory) { + this.delivery = Delivery.derivedFrom(getRouteSpecification(), getItinerary(), handlingHistory); + } + + /** + * @param object to compare + * @return True if they have the same identity + * @see #sameIdentityAs(Cargo) + */ + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + + if (object == null || getClass() != object.getClass()) { + return false; + } + + Cargo other = (Cargo) object; + return sameIdentityAs(other); + } + + private boolean sameIdentityAs(Cargo other) { + return other != null && trackingId.sameValueAs(other.trackingId); + } + + /** @return Hash code of tracking id. */ + @Override + public int hashCode() { + return trackingId.hashCode(); + } + + @Override + public String toString() { + return trackingId.toString(); + } } diff --git a/src/main/java/org/eclipse/cargotracker/domain/model/cargo/CargoRepository.java b/src/main/java/org/eclipse/cargotracker/domain/model/cargo/CargoRepository.java index f5234dc32..d8b4b942f 100644 --- a/src/main/java/org/eclipse/cargotracker/domain/model/cargo/CargoRepository.java +++ b/src/main/java/org/eclipse/cargotracker/domain/model/cargo/CargoRepository.java @@ -4,11 +4,11 @@ public interface CargoRepository { - Cargo find(TrackingId trackingId); + Cargo find(TrackingId trackingId); - List findAll(); + List findAll(); - void store(Cargo cargo); + void store(Cargo cargo); - TrackingId nextTrackingId(); -} \ No newline at end of file + TrackingId nextTrackingId(); +} diff --git a/src/main/java/org/eclipse/cargotracker/domain/model/cargo/Delivery.java b/src/main/java/org/eclipse/cargotracker/domain/model/cargo/Delivery.java index c4d21a908..9b965364c 100644 --- a/src/main/java/org/eclipse/cargotracker/domain/model/cargo/Delivery.java +++ b/src/main/java/org/eclipse/cargotracker/domain/model/cargo/Delivery.java @@ -34,329 +34,355 @@ import org.eclipse.cargotracker.domain.shared.DomainObjectUtils; /** - * The actual transportation of the cargo, as opposed to the customer - * requirement (RouteSpecification) and the plan (Itinerary). + * The actual transportation of the cargo, as opposed to the customer requirement + * (RouteSpecification) and the plan (Itinerary). */ @Embeddable public class Delivery implements Serializable { - private static final long serialVersionUID = 1L; - // Null object pattern. - public static final Date ETA_UNKOWN = null; - // Null object pattern - public static final HandlingActivity NO_ACTIVITY = new HandlingActivity(); - @Enumerated(EnumType.STRING) - @Column(name = "transport_status") - @NotNull - private TransportStatus transportStatus; - @ManyToOne - @JoinColumn(name = "last_known_location_id") - private Location lastKnownLocation; - @ManyToOne - @JoinColumn(name = "current_voyage_id") - private Voyage currentVoyage; - @NotNull - private boolean misdirected; - @Temporal(TemporalType.DATE) - private Date eta; - @Embedded - private HandlingActivity nextExpectedActivity; - @Column(name = "unloaded_at_dest") - @NotNull - private boolean isUnloadedAtDestination; - @Enumerated(EnumType.STRING) - @Column(name = "routing_status") - @NotNull - private RoutingStatus routingStatus; - @Temporal(TemporalType.TIMESTAMP) - @Column(name = "calculated_at") - @NotNull - private Date calculatedAt; - @ManyToOne - @JoinColumn(name = "last_event_id") - private HandlingEvent lastEvent; - - public Delivery() { - // Nothing to initialize - } - - public Delivery(HandlingEvent lastEvent, Itinerary itinerary, RouteSpecification routeSpecification) { - this.calculatedAt = new Date(); - this.lastEvent = lastEvent; - - this.misdirected = calculateMisdirectionStatus(itinerary); - this.routingStatus = calculateRoutingStatus(itinerary, routeSpecification); - this.transportStatus = calculateTransportStatus(); - this.lastKnownLocation = calculateLastKnownLocation(); - this.currentVoyage = calculateCurrentVoyage(); - this.eta = calculateEta(itinerary); - this.nextExpectedActivity = calculateNextExpectedActivity(routeSpecification, itinerary); - this.isUnloadedAtDestination = calculateUnloadedAtDestination(routeSpecification); - } - - /** - * Creates a new delivery snapshot to reflect changes in routing, i.e. when the - * route specification or the itinerary has changed but no additional handling - * of the cargo has been performed. - */ - Delivery updateOnRouting(RouteSpecification routeSpecification, Itinerary itinerary) { - Validate.notNull(routeSpecification, "Route specification is required"); - - return new Delivery(this.lastEvent, itinerary, routeSpecification); - } - - /** - * Creates a new delivery snapshot based on the complete handling history of a - * cargo, as well as its route specification and itinerary. - * - * @param routeSpecification route specification - * @param itinerary itinerary - * @param handlingHistory delivery history - * @return An up to date delivery. - */ - static Delivery derivedFrom(RouteSpecification routeSpecification, Itinerary itinerary, - HandlingHistory handlingHistory) { - Validate.notNull(routeSpecification, "Route specification is required"); - Validate.notNull(handlingHistory, "Delivery history is required"); - - HandlingEvent lastEvent = handlingHistory.getMostRecentlyCompletedEvent(); - - return new Delivery(lastEvent, itinerary, routeSpecification); - } - - public TransportStatus getTransportStatus() { - return transportStatus; - } - - public void setTransportStatus(TransportStatus transportStatus) { - this.transportStatus = transportStatus; - } - - public Location getLastKnownLocation() { - return DomainObjectUtils.nullSafe(lastKnownLocation, Location.UNKNOWN); - } - - public void setLastKnownLocation(Location lastKnownLocation) { - this.lastKnownLocation = lastKnownLocation; - } - - public void setLastEvent(HandlingEvent lastEvent) { - this.lastEvent = lastEvent; - } - - public Voyage getCurrentVoyage() { - return DomainObjectUtils.nullSafe(currentVoyage, Voyage.NONE); - } - - /** - * Check if cargo is misdirected. - *

- *

- * - * @return true if the cargo has been misdirected, - */ - public boolean isMisdirected() { - return misdirected; - } - - public void setMisdirected(boolean misdirected) { - this.misdirected = misdirected; - } - - public Date getEstimatedTimeOfArrival() { - if (eta != ETA_UNKOWN) { - return new Date(eta.getTime()); - } else { - return ETA_UNKOWN; - } - } - - public HandlingActivity getNextExpectedActivity() { - return nextExpectedActivity; - } - - /** - * @return True if the cargo has been unloaded at the final destination. - */ - public boolean isUnloadedAtDestination() { - return isUnloadedAtDestination; - } - - public void setUnloadedAtDestination(boolean isUnloadedAtDestination) { - this.isUnloadedAtDestination = isUnloadedAtDestination; - } - - public RoutingStatus getRoutingStatus() { - return routingStatus; - } - - public void setRoutingStatus(RoutingStatus routingStatus) { - this.routingStatus = routingStatus; - } - - /** - * @return When this delivery was calculated. - */ - public Date getCalculatedAt() { - return new Date(calculatedAt.getTime()); - } - - public void setCalculatedAt(Date calculatedAt) { - this.calculatedAt = calculatedAt; - } - - private TransportStatus calculateTransportStatus() { - if (lastEvent == null) { - return NOT_RECEIVED; - } - - switch (lastEvent.getType()) { - case LOAD: - return ONBOARD_CARRIER; - case UNLOAD: - case RECEIVE: - case CUSTOMS: - return IN_PORT; - case CLAIM: - return CLAIMED; - default: - return UNKNOWN; - } - } - - private Location calculateLastKnownLocation() { - if (lastEvent != null) { - return lastEvent.getLocation(); - } else { - return null; - } - } - - private Voyage calculateCurrentVoyage() { - if (getTransportStatus().equals(ONBOARD_CARRIER) && lastEvent != null) { - return lastEvent.getVoyage(); - } else { - return null; - } - } - - private boolean calculateMisdirectionStatus(Itinerary itinerary) { - if (lastEvent == null) { - return false; - } else { - return !itinerary.isExpected(lastEvent); - } - } - - private Date calculateEta(Itinerary itinerary) { - if (onTrack()) { - return itinerary.getFinalArrivalDate(); - } else { - return ETA_UNKOWN; - } - } - - private HandlingActivity calculateNextExpectedActivity(RouteSpecification routeSpecification, Itinerary itinerary) { - if (!onTrack()) { - return NO_ACTIVITY; - } - - if (lastEvent == null) { - return new HandlingActivity(HandlingEvent.Type.RECEIVE, routeSpecification.getOrigin()); - } - - switch (lastEvent.getType()) { - case LOAD: - for (Leg leg : itinerary.getLegs()) { - if (leg.getLoadLocation().sameIdentityAs(lastEvent.getLocation())) { - return new HandlingActivity(HandlingEvent.Type.UNLOAD, leg.getUnloadLocation(), leg.getVoyage()); - } - } - - return NO_ACTIVITY; - - case UNLOAD: - for (Iterator iterator = itinerary.getLegs().iterator(); iterator.hasNext();) { - Leg leg = iterator.next(); - - if (leg.getUnloadLocation().sameIdentityAs(lastEvent.getLocation())) { - if (iterator.hasNext()) { - Leg nextLeg = iterator.next(); - return new HandlingActivity(HandlingEvent.Type.LOAD, nextLeg.getLoadLocation(), - nextLeg.getVoyage()); - } else { - return new HandlingActivity(HandlingEvent.Type.CLAIM, leg.getUnloadLocation()); - } - } - } - - return NO_ACTIVITY; - - case RECEIVE: - Leg firstLeg = itinerary.getLegs().iterator().next(); - - return new HandlingActivity(HandlingEvent.Type.LOAD, firstLeg.getLoadLocation(), firstLeg.getVoyage()); - - case CLAIM: - default: - return NO_ACTIVITY; - } - } - - private RoutingStatus calculateRoutingStatus(Itinerary itinerary, RouteSpecification routeSpecification) { - if (itinerary == null || itinerary == Itinerary.EMPTY_ITINERARY) { - return NOT_ROUTED; - } else { - if (routeSpecification.isSatisfiedBy(itinerary)) { - return ROUTED; - } else { - return MISROUTED; - } - } - } - - private boolean calculateUnloadedAtDestination(RouteSpecification routeSpecification) { - return lastEvent != null && HandlingEvent.Type.UNLOAD.sameValueAs(lastEvent.getType()) - && routeSpecification.getDestination().sameIdentityAs(lastEvent.getLocation()); - } - - private boolean onTrack() { - return routingStatus.equals(ROUTED) && !misdirected; - } - - private boolean sameValueAs(Delivery other) { - return other != null && new EqualsBuilder().append(this.transportStatus, other.transportStatus) - .append(this.lastKnownLocation, other.lastKnownLocation).append(this.currentVoyage, other.currentVoyage) - .append(this.misdirected, other.misdirected).append(this.eta, other.eta) - .append(this.nextExpectedActivity, other.nextExpectedActivity) - .append(this.isUnloadedAtDestination, other.isUnloadedAtDestination) - .append(this.routingStatus, other.routingStatus).append(this.calculatedAt, other.calculatedAt) - .append(this.lastEvent, other.lastEvent).isEquals(); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - Delivery other = (Delivery) o; - - return sameValueAs(other); - } - - @Override - public int hashCode() { - return new HashCodeBuilder().append(transportStatus).append(lastKnownLocation).append(currentVoyage) - .append(misdirected).append(eta).append(nextExpectedActivity).append(isUnloadedAtDestination) - .append(routingStatus).append(calculatedAt).append(lastEvent).toHashCode(); - } + private static final long serialVersionUID = 1L; + // Null object pattern. + public static final Date ETA_UNKOWN = null; + // Null object pattern + public static final HandlingActivity NO_ACTIVITY = new HandlingActivity(); + + @Enumerated(EnumType.STRING) + @Column(name = "transport_status") + @NotNull + private TransportStatus transportStatus; + + @ManyToOne + @JoinColumn(name = "last_known_location_id") + private Location lastKnownLocation; + + @ManyToOne + @JoinColumn(name = "current_voyage_id") + private Voyage currentVoyage; + + @NotNull private boolean misdirected; + + @Temporal(TemporalType.DATE) + private Date eta; + + @Embedded private HandlingActivity nextExpectedActivity; + + @Column(name = "unloaded_at_dest") + @NotNull + private boolean isUnloadedAtDestination; + + @Enumerated(EnumType.STRING) + @Column(name = "routing_status") + @NotNull + private RoutingStatus routingStatus; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name = "calculated_at") + @NotNull + private Date calculatedAt; + + @ManyToOne + @JoinColumn(name = "last_event_id") + private HandlingEvent lastEvent; + + public Delivery() { + // Nothing to initialize + } + + public Delivery( + HandlingEvent lastEvent, Itinerary itinerary, RouteSpecification routeSpecification) { + this.calculatedAt = new Date(); + this.lastEvent = lastEvent; + + this.misdirected = calculateMisdirectionStatus(itinerary); + this.routingStatus = calculateRoutingStatus(itinerary, routeSpecification); + this.transportStatus = calculateTransportStatus(); + this.lastKnownLocation = calculateLastKnownLocation(); + this.currentVoyage = calculateCurrentVoyage(); + this.eta = calculateEta(itinerary); + this.nextExpectedActivity = calculateNextExpectedActivity(routeSpecification, itinerary); + this.isUnloadedAtDestination = calculateUnloadedAtDestination(routeSpecification); + } + + /** + * Creates a new delivery snapshot to reflect changes in routing, i.e. when the route + * specification or the itinerary has changed but no additional handling of the cargo has been + * performed. + */ + Delivery updateOnRouting(RouteSpecification routeSpecification, Itinerary itinerary) { + Validate.notNull(routeSpecification, "Route specification is required"); + + return new Delivery(this.lastEvent, itinerary, routeSpecification); + } + + /** + * Creates a new delivery snapshot based on the complete handling history of a cargo, as well as + * its route specification and itinerary. + * + * @param routeSpecification route specification + * @param itinerary itinerary + * @param handlingHistory delivery history + * @return An up to date delivery. + */ + static Delivery derivedFrom( + RouteSpecification routeSpecification, Itinerary itinerary, HandlingHistory handlingHistory) { + Validate.notNull(routeSpecification, "Route specification is required"); + Validate.notNull(handlingHistory, "Delivery history is required"); + + HandlingEvent lastEvent = handlingHistory.getMostRecentlyCompletedEvent(); + + return new Delivery(lastEvent, itinerary, routeSpecification); + } + + public TransportStatus getTransportStatus() { + return transportStatus; + } + + public void setTransportStatus(TransportStatus transportStatus) { + this.transportStatus = transportStatus; + } + + public Location getLastKnownLocation() { + return DomainObjectUtils.nullSafe(lastKnownLocation, Location.UNKNOWN); + } + + public void setLastKnownLocation(Location lastKnownLocation) { + this.lastKnownLocation = lastKnownLocation; + } + + public void setLastEvent(HandlingEvent lastEvent) { + this.lastEvent = lastEvent; + } + + public Voyage getCurrentVoyage() { + return DomainObjectUtils.nullSafe(currentVoyage, Voyage.NONE); + } + + /** + * Check if cargo is misdirected. + * + *

+ * + *

+ * + * @return true if the cargo has been misdirected, + */ + public boolean isMisdirected() { + return misdirected; + } + + public void setMisdirected(boolean misdirected) { + this.misdirected = misdirected; + } + + public Date getEstimatedTimeOfArrival() { + if (eta != ETA_UNKOWN) { + return new Date(eta.getTime()); + } else { + return ETA_UNKOWN; + } + } + + public HandlingActivity getNextExpectedActivity() { + return nextExpectedActivity; + } + + /** @return True if the cargo has been unloaded at the final destination. */ + public boolean isUnloadedAtDestination() { + return isUnloadedAtDestination; + } + + public void setUnloadedAtDestination(boolean isUnloadedAtDestination) { + this.isUnloadedAtDestination = isUnloadedAtDestination; + } + + public RoutingStatus getRoutingStatus() { + return routingStatus; + } + + public void setRoutingStatus(RoutingStatus routingStatus) { + this.routingStatus = routingStatus; + } + + /** @return When this delivery was calculated. */ + public Date getCalculatedAt() { + return new Date(calculatedAt.getTime()); + } + + public void setCalculatedAt(Date calculatedAt) { + this.calculatedAt = calculatedAt; + } + + private TransportStatus calculateTransportStatus() { + if (lastEvent == null) { + return NOT_RECEIVED; + } + + switch (lastEvent.getType()) { + case LOAD: + return ONBOARD_CARRIER; + case UNLOAD: + case RECEIVE: + case CUSTOMS: + return IN_PORT; + case CLAIM: + return CLAIMED; + default: + return UNKNOWN; + } + } + + private Location calculateLastKnownLocation() { + if (lastEvent != null) { + return lastEvent.getLocation(); + } else { + return null; + } + } + + private Voyage calculateCurrentVoyage() { + if (getTransportStatus().equals(ONBOARD_CARRIER) && lastEvent != null) { + return lastEvent.getVoyage(); + } else { + return null; + } + } + + private boolean calculateMisdirectionStatus(Itinerary itinerary) { + if (lastEvent == null) { + return false; + } else { + return !itinerary.isExpected(lastEvent); + } + } + + private Date calculateEta(Itinerary itinerary) { + if (onTrack()) { + return itinerary.getFinalArrivalDate(); + } else { + return ETA_UNKOWN; + } + } + + private HandlingActivity calculateNextExpectedActivity( + RouteSpecification routeSpecification, Itinerary itinerary) { + if (!onTrack()) { + return NO_ACTIVITY; + } + + if (lastEvent == null) { + return new HandlingActivity(HandlingEvent.Type.RECEIVE, routeSpecification.getOrigin()); + } + + switch (lastEvent.getType()) { + case LOAD: + for (Leg leg : itinerary.getLegs()) { + if (leg.getLoadLocation().sameIdentityAs(lastEvent.getLocation())) { + return new HandlingActivity( + HandlingEvent.Type.UNLOAD, leg.getUnloadLocation(), leg.getVoyage()); + } + } + + return NO_ACTIVITY; + + case UNLOAD: + for (Iterator iterator = itinerary.getLegs().iterator(); iterator.hasNext(); ) { + Leg leg = iterator.next(); + + if (leg.getUnloadLocation().sameIdentityAs(lastEvent.getLocation())) { + if (iterator.hasNext()) { + Leg nextLeg = iterator.next(); + return new HandlingActivity( + HandlingEvent.Type.LOAD, nextLeg.getLoadLocation(), nextLeg.getVoyage()); + } else { + return new HandlingActivity(HandlingEvent.Type.CLAIM, leg.getUnloadLocation()); + } + } + } + + return NO_ACTIVITY; + + case RECEIVE: + Leg firstLeg = itinerary.getLegs().iterator().next(); + + return new HandlingActivity( + HandlingEvent.Type.LOAD, firstLeg.getLoadLocation(), firstLeg.getVoyage()); + + case CLAIM: + default: + return NO_ACTIVITY; + } + } + + private RoutingStatus calculateRoutingStatus( + Itinerary itinerary, RouteSpecification routeSpecification) { + if (itinerary == null || itinerary == Itinerary.EMPTY_ITINERARY) { + return NOT_ROUTED; + } else { + if (routeSpecification.isSatisfiedBy(itinerary)) { + return ROUTED; + } else { + return MISROUTED; + } + } + } + + private boolean calculateUnloadedAtDestination(RouteSpecification routeSpecification) { + return lastEvent != null + && HandlingEvent.Type.UNLOAD.sameValueAs(lastEvent.getType()) + && routeSpecification.getDestination().sameIdentityAs(lastEvent.getLocation()); + } + + private boolean onTrack() { + return routingStatus.equals(ROUTED) && !misdirected; + } + + private boolean sameValueAs(Delivery other) { + return other != null + && new EqualsBuilder() + .append(this.transportStatus, other.transportStatus) + .append(this.lastKnownLocation, other.lastKnownLocation) + .append(this.currentVoyage, other.currentVoyage) + .append(this.misdirected, other.misdirected) + .append(this.eta, other.eta) + .append(this.nextExpectedActivity, other.nextExpectedActivity) + .append(this.isUnloadedAtDestination, other.isUnloadedAtDestination) + .append(this.routingStatus, other.routingStatus) + .append(this.calculatedAt, other.calculatedAt) + .append(this.lastEvent, other.lastEvent) + .isEquals(); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + Delivery other = (Delivery) o; + + return sameValueAs(other); + } + + @Override + public int hashCode() { + return new HashCodeBuilder() + .append(transportStatus) + .append(lastKnownLocation) + .append(currentVoyage) + .append(misdirected) + .append(eta) + .append(nextExpectedActivity) + .append(isUnloadedAtDestination) + .append(routingStatus) + .append(calculatedAt) + .append(lastEvent) + .toHashCode(); + } } diff --git a/src/main/java/org/eclipse/cargotracker/domain/model/cargo/HandlingActivity.java b/src/main/java/org/eclipse/cargotracker/domain/model/cargo/HandlingActivity.java index 155509c8e..7d127d759 100644 --- a/src/main/java/org/eclipse/cargotracker/domain/model/cargo/HandlingActivity.java +++ b/src/main/java/org/eclipse/cargotracker/domain/model/cargo/HandlingActivity.java @@ -17,93 +17,102 @@ import org.eclipse.cargotracker.domain.model.voyage.Voyage; /** - * A handling activity represents how and where a cargo can be handled, and can - * be used to express predictions about what is expected to happen to a cargo in - * the future. + * A handling activity represents how and where a cargo can be handled, and can be used to express + * predictions about what is expected to happen to a cargo in the future. */ @Embeddable public class HandlingActivity implements Serializable { - private static final long serialVersionUID = 1L; - @Enumerated(EnumType.STRING) - @Column(name = "next_expected_handling_event_type") - private HandlingEvent.Type type; - @ManyToOne - @JoinColumn(name = "next_expected_location_id") - private Location location; - @ManyToOne - @JoinColumn(name = "next_expected_voyage_id") - private Voyage voyage; - - public HandlingActivity() { - } - - public HandlingActivity(HandlingEvent.Type type, Location location) { - Validate.notNull(type, "Handling event type is required"); - Validate.notNull(location, "Location is required"); - - this.type = type; - this.location = location; - } - - public HandlingActivity(HandlingEvent.Type type, Location location, Voyage voyage) { - Validate.notNull(type, "Handling event type is required"); - Validate.notNull(location, "Location is required"); - Validate.notNull(voyage, "Voyage is required"); - - this.type = type; - this.location = location; - this.voyage = voyage; - } - - public HandlingEvent.Type getType() { - return type; - } - - public Location getLocation() { - return location; - } - - public Voyage getVoyage() { - return voyage; - } - - private boolean sameValueAs(HandlingActivity other) { - return other != null && new EqualsBuilder().append(this.type, other.type).append(this.location, other.location) - .append(this.voyage, other.voyage).isEquals(); - } - - @Override - public int hashCode() { - return new HashCodeBuilder().append(this.type).append(this.location).append(this.voyage).toHashCode(); - } - - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - if (obj == null) { - return false; - } - if (obj.getClass() != this.getClass()) { - return false; - } - - HandlingActivity other = (HandlingActivity) obj; - - return sameValueAs(other); - } - - public boolean isEmpty() { - if (type != null) { - return false; - } - - if (location != null) { - return false; - } - - return voyage == null; - } + private static final long serialVersionUID = 1L; + + @Enumerated(EnumType.STRING) + @Column(name = "next_expected_handling_event_type") + private HandlingEvent.Type type; + + @ManyToOne + @JoinColumn(name = "next_expected_location_id") + private Location location; + + @ManyToOne + @JoinColumn(name = "next_expected_voyage_id") + private Voyage voyage; + + public HandlingActivity() {} + + public HandlingActivity(HandlingEvent.Type type, Location location) { + Validate.notNull(type, "Handling event type is required"); + Validate.notNull(location, "Location is required"); + + this.type = type; + this.location = location; + } + + public HandlingActivity(HandlingEvent.Type type, Location location, Voyage voyage) { + Validate.notNull(type, "Handling event type is required"); + Validate.notNull(location, "Location is required"); + Validate.notNull(voyage, "Voyage is required"); + + this.type = type; + this.location = location; + this.voyage = voyage; + } + + public HandlingEvent.Type getType() { + return type; + } + + public Location getLocation() { + return location; + } + + public Voyage getVoyage() { + return voyage; + } + + private boolean sameValueAs(HandlingActivity other) { + return other != null + && new EqualsBuilder() + .append(this.type, other.type) + .append(this.location, other.location) + .append(this.voyage, other.voyage) + .isEquals(); + } + + @Override + public int hashCode() { + return new HashCodeBuilder() + .append(this.type) + .append(this.location) + .append(this.voyage) + .toHashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (obj == null) { + return false; + } + if (obj.getClass() != this.getClass()) { + return false; + } + + HandlingActivity other = (HandlingActivity) obj; + + return sameValueAs(other); + } + + public boolean isEmpty() { + if (type != null) { + return false; + } + + if (location != null) { + return false; + } + + return voyage == null; + } } diff --git a/src/main/java/org/eclipse/cargotracker/domain/model/cargo/Itinerary.java b/src/main/java/org/eclipse/cargotracker/domain/model/cargo/Itinerary.java index fa201dafe..3042e54f9 100644 --- a/src/main/java/org/eclipse/cargotracker/domain/model/cargo/Itinerary.java +++ b/src/main/java/org/eclipse/cargotracker/domain/model/cargo/Itinerary.java @@ -20,155 +20,156 @@ @Embeddable public class Itinerary implements Serializable { - private static final long serialVersionUID = 1L; - - private static final Date END_OF_DAYS = new Date(Long.MAX_VALUE); - // Null object pattern. - public static final Itinerary EMPTY_ITINERARY = new Itinerary(); - - // TODO [Clean Code] Look into why cascade delete doesn't work. - @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true) - @JoinColumn(name = "cargo_id") - // TODO [Clean Code] Index this is in leg_index - @OrderBy("loadTime") - @PrivateOwned - @Size(min = 1) - private List legs = Collections.emptyList(); - - public Itinerary() { - // Nothing to initialize. - } - - public Itinerary(List legs) { - Validate.notEmpty(legs); - Validate.noNullElements(legs); - - this.legs = legs; - } - - public List getLegs() { - return Collections.unmodifiableList(legs); - } - - /** - * Test if the given handling event is expected when executing this itinerary. - */ - public boolean isExpected(HandlingEvent event) { - if (legs.isEmpty()) { - return true; - } - - switch (event.getType()) { - case RECEIVE: { - // Check that the first leg's origin is the event's location - Leg leg = legs.get(0); - return (leg.getLoadLocation().equals(event.getLocation())); - } - - case LOAD: { - for (Leg leg : legs) { - if (leg.getLoadLocation().equals(event.getLocation()) && leg.getVoyage().equals(event.getVoyage())) { - return true; - } - } - - return false; - } - - case UNLOAD: { - // Check that the there is one leg with same unload location and - // voyage - for (Leg leg : legs) { - if (leg.getUnloadLocation().equals(event.getLocation()) && leg.getVoyage().equals(event.getVoyage())) { - return true; - } - } - - return false; - } - - case CLAIM: { - // Check that the last leg's destination is from the event's - // location - Leg leg = getLastLeg(); - - return (leg.getUnloadLocation().equals(event.getLocation())); - } - - case CUSTOMS: { - return true; - } - - default: - throw new RuntimeException("Event case is not handled"); - } - } - - Location getInitialDepartureLocation() { - if (legs.isEmpty()) { - return Location.UNKNOWN; - } else { - return legs.get(0).getLoadLocation(); - } - } - - Location getFinalArrivalLocation() { - if (legs.isEmpty()) { - return Location.UNKNOWN; - } else { - return getLastLeg().getUnloadLocation(); - } - } - - /** - * @return Date when cargo arrives at final destination. - */ - Date getFinalArrivalDate() { - Leg lastLeg = getLastLeg(); - - if (lastLeg == null) { - return new Date(END_OF_DAYS.getTime()); - } else { - return new Date(lastLeg.getUnloadTime().getTime()); - } - } - - /** - * @return The last leg on the itinerary. - */ - Leg getLastLeg() { - if (legs.isEmpty()) { - return null; - } else { - return legs.get(legs.size() - 1); - } - } - - private boolean sameValueAs(Itinerary other) { - return other != null && legs.equals(other.legs); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - Itinerary itinerary = (Itinerary) o; - - return sameValueAs(itinerary); - } - - @Override - public int hashCode() { - return legs.hashCode(); - } - - @Override - public String toString() { - return "Itinerary{" + "legs=" + legs + '}'; - } + private static final long serialVersionUID = 1L; + + private static final Date END_OF_DAYS = new Date(Long.MAX_VALUE); + // Null object pattern. + public static final Itinerary EMPTY_ITINERARY = new Itinerary(); + + // TODO [Clean Code] Look into why cascade delete doesn't work. + @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true) + @JoinColumn(name = "cargo_id") + // TODO [Clean Code] Index this is in leg_index + @OrderBy("loadTime") + @PrivateOwned + @Size(min = 1) + private List legs = Collections.emptyList(); + + public Itinerary() { + // Nothing to initialize. + } + + public Itinerary(List legs) { + Validate.notEmpty(legs); + Validate.noNullElements(legs); + + this.legs = legs; + } + + public List getLegs() { + return Collections.unmodifiableList(legs); + } + + /** Test if the given handling event is expected when executing this itinerary. */ + public boolean isExpected(HandlingEvent event) { + if (legs.isEmpty()) { + return true; + } + + switch (event.getType()) { + case RECEIVE: + { + // Check that the first leg's origin is the event's location + Leg leg = legs.get(0); + return (leg.getLoadLocation().equals(event.getLocation())); + } + + case LOAD: + { + for (Leg leg : legs) { + if (leg.getLoadLocation().equals(event.getLocation()) + && leg.getVoyage().equals(event.getVoyage())) { + return true; + } + } + + return false; + } + + case UNLOAD: + { + // Check that the there is one leg with same unload location and + // voyage + for (Leg leg : legs) { + if (leg.getUnloadLocation().equals(event.getLocation()) + && leg.getVoyage().equals(event.getVoyage())) { + return true; + } + } + + return false; + } + + case CLAIM: + { + // Check that the last leg's destination is from the event's + // location + Leg leg = getLastLeg(); + + return (leg.getUnloadLocation().equals(event.getLocation())); + } + + case CUSTOMS: + { + return true; + } + + default: + throw new RuntimeException("Event case is not handled"); + } + } + + Location getInitialDepartureLocation() { + if (legs.isEmpty()) { + return Location.UNKNOWN; + } else { + return legs.get(0).getLoadLocation(); + } + } + + Location getFinalArrivalLocation() { + if (legs.isEmpty()) { + return Location.UNKNOWN; + } else { + return getLastLeg().getUnloadLocation(); + } + } + + /** @return Date when cargo arrives at final destination. */ + Date getFinalArrivalDate() { + Leg lastLeg = getLastLeg(); + + if (lastLeg == null) { + return new Date(END_OF_DAYS.getTime()); + } else { + return new Date(lastLeg.getUnloadTime().getTime()); + } + } + + /** @return The last leg on the itinerary. */ + Leg getLastLeg() { + if (legs.isEmpty()) { + return null; + } else { + return legs.get(legs.size() - 1); + } + } + + private boolean sameValueAs(Itinerary other) { + return other != null && legs.equals(other.legs); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + Itinerary itinerary = (Itinerary) o; + + return sameValueAs(itinerary); + } + + @Override + public int hashCode() { + return legs.hashCode(); + } + + @Override + public String toString() { + return "Itinerary{" + "legs=" + legs + '}'; + } } diff --git a/src/main/java/org/eclipse/cargotracker/domain/model/cargo/Leg.java b/src/main/java/org/eclipse/cargotracker/domain/model/cargo/Leg.java index a1fea44b3..1dc025567 100644 --- a/src/main/java/org/eclipse/cargotracker/domain/model/cargo/Leg.java +++ b/src/main/java/org/eclipse/cargotracker/domain/model/cargo/Leg.java @@ -22,94 +22,125 @@ @Entity public class Leg implements Serializable { - private static final long serialVersionUID = 1L; - @Id - @GeneratedValue - private Long id; - @ManyToOne - @JoinColumn(name = "voyage_id") - @NotNull - private Voyage voyage; - @ManyToOne - @JoinColumn(name = "load_location_id") - @NotNull - private Location loadLocation; - @ManyToOne - @JoinColumn(name = "unload_location_id") - @NotNull - private Location unloadLocation; - @Temporal(TemporalType.TIMESTAMP) - @Column(name = "load_time") - @NotNull - private Date loadTime; - @Temporal(TemporalType.TIMESTAMP) - @Column(name = "unload_time") - @NotNull - private Date unloadTime; - - public Leg() { - // Nothing to initialize. - } - - public Leg(Voyage voyage, Location loadLocation, Location unloadLocation, Date loadTime, Date unloadTime) { - Validate.noNullElements(new Object[] { voyage, loadLocation, unloadLocation, loadTime, unloadTime }); - - this.voyage = voyage; - this.loadLocation = loadLocation; - this.unloadLocation = unloadLocation; - this.loadTime = loadTime; - this.unloadTime = unloadTime; - } - - public Voyage getVoyage() { - return voyage; - } - - public Location getLoadLocation() { - return loadLocation; - } - - public Location getUnloadLocation() { - return unloadLocation; - } - - public Date getLoadTime() { - return new Date(loadTime.getTime()); - } - - public Date getUnloadTime() { - return new Date(unloadTime.getTime()); - } - - private boolean sameValueAs(Leg other) { - return other != null && new EqualsBuilder().append(this.voyage, other.voyage) - .append(this.loadLocation, other.loadLocation).append(this.unloadLocation, other.unloadLocation) - .append(this.loadTime, other.loadTime).append(this.unloadTime, other.unloadTime).isEquals(); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - Leg leg = (Leg) o; - - return sameValueAs(leg); - } - - @Override - public int hashCode() { - return new HashCodeBuilder().append(voyage).append(loadLocation).append(unloadLocation).append(loadTime) - .append(unloadTime).toHashCode(); - } - - @Override - public String toString() { - return "Leg{" + "id=" + id + ", voyage=" + voyage + ", loadLocation=" + loadLocation + ", unloadLocation=" - + unloadLocation + ", loadTime=" + loadTime + ", unloadTime=" + unloadTime + '}'; - } + private static final long serialVersionUID = 1L; + @Id @GeneratedValue private Long id; + + @ManyToOne + @JoinColumn(name = "voyage_id") + @NotNull + private Voyage voyage; + + @ManyToOne + @JoinColumn(name = "load_location_id") + @NotNull + private Location loadLocation; + + @ManyToOne + @JoinColumn(name = "unload_location_id") + @NotNull + private Location unloadLocation; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name = "load_time") + @NotNull + private Date loadTime; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name = "unload_time") + @NotNull + private Date unloadTime; + + public Leg() { + // Nothing to initialize. + } + + public Leg( + Voyage voyage, + Location loadLocation, + Location unloadLocation, + Date loadTime, + Date unloadTime) { + Validate.noNullElements( + new Object[] {voyage, loadLocation, unloadLocation, loadTime, unloadTime}); + + this.voyage = voyage; + this.loadLocation = loadLocation; + this.unloadLocation = unloadLocation; + this.loadTime = loadTime; + this.unloadTime = unloadTime; + } + + public Voyage getVoyage() { + return voyage; + } + + public Location getLoadLocation() { + return loadLocation; + } + + public Location getUnloadLocation() { + return unloadLocation; + } + + public Date getLoadTime() { + return new Date(loadTime.getTime()); + } + + public Date getUnloadTime() { + return new Date(unloadTime.getTime()); + } + + private boolean sameValueAs(Leg other) { + return other != null + && new EqualsBuilder() + .append(this.voyage, other.voyage) + .append(this.loadLocation, other.loadLocation) + .append(this.unloadLocation, other.unloadLocation) + .append(this.loadTime, other.loadTime) + .append(this.unloadTime, other.unloadTime) + .isEquals(); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + Leg leg = (Leg) o; + + return sameValueAs(leg); + } + + @Override + public int hashCode() { + return new HashCodeBuilder() + .append(voyage) + .append(loadLocation) + .append(unloadLocation) + .append(loadTime) + .append(unloadTime) + .toHashCode(); + } + + @Override + public String toString() { + return "Leg{" + + "id=" + + id + + ", voyage=" + + voyage + + ", loadLocation=" + + loadLocation + + ", unloadLocation=" + + unloadLocation + + ", loadTime=" + + loadTime + + ", unloadTime=" + + unloadTime + + '}'; + } } diff --git a/src/main/java/org/eclipse/cargotracker/domain/model/cargo/RouteSpecification.java b/src/main/java/org/eclipse/cargotracker/domain/model/cargo/RouteSpecification.java index bb2122f03..adbccc02f 100644 --- a/src/main/java/org/eclipse/cargotracker/domain/model/cargo/RouteSpecification.java +++ b/src/main/java/org/eclipse/cargotracker/domain/model/cargo/RouteSpecification.java @@ -18,85 +18,94 @@ import org.eclipse.cargotracker.domain.shared.AbstractSpecification; /** - * Route specification. Describes where a cargo origin and destination is, and - * the arrival deadline. + * Route specification. Describes where a cargo origin and destination is, and the arrival deadline. */ @Embeddable public class RouteSpecification extends AbstractSpecification implements Serializable { - private static final long serialVersionUID = 1L; - @ManyToOne - @JoinColumn(name = "spec_origin_id", updatable = false) - private Location origin; - @ManyToOne - @JoinColumn(name = "spec_destination_id") - private Location destination; - @Temporal(TemporalType.DATE) - @Column(name = "spec_arrival_deadline") - @NotNull - private Date arrivalDeadline; - - public RouteSpecification() { - } - - /** - * @param origin origin location - can't be the same as the destination - * @param destination destination location - can't be the same as the origin - * @param arrivalDeadline arrival deadline - */ - public RouteSpecification(Location origin, Location destination, Date arrivalDeadline) { - Validate.notNull(origin, "Origin is required"); - Validate.notNull(destination, "Destination is required"); - Validate.notNull(arrivalDeadline, "Arrival deadline is required"); - Validate.isTrue(!origin.sameIdentityAs(destination), "Origin and destination can't be the same: " + origin); - - this.origin = origin; - this.destination = destination; - this.arrivalDeadline = (Date) arrivalDeadline.clone(); - } - - public Location getOrigin() { - return origin; - } - - public Location getDestination() { - return destination; - } - - public Date getArrivalDeadline() { - return new Date(arrivalDeadline.getTime()); - } - - @Override - public boolean isSatisfiedBy(Itinerary itinerary) { - return itinerary != null && getOrigin().sameIdentityAs(itinerary.getInitialDepartureLocation()) - && getDestination().sameIdentityAs(itinerary.getFinalArrivalLocation()) - && getArrivalDeadline().after(itinerary.getFinalArrivalDate()); - } - - private boolean sameValueAs(RouteSpecification other) { - return other != null - && new EqualsBuilder().append(this.origin, other.origin).append(this.destination, other.destination) - .append(this.arrivalDeadline, other.arrivalDeadline).isEquals(); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - RouteSpecification that = (RouteSpecification) o; - - return sameValueAs(that); - } - - @Override - public int hashCode() { - return new HashCodeBuilder().append(this.origin).append(this.destination).append(this.arrivalDeadline) - .toHashCode(); - } + private static final long serialVersionUID = 1L; + + @ManyToOne + @JoinColumn(name = "spec_origin_id", updatable = false) + private Location origin; + + @ManyToOne + @JoinColumn(name = "spec_destination_id") + private Location destination; + + @Temporal(TemporalType.DATE) + @Column(name = "spec_arrival_deadline") + @NotNull + private Date arrivalDeadline; + + public RouteSpecification() {} + + /** + * @param origin origin location - can't be the same as the destination + * @param destination destination location - can't be the same as the origin + * @param arrivalDeadline arrival deadline + */ + public RouteSpecification(Location origin, Location destination, Date arrivalDeadline) { + Validate.notNull(origin, "Origin is required"); + Validate.notNull(destination, "Destination is required"); + Validate.notNull(arrivalDeadline, "Arrival deadline is required"); + Validate.isTrue( + !origin.sameIdentityAs(destination), "Origin and destination can't be the same: " + origin); + + this.origin = origin; + this.destination = destination; + this.arrivalDeadline = (Date) arrivalDeadline.clone(); + } + + public Location getOrigin() { + return origin; + } + + public Location getDestination() { + return destination; + } + + public Date getArrivalDeadline() { + return new Date(arrivalDeadline.getTime()); + } + + @Override + public boolean isSatisfiedBy(Itinerary itinerary) { + return itinerary != null + && getOrigin().sameIdentityAs(itinerary.getInitialDepartureLocation()) + && getDestination().sameIdentityAs(itinerary.getFinalArrivalLocation()) + && getArrivalDeadline().after(itinerary.getFinalArrivalDate()); + } + + private boolean sameValueAs(RouteSpecification other) { + return other != null + && new EqualsBuilder() + .append(this.origin, other.origin) + .append(this.destination, other.destination) + .append(this.arrivalDeadline, other.arrivalDeadline) + .isEquals(); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + RouteSpecification that = (RouteSpecification) o; + + return sameValueAs(that); + } + + @Override + public int hashCode() { + return new HashCodeBuilder() + .append(this.origin) + .append(this.destination) + .append(this.arrivalDeadline) + .toHashCode(); + } } diff --git a/src/main/java/org/eclipse/cargotracker/domain/model/cargo/RoutingStatus.java b/src/main/java/org/eclipse/cargotracker/domain/model/cargo/RoutingStatus.java index 6f1679dc4..1cb2c4db6 100644 --- a/src/main/java/org/eclipse/cargotracker/domain/model/cargo/RoutingStatus.java +++ b/src/main/java/org/eclipse/cargotracker/domain/model/cargo/RoutingStatus.java @@ -1,10 +1,11 @@ package org.eclipse.cargotracker.domain.model.cargo; public enum RoutingStatus { + NOT_ROUTED, + ROUTED, + MISROUTED; - NOT_ROUTED, ROUTED, MISROUTED; - - public boolean sameValueAs(RoutingStatus other) { - return this.equals(other); - } + public boolean sameValueAs(RoutingStatus other) { + return this.equals(other); + } } diff --git a/src/main/java/org/eclipse/cargotracker/domain/model/cargo/TrackingId.java b/src/main/java/org/eclipse/cargotracker/domain/model/cargo/TrackingId.java index fe4b9a1e5..e2e51e19c 100644 --- a/src/main/java/org/eclipse/cargotracker/domain/model/cargo/TrackingId.java +++ b/src/main/java/org/eclipse/cargotracker/domain/model/cargo/TrackingId.java @@ -7,55 +7,51 @@ import org.apache.commons.lang3.Validate; -/** - * Uniquely identifies a particular cargo. Automatically generated by the - * application. - */ +/** Uniquely identifies a particular cargo. Automatically generated by the application. */ @Embeddable public class TrackingId implements Serializable { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - @Column(name = "tracking_id", unique = true, updatable = false) - private String id; + @Column(name = "tracking_id", unique = true, updatable = false) + private String id; - public TrackingId() { - } + public TrackingId() {} - public TrackingId(String id) { - Validate.notNull(id); - this.id = id; - } + public TrackingId(String id) { + Validate.notNull(id); + this.id = id; + } - public String getIdString() { - return id; - } + public String getIdString() { + return id; + } - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } - TrackingId other = (TrackingId) o; + TrackingId other = (TrackingId) o; - return sameValueAs(other); - } + return sameValueAs(other); + } - @Override - public int hashCode() { - return id.hashCode(); - } + @Override + public int hashCode() { + return id.hashCode(); + } - boolean sameValueAs(TrackingId other) { - return other != null && this.id.equals(other.id); - } + boolean sameValueAs(TrackingId other) { + return other != null && this.id.equals(other.id); + } - @Override - public String toString() { - return id; - } + @Override + public String toString() { + return id; + } } diff --git a/src/main/java/org/eclipse/cargotracker/domain/model/cargo/TransportStatus.java b/src/main/java/org/eclipse/cargotracker/domain/model/cargo/TransportStatus.java index 8dafd3c98..28264c66d 100644 --- a/src/main/java/org/eclipse/cargotracker/domain/model/cargo/TransportStatus.java +++ b/src/main/java/org/eclipse/cargotracker/domain/model/cargo/TransportStatus.java @@ -1,10 +1,13 @@ package org.eclipse.cargotracker.domain.model.cargo; public enum TransportStatus { + NOT_RECEIVED, + IN_PORT, + ONBOARD_CARRIER, + CLAIMED, + UNKNOWN; - NOT_RECEIVED, IN_PORT, ONBOARD_CARRIER, CLAIMED, UNKNOWN; - - public boolean sameValueAs(TransportStatus other) { - return this.equals(other); - } + public boolean sameValueAs(TransportStatus other) { + return this.equals(other); + } } diff --git a/src/main/java/org/eclipse/cargotracker/domain/package.html b/src/main/java/org/eclipse/cargotracker/domain/package.html index a7086b898..dfba81c2c 100644 --- a/src/main/java/org/eclipse/cargotracker/domain/package.html +++ b/src/main/java/org/eclipse/cargotracker/domain/package.html @@ -5,9 +5,9 @@ in classes, interfaces and method signatures, and every concept in here is familiar to a expert in the cargo shipping domain.

There is no infrastructure or user interface related code here, - except for things like transactional, validation and security metadata which is - likely to be relevant to a domain expert ("Either all of foo succeeds - or none of it does", "In order to do bar you need to be a Supervisor", - and so on).

+ except for things like transactional, validation and security metadata + which is likely to be relevant to a domain expert ("Either all of foo + succeeds or none of it does", "In order to do bar you need to be a + Supervisor", and so on).

From 92e9d16c559f804a03c51cb9edf0f54f33af47ef Mon Sep 17 00:00:00 2001 From: Reza Rahman Date: Sun, 17 Jan 2021 09:33:43 -0500 Subject: [PATCH 03/22] Apply Google Java Code Style --- .../CannotCreateHandlingEventException.java | 21 +- .../domain/model/handling/HandlingEvent.java | 492 ++++++++++-------- .../model/handling/HandlingEventFactory.java | 149 +++--- .../handling/HandlingEventRepository.java | 4 +- .../model/handling/HandlingHistory.java | 133 +++-- .../model/handling/UnknownCargoException.java | 30 +- .../handling/UnknownLocationException.java | 18 +- .../handling/UnknownVoyageException.java | 22 +- .../domain/model/location/Location.java | 164 +++--- .../model/location/LocationRepository.java | 4 +- .../model/location/SampleLocations.java | 31 +- .../domain/model/location/UnLocode.java | 122 +++-- 12 files changed, 603 insertions(+), 587 deletions(-) diff --git a/src/main/java/org/eclipse/cargotracker/domain/model/handling/CannotCreateHandlingEventException.java b/src/main/java/org/eclipse/cargotracker/domain/model/handling/CannotCreateHandlingEventException.java index 456005d64..2a40f665c 100644 --- a/src/main/java/org/eclipse/cargotracker/domain/model/handling/CannotCreateHandlingEventException.java +++ b/src/main/java/org/eclipse/cargotracker/domain/model/handling/CannotCreateHandlingEventException.java @@ -4,21 +4,20 @@ /** * If a {@link HandlingEvent} can't be created from a given set of parameters. - *

- * It is a checked exception because it's not a programming error, but rather a - * special case that the application is built to handle. It can occur during - * normal program execution. + * + *

It is a checked exception because it's not a programming error, but rather a special case that + * the application is built to handle. It can occur during normal program execution. */ @ApplicationException(rollback = true) public class CannotCreateHandlingEventException extends Exception { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - public CannotCreateHandlingEventException(Exception e) { - super(e); - } + public CannotCreateHandlingEventException(Exception e) { + super(e); + } - public CannotCreateHandlingEventException() { - super(); - } + public CannotCreateHandlingEventException() { + super(); + } } diff --git a/src/main/java/org/eclipse/cargotracker/domain/model/handling/HandlingEvent.java b/src/main/java/org/eclipse/cargotracker/domain/model/handling/HandlingEvent.java index 8bb93e08a..3752da939 100644 --- a/src/main/java/org/eclipse/cargotracker/domain/model/handling/HandlingEvent.java +++ b/src/main/java/org/eclipse/cargotracker/domain/model/handling/HandlingEvent.java @@ -27,236 +27,272 @@ import org.eclipse.cargotracker.domain.shared.DomainObjectUtils; /** - * A HandlingEvent is used to register the event when, for instance, a cargo is - * unloaded from a carrier at a some location at a given time. - *

- * The HandlingEvent's are sent from different Incident Logging Applications - * some time after the event occurred and contain information about the null - * {@link TrackingId}, {@link Location}, time stamp of the completion of the - * event, and possibly, if applicable a {@link Voyage}. - *

- * This class is the only member, and consequently the root, of the - * HandlingEvent aggregate. - *

- * HandlingEvent's could contain information about a {@link Voyage} and if so, - * the event type must be either {@link Type#LOAD} or {@link Type#UNLOAD}. - *

- * All other events must be of {@link Type#RECEIVE}, {@link Type#CLAIM} or - * {@link Type#CUSTOMS}. + * A HandlingEvent is used to register the event when, for instance, a cargo is unloaded from a + * carrier at a some location at a given time. + * + *

The HandlingEvent's are sent from different Incident Logging Applications some time after the + * event occurred and contain information about the null {@link TrackingId}, {@link Location}, time + * stamp of the completion of the event, and possibly, if applicable a {@link Voyage}. + * + *

This class is the only member, and consequently the root, of the HandlingEvent aggregate. + * + *

HandlingEvent's could contain information about a {@link Voyage} and if so, the event type + * must be either {@link Type#LOAD} or {@link Type#UNLOAD}. + * + *

All other events must be of {@link Type#RECEIVE}, {@link Type#CLAIM} or {@link Type#CUSTOMS}. */ @Entity -@NamedQuery(name = "HandlingEvent.findByTrackingId", query = "Select e from HandlingEvent e where e.cargo.trackingId = :trackingId") +@NamedQuery( + name = "HandlingEvent.findByTrackingId", + query = "Select e from HandlingEvent e where e.cargo.trackingId = :trackingId") public class HandlingEvent implements Serializable { - private static final long serialVersionUID = 1L; - @Id - @GeneratedValue - private Long id; - @Enumerated(EnumType.STRING) - @NotNull - private Type type; - @ManyToOne - @JoinColumn(name = "voyage_id") - private Voyage voyage; - @ManyToOne - @JoinColumn(name = "location_id") - @NotNull - private Location location; - @Temporal(TemporalType.DATE) - @NotNull - @Column(name = "completionTime") - private Date completionTime; - @Temporal(TemporalType.DATE) - @NotNull - @Column(name = "registration") - private Date registrationTime; - @ManyToOne - @JoinColumn(name = "cargo_id") - @NotNull - private Cargo cargo; - @Transient - private String summary; - - /** - * Handling event type. Either requires or prohibits a carrier movement - * association, it's never optional. - */ - public enum Type { - - // Loaded onto voyage from port location. - LOAD(true), - // Unloaded from voyage to port location - UNLOAD(true), - // Received by carrier - RECEIVE(false), - // Cargo claimed by recepient - CLAIM(false), - // Cargo went through customs - CUSTOMS(false); - - private final boolean voyageRequired; - - /** - * Private enum constructor. - * - * @param voyageRequired whether or not a voyage is associated with this event - * type - */ - private Type(boolean voyageRequired) { - this.voyageRequired = voyageRequired; - } - - /** - * @return True if a voyage association is required for this event type. - */ - public boolean requiresVoyage() { - return voyageRequired; - } - - /** - * @return True if a voyage association is prohibited for this event type. - */ - public boolean prohibitsVoyage() { - return !requiresVoyage(); - } - - public boolean sameValueAs(Type other) { - return other != null && this.equals(other); - } - } - - public HandlingEvent() { - // Nothing to initialize. - } - - /** - * @param cargo The cargo - * @param completionTime completion time, the reported time that the event - * actually happened (e.g. the receive took place). - * @param registrationTime registration time, the time the message is received - * @param type type of event - * @param location where the event took place - * @param voyage the voyage - */ - public HandlingEvent(Cargo cargo, Date completionTime, Date registrationTime, Type type, Location location, - Voyage voyage) { - Validate.notNull(cargo, "Cargo is required"); - Validate.notNull(completionTime, "Completion time is required"); - Validate.notNull(registrationTime, "Registration time is required"); - Validate.notNull(type, "Handling event type is required"); - Validate.notNull(location, "Location is required"); - Validate.notNull(voyage, "Voyage is required"); - - if (type.prohibitsVoyage()) { - throw new IllegalArgumentException("Voyage is not allowed with event type " + type); - } - - this.voyage = voyage; - this.completionTime = (Date) completionTime.clone(); - this.registrationTime = (Date) registrationTime.clone(); - this.type = type; - this.location = location; - this.cargo = cargo; - } - - /** - * @param cargo cargo - * @param completionTime completion time, the reported time that the event - * actually happened (e.g. the receive took place). - * @param registrationTime registration time, the time the message is received - * @param type type of event - * @param location where the event took place - */ - public HandlingEvent(Cargo cargo, Date completionTime, Date registrationTime, Type type, Location location) { - Validate.notNull(cargo, "Cargo is required"); - Validate.notNull(completionTime, "Completion time is required"); - Validate.notNull(registrationTime, "Registration time is required"); - Validate.notNull(type, "Handling event type is required"); - Validate.notNull(location, "Location is required"); - - if (type.requiresVoyage()) { - throw new IllegalArgumentException("Voyage is required for event type " + type); - } - - this.completionTime = (Date) completionTime.clone(); - this.registrationTime = (Date) registrationTime.clone(); - this.type = type; - this.location = location; - this.cargo = cargo; - this.voyage = null; - } - - public Type getType() { - return this.type; - } - - public Voyage getVoyage() { - return DomainObjectUtils.nullSafe(this.voyage, Voyage.NONE); - } - - public Date getCompletionTime() { - return new Date(this.completionTime.getTime()); - } - - public Date getRegistrationTime() { - return new Date(this.registrationTime.getTime()); - } - - public Location getLocation() { - return this.location; - } - - public Cargo getCargo() { - return this.cargo; - } - - public String getSummary() { - StringBuilder builder = new StringBuilder(location.getName()).append("\n").append(completionTime).append("\n") - .append("Type: ").append(type).append("\n").append("Reg.: ").append(registrationTime).append("\n"); - - if (voyage != null) { - builder.append("Voyage: ").append(voyage.getVoyageNumber()); - } - return builder.toString(); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - HandlingEvent event = (HandlingEvent) o; - - return sameEventAs(event); - } - - private boolean sameEventAs(HandlingEvent other) { - return other != null && new EqualsBuilder().append(this.cargo, other.cargo).append(this.voyage, other.voyage) - .append(this.completionTime, other.completionTime).append(this.location, other.location) - .append(this.type, other.type).isEquals(); - } - - @Override - public int hashCode() { - return new HashCodeBuilder().append(cargo).append(voyage).append(completionTime).append(location).append(type) - .toHashCode(); - } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder("\n--- Handling event ---\n").append("Cargo: ") - .append(cargo.getTrackingId()).append("\n").append("Type: ").append(type).append("\n") - .append("Location: ").append(location.getName()).append("\n").append("Completed on: ") - .append(completionTime).append("\n").append("Registered on: ").append(registrationTime).append("\n"); - - if (voyage != null) { - builder.append("Voyage: ").append(voyage.getVoyageNumber()).append("\n"); - } - - return builder.toString(); - } + private static final long serialVersionUID = 1L; + @Id @GeneratedValue private Long id; + + @Enumerated(EnumType.STRING) + @NotNull + private Type type; + + @ManyToOne + @JoinColumn(name = "voyage_id") + private Voyage voyage; + + @ManyToOne + @JoinColumn(name = "location_id") + @NotNull + private Location location; + + @Temporal(TemporalType.DATE) + @NotNull + @Column(name = "completionTime") + private Date completionTime; + + @Temporal(TemporalType.DATE) + @NotNull + @Column(name = "registration") + private Date registrationTime; + + @ManyToOne + @JoinColumn(name = "cargo_id") + @NotNull + private Cargo cargo; + + @Transient private String summary; + + /** + * Handling event type. Either requires or prohibits a carrier movement association, it's never + * optional. + */ + public enum Type { + + // Loaded onto voyage from port location. + LOAD(true), + // Unloaded from voyage to port location + UNLOAD(true), + // Received by carrier + RECEIVE(false), + // Cargo claimed by recepient + CLAIM(false), + // Cargo went through customs + CUSTOMS(false); + + private final boolean voyageRequired; + + /** + * Private enum constructor. + * + * @param voyageRequired whether or not a voyage is associated with this event type + */ + private Type(boolean voyageRequired) { + this.voyageRequired = voyageRequired; + } + + /** @return True if a voyage association is required for this event type. */ + public boolean requiresVoyage() { + return voyageRequired; + } + + /** @return True if a voyage association is prohibited for this event type. */ + public boolean prohibitsVoyage() { + return !requiresVoyage(); + } + + public boolean sameValueAs(Type other) { + return other != null && this.equals(other); + } + } + + public HandlingEvent() { + // Nothing to initialize. + } + + /** + * @param cargo The cargo + * @param completionTime completion time, the reported time that the event actually happened (e.g. + * the receive took place). + * @param registrationTime registration time, the time the message is received + * @param type type of event + * @param location where the event took place + * @param voyage the voyage + */ + public HandlingEvent( + Cargo cargo, + Date completionTime, + Date registrationTime, + Type type, + Location location, + Voyage voyage) { + Validate.notNull(cargo, "Cargo is required"); + Validate.notNull(completionTime, "Completion time is required"); + Validate.notNull(registrationTime, "Registration time is required"); + Validate.notNull(type, "Handling event type is required"); + Validate.notNull(location, "Location is required"); + Validate.notNull(voyage, "Voyage is required"); + + if (type.prohibitsVoyage()) { + throw new IllegalArgumentException("Voyage is not allowed with event type " + type); + } + + this.voyage = voyage; + this.completionTime = (Date) completionTime.clone(); + this.registrationTime = (Date) registrationTime.clone(); + this.type = type; + this.location = location; + this.cargo = cargo; + } + + /** + * @param cargo cargo + * @param completionTime completion time, the reported time that the event actually happened (e.g. + * the receive took place). + * @param registrationTime registration time, the time the message is received + * @param type type of event + * @param location where the event took place + */ + public HandlingEvent( + Cargo cargo, Date completionTime, Date registrationTime, Type type, Location location) { + Validate.notNull(cargo, "Cargo is required"); + Validate.notNull(completionTime, "Completion time is required"); + Validate.notNull(registrationTime, "Registration time is required"); + Validate.notNull(type, "Handling event type is required"); + Validate.notNull(location, "Location is required"); + + if (type.requiresVoyage()) { + throw new IllegalArgumentException("Voyage is required for event type " + type); + } + + this.completionTime = (Date) completionTime.clone(); + this.registrationTime = (Date) registrationTime.clone(); + this.type = type; + this.location = location; + this.cargo = cargo; + this.voyage = null; + } + + public Type getType() { + return this.type; + } + + public Voyage getVoyage() { + return DomainObjectUtils.nullSafe(this.voyage, Voyage.NONE); + } + + public Date getCompletionTime() { + return new Date(this.completionTime.getTime()); + } + + public Date getRegistrationTime() { + return new Date(this.registrationTime.getTime()); + } + + public Location getLocation() { + return this.location; + } + + public Cargo getCargo() { + return this.cargo; + } + + public String getSummary() { + StringBuilder builder = + new StringBuilder(location.getName()) + .append("\n") + .append(completionTime) + .append("\n") + .append("Type: ") + .append(type) + .append("\n") + .append("Reg.: ") + .append(registrationTime) + .append("\n"); + + if (voyage != null) { + builder.append("Voyage: ").append(voyage.getVoyageNumber()); + } + return builder.toString(); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + HandlingEvent event = (HandlingEvent) o; + + return sameEventAs(event); + } + + private boolean sameEventAs(HandlingEvent other) { + return other != null + && new EqualsBuilder() + .append(this.cargo, other.cargo) + .append(this.voyage, other.voyage) + .append(this.completionTime, other.completionTime) + .append(this.location, other.location) + .append(this.type, other.type) + .isEquals(); + } + + @Override + public int hashCode() { + return new HashCodeBuilder() + .append(cargo) + .append(voyage) + .append(completionTime) + .append(location) + .append(type) + .toHashCode(); + } + + @Override + public String toString() { + StringBuilder builder = + new StringBuilder("\n--- Handling event ---\n") + .append("Cargo: ") + .append(cargo.getTrackingId()) + .append("\n") + .append("Type: ") + .append(type) + .append("\n") + .append("Location: ") + .append(location.getName()) + .append("\n") + .append("Completed on: ") + .append(completionTime) + .append("\n") + .append("Registered on: ") + .append(registrationTime) + .append("\n"); + + if (voyage != null) { + builder.append("Voyage: ").append(voyage.getVoyageNumber()).append("\n"); + } + + return builder.toString(); + } } diff --git a/src/main/java/org/eclipse/cargotracker/domain/model/handling/HandlingEventFactory.java b/src/main/java/org/eclipse/cargotracker/domain/model/handling/HandlingEventFactory.java index c2b7d8600..f1b194697 100644 --- a/src/main/java/org/eclipse/cargotracker/domain/model/handling/HandlingEventFactory.java +++ b/src/main/java/org/eclipse/cargotracker/domain/model/handling/HandlingEventFactory.java @@ -19,78 +19,79 @@ @ApplicationScoped public class HandlingEventFactory implements Serializable { - private static final long serialVersionUID = 1L; - @Inject - private CargoRepository cargoRepository; - @Inject - private VoyageRepository voyageRepository; - @Inject - private LocationRepository locationRepository; - - /** - * @param registrationTime time when this event was received by the system - * @param completionTime when the event was completed, for example finished - * loading - * @param trackingId cargo tracking id - * @param voyageNumber voyage number - * @param unlocode United Nations Location Code for the location of the - * event - * @param type type of event - * @return A handling event. - * @throws UnknownVoyageException if there's no voyage with this number - * @throws UnknownCargoException if there's no cargo with this tracking id - * @throws UnknownLocationException if there's no location with this UN Locode - */ - // TODO [Clean Code] Look at the exception handling more seriously. - public HandlingEvent createHandlingEvent(Date registrationTime, Date completionTime, TrackingId trackingId, - VoyageNumber voyageNumber, UnLocode unlocode, HandlingEvent.Type type) - throws CannotCreateHandlingEventException { - Cargo cargo = findCargo(trackingId); - Voyage voyage = findVoyage(voyageNumber); - Location location = findLocation(unlocode); - - try { - if (voyage == null) { - return new HandlingEvent(cargo, completionTime, registrationTime, type, location); - } else { - return new HandlingEvent(cargo, completionTime, registrationTime, type, location, voyage); - } - } catch (Exception e) { - throw new CannotCreateHandlingEventException(e); - } - } - - private Cargo findCargo(TrackingId trackingId) throws UnknownCargoException { - Cargo cargo = cargoRepository.find(trackingId); - - if (cargo == null) { - throw new UnknownCargoException(trackingId); - } - - return cargo; - } - - private Voyage findVoyage(VoyageNumber voyageNumber) throws UnknownVoyageException { - if (voyageNumber == null) { - return null; - } - - Voyage voyage = voyageRepository.find(voyageNumber); - - if (voyage == null) { - throw new UnknownVoyageException(voyageNumber); - } - - return voyage; - } - - private Location findLocation(UnLocode unlocode) throws UnknownLocationException { - Location location = locationRepository.find(unlocode); - - if (location == null) { - throw new UnknownLocationException(unlocode); - } - - return location; - } + private static final long serialVersionUID = 1L; + + @Inject private CargoRepository cargoRepository; + @Inject private VoyageRepository voyageRepository; + @Inject private LocationRepository locationRepository; + + /** + * @param registrationTime time when this event was received by the system + * @param completionTime when the event was completed, for example finished loading + * @param trackingId cargo tracking id + * @param voyageNumber voyage number + * @param unlocode United Nations Location Code for the location of the event + * @param type type of event + * @return A handling event. + * @throws UnknownVoyageException if there's no voyage with this number + * @throws UnknownCargoException if there's no cargo with this tracking id + * @throws UnknownLocationException if there's no location with this UN Locode + */ + // TODO [Clean Code] Look at the exception handling more seriously. + public HandlingEvent createHandlingEvent( + Date registrationTime, + Date completionTime, + TrackingId trackingId, + VoyageNumber voyageNumber, + UnLocode unlocode, + HandlingEvent.Type type) + throws CannotCreateHandlingEventException { + Cargo cargo = findCargo(trackingId); + Voyage voyage = findVoyage(voyageNumber); + Location location = findLocation(unlocode); + + try { + if (voyage == null) { + return new HandlingEvent(cargo, completionTime, registrationTime, type, location); + } else { + return new HandlingEvent(cargo, completionTime, registrationTime, type, location, voyage); + } + } catch (Exception e) { + throw new CannotCreateHandlingEventException(e); + } + } + + private Cargo findCargo(TrackingId trackingId) throws UnknownCargoException { + Cargo cargo = cargoRepository.find(trackingId); + + if (cargo == null) { + throw new UnknownCargoException(trackingId); + } + + return cargo; + } + + private Voyage findVoyage(VoyageNumber voyageNumber) throws UnknownVoyageException { + if (voyageNumber == null) { + return null; + } + + Voyage voyage = voyageRepository.find(voyageNumber); + + if (voyage == null) { + throw new UnknownVoyageException(voyageNumber); + } + + return voyage; + } + + private Location findLocation(UnLocode unlocode) throws UnknownLocationException { + Location location = locationRepository.find(unlocode); + + if (location == null) { + throw new UnknownLocationException(unlocode); + } + + return location; + } } diff --git a/src/main/java/org/eclipse/cargotracker/domain/model/handling/HandlingEventRepository.java b/src/main/java/org/eclipse/cargotracker/domain/model/handling/HandlingEventRepository.java index ce4849763..55816fa21 100644 --- a/src/main/java/org/eclipse/cargotracker/domain/model/handling/HandlingEventRepository.java +++ b/src/main/java/org/eclipse/cargotracker/domain/model/handling/HandlingEventRepository.java @@ -4,7 +4,7 @@ public interface HandlingEventRepository { - void store(HandlingEvent event); + void store(HandlingEvent event); - HandlingHistory lookupHandlingHistoryOfCargo(TrackingId trackingId); + HandlingHistory lookupHandlingHistoryOfCargo(TrackingId trackingId); } diff --git a/src/main/java/org/eclipse/cargotracker/domain/model/handling/HandlingHistory.java b/src/main/java/org/eclipse/cargotracker/domain/model/handling/HandlingHistory.java index 9f3d32cba..dd1719418 100644 --- a/src/main/java/org/eclipse/cargotracker/domain/model/handling/HandlingHistory.java +++ b/src/main/java/org/eclipse/cargotracker/domain/model/handling/HandlingHistory.java @@ -11,71 +11,70 @@ public class HandlingHistory { - private final List handlingEvents; - // Null object pattern. - public static final HandlingHistory EMPTY = new HandlingHistory(Collections.emptyList()); - - public HandlingHistory(Collection handlingEvents) { - Validate.notNull(handlingEvents, "Handling events are required"); - - this.handlingEvents = new ArrayList<>(handlingEvents); - } - - public List getAllHandlingEvents() { - return handlingEvents; - } - - /** - * @return A distinct list (no duplicate registrations) of handling events, - * ordered by completion time. - */ - public List getDistinctEventsByCompletionTime() { - List ordered = new ArrayList<>(new HashSet<>(handlingEvents)); - Collections.sort(ordered, BY_COMPLETION_TIME_COMPARATOR); - - return Collections.unmodifiableList(ordered); - } - - /** - * @return Most recently completed event, or null if the delivery history is - * empty. - */ - public HandlingEvent getMostRecentlyCompletedEvent() { - List distinctEvents = getDistinctEventsByCompletionTime(); - - if (distinctEvents.isEmpty()) { - return null; - } else { - return distinctEvents.get(distinctEvents.size() - 1); - } - } - - private boolean sameValueAs(HandlingHistory other) { - return other != null && this.handlingEvents.equals(other.handlingEvents); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - HandlingHistory other = (HandlingHistory) o; - return sameValueAs(other); - } - - @Override - public int hashCode() { - return handlingEvents.hashCode(); - } - - private static final Comparator BY_COMPLETION_TIME_COMPARATOR = new Comparator() { - @Override - public int compare(HandlingEvent he1, HandlingEvent he2) { - return he1.getCompletionTime().compareTo(he2.getCompletionTime()); - } - }; + private final List handlingEvents; + // Null object pattern. + public static final HandlingHistory EMPTY = + new HandlingHistory(Collections.emptyList()); + + public HandlingHistory(Collection handlingEvents) { + Validate.notNull(handlingEvents, "Handling events are required"); + + this.handlingEvents = new ArrayList<>(handlingEvents); + } + + public List getAllHandlingEvents() { + return handlingEvents; + } + + /** + * @return A distinct list (no duplicate registrations) of handling events, ordered by completion + * time. + */ + public List getDistinctEventsByCompletionTime() { + List ordered = new ArrayList<>(new HashSet<>(handlingEvents)); + Collections.sort(ordered, BY_COMPLETION_TIME_COMPARATOR); + + return Collections.unmodifiableList(ordered); + } + + /** @return Most recently completed event, or null if the delivery history is empty. */ + public HandlingEvent getMostRecentlyCompletedEvent() { + List distinctEvents = getDistinctEventsByCompletionTime(); + + if (distinctEvents.isEmpty()) { + return null; + } else { + return distinctEvents.get(distinctEvents.size() - 1); + } + } + + private boolean sameValueAs(HandlingHistory other) { + return other != null && this.handlingEvents.equals(other.handlingEvents); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + HandlingHistory other = (HandlingHistory) o; + return sameValueAs(other); + } + + @Override + public int hashCode() { + return handlingEvents.hashCode(); + } + + private static final Comparator BY_COMPLETION_TIME_COMPARATOR = + new Comparator() { + @Override + public int compare(HandlingEvent he1, HandlingEvent he2) { + return he1.getCompletionTime().compareTo(he2.getCompletionTime()); + } + }; } diff --git a/src/main/java/org/eclipse/cargotracker/domain/model/handling/UnknownCargoException.java b/src/main/java/org/eclipse/cargotracker/domain/model/handling/UnknownCargoException.java index 1350de0e4..10d94295d 100644 --- a/src/main/java/org/eclipse/cargotracker/domain/model/handling/UnknownCargoException.java +++ b/src/main/java/org/eclipse/cargotracker/domain/model/handling/UnknownCargoException.java @@ -2,26 +2,20 @@ import org.eclipse.cargotracker.domain.model.cargo.TrackingId; -/** - * Thrown when trying to register an event with an unknown tracking id. - */ +/** Thrown when trying to register an event with an unknown tracking id. */ public class UnknownCargoException extends CannotCreateHandlingEventException { - private static final long serialVersionUID = 1L; - private final TrackingId trackingId; + private static final long serialVersionUID = 1L; + private final TrackingId trackingId; - /** - * @param trackingId cargo tracking id - */ - public UnknownCargoException(TrackingId trackingId) { - this.trackingId = trackingId; - } + /** @param trackingId cargo tracking id */ + public UnknownCargoException(TrackingId trackingId) { + this.trackingId = trackingId; + } - /** - * {@inheritDoc} - */ - @Override - public String getMessage() { - return "No cargo with tracking id " + trackingId.getIdString() + " exists in the system"; - } + /** {@inheritDoc} */ + @Override + public String getMessage() { + return "No cargo with tracking id " + trackingId.getIdString() + " exists in the system"; + } } diff --git a/src/main/java/org/eclipse/cargotracker/domain/model/handling/UnknownLocationException.java b/src/main/java/org/eclipse/cargotracker/domain/model/handling/UnknownLocationException.java index 1d2b34858..3fd60af25 100644 --- a/src/main/java/org/eclipse/cargotracker/domain/model/handling/UnknownLocationException.java +++ b/src/main/java/org/eclipse/cargotracker/domain/model/handling/UnknownLocationException.java @@ -4,15 +4,15 @@ public class UnknownLocationException extends CannotCreateHandlingEventException { - private static final long serialVersionUID = 1L; - private final UnLocode unlocode; + private static final long serialVersionUID = 1L; + private final UnLocode unlocode; - public UnknownLocationException(UnLocode unlocode) { - this.unlocode = unlocode; - } + public UnknownLocationException(UnLocode unlocode) { + this.unlocode = unlocode; + } - @Override - public String getMessage() { - return "No location with UN locode " + unlocode.getIdString() + " exists in the system"; - } + @Override + public String getMessage() { + return "No location with UN locode " + unlocode.getIdString() + " exists in the system"; + } } diff --git a/src/main/java/org/eclipse/cargotracker/domain/model/handling/UnknownVoyageException.java b/src/main/java/org/eclipse/cargotracker/domain/model/handling/UnknownVoyageException.java index 20805ad78..696f56af9 100644 --- a/src/main/java/org/eclipse/cargotracker/domain/model/handling/UnknownVoyageException.java +++ b/src/main/java/org/eclipse/cargotracker/domain/model/handling/UnknownVoyageException.java @@ -2,20 +2,18 @@ import org.eclipse.cargotracker.domain.model.voyage.VoyageNumber; -/** - * Thrown when trying to register an event with an unknown carrier movement id. - */ +/** Thrown when trying to register an event with an unknown carrier movement id. */ public class UnknownVoyageException extends CannotCreateHandlingEventException { - private static final long serialVersionUID = 1L; - private final VoyageNumber voyageNumber; + private static final long serialVersionUID = 1L; + private final VoyageNumber voyageNumber; - public UnknownVoyageException(VoyageNumber voyageNumber) { - this.voyageNumber = voyageNumber; - } + public UnknownVoyageException(VoyageNumber voyageNumber) { + this.voyageNumber = voyageNumber; + } - @Override - public String getMessage() { - return "No voyage with number " + voyageNumber.getIdString() + " exists in the system"; - } + @Override + public String getMessage() { + return "No voyage with number " + voyageNumber.getIdString() + " exists in the system"; + } } diff --git a/src/main/java/org/eclipse/cargotracker/domain/model/location/Location.java b/src/main/java/org/eclipse/cargotracker/domain/model/location/Location.java index 2b0cae0ff..1e76b4974 100644 --- a/src/main/java/org/eclipse/cargotracker/domain/model/location/Location.java +++ b/src/main/java/org/eclipse/cargotracker/domain/model/location/Location.java @@ -13,93 +13,87 @@ import org.apache.commons.lang3.Validate; /** - * A location in our model is stops on a journey, such as cargo origin or - * destination, or carrier movement end points. - *

- * It is uniquely identified by a UN location code. + * A location in our model is stops on a journey, such as cargo origin or destination, or carrier + * movement end points. + * + *

It is uniquely identified by a UN location code. */ @Entity -@NamedQueries({ @NamedQuery(name = "Location.findAll", query = "Select l from Location l"), - @NamedQuery(name = "Location.findByUnLocode", query = "Select l from Location l where l.unLocode = :unLocode") }) +@NamedQueries({ + @NamedQuery(name = "Location.findAll", query = "Select l from Location l"), + @NamedQuery( + name = "Location.findByUnLocode", + query = "Select l from Location l where l.unLocode = :unLocode") +}) public class Location implements Serializable { - private static final long serialVersionUID = 1L; - - // Special Location object that marks an unknown location. - public static final Location UNKNOWN = new Location(new UnLocode("XXXXX"), "Unknown location"); - - @Id - @GeneratedValue - private Long id; - @Embedded - private UnLocode unLocode; - @NotNull - private String name; - - public Location() { - // Nothing to do. - } - - /** - * @param unLocode UN Locode - * @param name Location name - * @throws IllegalArgumentException if the UN Locode or name is null - */ - public Location(UnLocode unLocode, String name) { - Validate.notNull(unLocode); - Validate.notNull(name); - - this.unLocode = unLocode; - this.name = name; - } - - /** - * @return UN location code for this location. - */ - public UnLocode getUnLocode() { - return unLocode; - } - - /** - * @return Actual name of this location, e.g. "Stockholm". - */ - public String getName() { - return name; - } - - /** - * @param object to compare - * @return Since this is an entiy this will be true iff UN locodes are equal. - */ - @Override - public boolean equals(Object object) { - if (object == null) { - return false; - } - if (this == object) { - return true; - } - if (!(object instanceof Location)) { - return false; - } - Location other = (Location) object; - return sameIdentityAs(other); - } - - public boolean sameIdentityAs(Location other) { - return this.unLocode.sameValueAs(other.unLocode); - } - - /** - * @return Hash code of UN locode. - */ - @Override - public int hashCode() { - return unLocode.hashCode(); - } - - @Override - public String toString() { - return name + " [" + unLocode + "]"; - } + private static final long serialVersionUID = 1L; + + // Special Location object that marks an unknown location. + public static final Location UNKNOWN = new Location(new UnLocode("XXXXX"), "Unknown location"); + + @Id @GeneratedValue private Long id; + @Embedded private UnLocode unLocode; + @NotNull private String name; + + public Location() { + // Nothing to do. + } + + /** + * @param unLocode UN Locode + * @param name Location name + * @throws IllegalArgumentException if the UN Locode or name is null + */ + public Location(UnLocode unLocode, String name) { + Validate.notNull(unLocode); + Validate.notNull(name); + + this.unLocode = unLocode; + this.name = name; + } + + /** @return UN location code for this location. */ + public UnLocode getUnLocode() { + return unLocode; + } + + /** @return Actual name of this location, e.g. "Stockholm". */ + public String getName() { + return name; + } + + /** + * @param object to compare + * @return Since this is an entiy this will be true iff UN locodes are equal. + */ + @Override + public boolean equals(Object object) { + if (object == null) { + return false; + } + if (this == object) { + return true; + } + if (!(object instanceof Location)) { + return false; + } + Location other = (Location) object; + return sameIdentityAs(other); + } + + public boolean sameIdentityAs(Location other) { + return this.unLocode.sameValueAs(other.unLocode); + } + + /** @return Hash code of UN locode. */ + @Override + public int hashCode() { + return unLocode.hashCode(); + } + + @Override + public String toString() { + return name + " [" + unLocode + "]"; + } } diff --git a/src/main/java/org/eclipse/cargotracker/domain/model/location/LocationRepository.java b/src/main/java/org/eclipse/cargotracker/domain/model/location/LocationRepository.java index b1094d61d..ac4dc25d4 100644 --- a/src/main/java/org/eclipse/cargotracker/domain/model/location/LocationRepository.java +++ b/src/main/java/org/eclipse/cargotracker/domain/model/location/LocationRepository.java @@ -4,7 +4,7 @@ public interface LocationRepository { - Location find(UnLocode unLocode); + Location find(UnLocode unLocode); - List findAll(); + List findAll(); } diff --git a/src/main/java/org/eclipse/cargotracker/domain/model/location/SampleLocations.java b/src/main/java/org/eclipse/cargotracker/domain/model/location/SampleLocations.java index 8e8bc9739..7f2cbbc22 100644 --- a/src/main/java/org/eclipse/cargotracker/domain/model/location/SampleLocations.java +++ b/src/main/java/org/eclipse/cargotracker/domain/model/location/SampleLocations.java @@ -1,22 +1,19 @@ package org.eclipse.cargotracker.domain.model.location; -/** - * Sample locations, for test purposes. - */ +/** Sample locations, for test purposes. */ public class SampleLocations { - public static final Location HONGKONG = new Location(new UnLocode("CNHKG"), "Hong Kong"); - public static final Location MELBOURNE = new Location(new UnLocode("AUMEL"), "Melbourne"); - public static final Location STOCKHOLM = new Location(new UnLocode("SESTO"), "Stockholm"); - public static final Location HELSINKI = new Location(new UnLocode("FIHEL"), "Helsinki"); - public static final Location CHICAGO = new Location(new UnLocode("USCHI"), "Chicago"); - public static final Location TOKYO = new Location(new UnLocode("JNTKO"), "Tokyo"); - public static final Location HAMBURG = new Location(new UnLocode("DEHAM"), "Hamburg"); - public static final Location SHANGHAI = new Location(new UnLocode("CNSHA"), "Shanghai"); - public static final Location ROTTERDAM = new Location(new UnLocode("NLRTM"), "Rotterdam"); - public static final Location GOTHENBURG = new Location(new UnLocode("SEGOT"), "Gothenburg"); - public static final Location HANGZOU = new Location(new UnLocode("CNHGH"), "Hangzhou"); - public static final Location NEWYORK = new Location(new UnLocode("USNYC"), "New York"); - public static final Location DALLAS = new Location(new UnLocode("USDAL"), "Dallas"); - + public static final Location HONGKONG = new Location(new UnLocode("CNHKG"), "Hong Kong"); + public static final Location MELBOURNE = new Location(new UnLocode("AUMEL"), "Melbourne"); + public static final Location STOCKHOLM = new Location(new UnLocode("SESTO"), "Stockholm"); + public static final Location HELSINKI = new Location(new UnLocode("FIHEL"), "Helsinki"); + public static final Location CHICAGO = new Location(new UnLocode("USCHI"), "Chicago"); + public static final Location TOKYO = new Location(new UnLocode("JNTKO"), "Tokyo"); + public static final Location HAMBURG = new Location(new UnLocode("DEHAM"), "Hamburg"); + public static final Location SHANGHAI = new Location(new UnLocode("CNSHA"), "Shanghai"); + public static final Location ROTTERDAM = new Location(new UnLocode("NLRTM"), "Rotterdam"); + public static final Location GOTHENBURG = new Location(new UnLocode("SEGOT"), "Gothenburg"); + public static final Location HANGZOU = new Location(new UnLocode("CNHGH"), "Hangzhou"); + public static final Location NEWYORK = new Location(new UnLocode("USNYC"), "New York"); + public static final Location DALLAS = new Location(new UnLocode("USDAL"), "Dallas"); } diff --git a/src/main/java/org/eclipse/cargotracker/domain/model/location/UnLocode.java b/src/main/java/org/eclipse/cargotracker/domain/model/location/UnLocode.java index 6f3888214..ccbffd26d 100644 --- a/src/main/java/org/eclipse/cargotracker/domain/model/location/UnLocode.java +++ b/src/main/java/org/eclipse/cargotracker/domain/model/location/UnLocode.java @@ -10,71 +10,69 @@ /** * United nations location code. - *

- * http://www.unece.org/cefact/locode/ + * + *

http://www.unece.org/cefact/locode/ * http://www.unece.org/cefact/locode/DocColumnDescription.htm#LOCODE */ @Embeddable public class UnLocode implements Serializable { - private static final long serialVersionUID = 1L; - - @NotNull - // Country code is exactly two letters. - // Location code is usually three letters, but may contain the numbers 2-9 - // as well. - @Pattern(regexp = "[a-zA-Z]{2}[a-zA-Z2-9]{3}") - private String unlocode; - private static final java.util.regex.Pattern VALID_PATTERN = java.util.regex.Pattern - .compile("[a-zA-Z]{2}[a-zA-Z2-9]{3}"); - - public UnLocode() { - // Nothing to initialize. - } - - /** - * @param countryAndLocation Location string. - */ - public UnLocode(String countryAndLocation) { - Validate.notNull(countryAndLocation, "Country and location may not be null"); - Validate.isTrue(VALID_PATTERN.matcher(countryAndLocation).matches(), - countryAndLocation + " is not a valid UN/LOCODE (does not match pattern)"); - - this.unlocode = countryAndLocation.toUpperCase(); - } - - /** - * @return country code and location code concatenated, always upper case. - */ - public String getIdString() { - return unlocode; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - UnLocode other = (UnLocode) o; - - return sameValueAs(other); - } - - @Override - public int hashCode() { - return unlocode.hashCode(); - } - - boolean sameValueAs(UnLocode other) { - return other != null && this.unlocode.equals(other.unlocode); - } - - @Override - public String toString() { - return getIdString(); - } + private static final long serialVersionUID = 1L; + + @NotNull + // Country code is exactly two letters. + // Location code is usually three letters, but may contain the numbers 2-9 + // as well. + @Pattern(regexp = "[a-zA-Z]{2}[a-zA-Z2-9]{3}") + private String unlocode; + + private static final java.util.regex.Pattern VALID_PATTERN = + java.util.regex.Pattern.compile("[a-zA-Z]{2}[a-zA-Z2-9]{3}"); + + public UnLocode() { + // Nothing to initialize. + } + + /** @param countryAndLocation Location string. */ + public UnLocode(String countryAndLocation) { + Validate.notNull(countryAndLocation, "Country and location may not be null"); + Validate.isTrue( + VALID_PATTERN.matcher(countryAndLocation).matches(), + countryAndLocation + " is not a valid UN/LOCODE (does not match pattern)"); + + this.unlocode = countryAndLocation.toUpperCase(); + } + + /** @return country code and location code concatenated, always upper case. */ + public String getIdString() { + return unlocode; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + UnLocode other = (UnLocode) o; + + return sameValueAs(other); + } + + @Override + public int hashCode() { + return unlocode.hashCode(); + } + + boolean sameValueAs(UnLocode other) { + return other != null && this.unlocode.equals(other.unlocode); + } + + @Override + public String toString() { + return getIdString(); + } } From d1f23cbbe45fb05750b39809efea49114a10745e Mon Sep 17 00:00:00 2001 From: Reza Rahman Date: Sun, 17 Jan 2021 09:51:46 -0500 Subject: [PATCH 04/22] Apply Google Java Style Guide --- .../domain/model/voyage/CarrierMovement.java | 178 +++++++------ .../domain/model/voyage/SampleVoyages.java | 249 ++++++++++-------- .../domain/model/voyage/Schedule.java | 108 ++++---- .../domain/model/voyage/Voyage.java | 217 +++++++-------- .../domain/model/voyage/VoyageNumber.java | 100 +++---- .../domain/model/voyage/VoyageRepository.java | 4 +- .../domain/service/RoutingService.java | 12 +- .../domain/shared/AbstractSpecification.java | 48 ++-- .../domain/shared/AndSpecification.java | 40 ++- .../domain/shared/DomainObjectUtils.java | 26 +- .../domain/shared/NotSpecification.java | 35 ++- .../domain/shared/OrSpecification.java | 39 ++- .../domain/shared/Specification.java | 67 +++-- 13 files changed, 573 insertions(+), 550 deletions(-) diff --git a/src/main/java/org/eclipse/cargotracker/domain/model/voyage/CarrierMovement.java b/src/main/java/org/eclipse/cargotracker/domain/model/voyage/CarrierMovement.java index 1b64b3e32..131c36ba0 100644 --- a/src/main/java/org/eclipse/cargotracker/domain/model/voyage/CarrierMovement.java +++ b/src/main/java/org/eclipse/cargotracker/domain/model/voyage/CarrierMovement.java @@ -19,94 +19,100 @@ import org.apache.commons.lang3.builder.HashCodeBuilder; import org.eclipse.cargotracker.domain.model.location.Location; -/** - * A carrier movement is a vessel voyage from one location to another. - */ +/** A carrier movement is a vessel voyage from one location to another. */ @Entity @Table(name = "carrier_movement") public class CarrierMovement implements Serializable { - private static final long serialVersionUID = 1L; - - // Null object pattern - public static final CarrierMovement NONE = new CarrierMovement(Location.UNKNOWN, Location.UNKNOWN, new Date(0), - new Date(0)); - - @Id - @GeneratedValue - private Long id; - - @ManyToOne - @JoinColumn(name = "departure_location_id") - @NotNull - private Location departureLocation; - - @ManyToOne - @JoinColumn(name = "arrival_location_id") - @NotNull - private Location arrivalLocation; - - @Temporal(TemporalType.TIMESTAMP) - @Column(name = "departure_time") - @NotNull - private Date departureTime; - - @Temporal(TemporalType.TIMESTAMP) - @Column(name = "arrival_time") - @NotNull - private Date arrivalTime; - - public CarrierMovement() { - // Nothing to initialize. - } - - public CarrierMovement(Location departureLocation, Location arrivalLocation, Date departureTime, Date arrivalTime) { - Validate.noNullElements(new Object[] { departureLocation, arrivalLocation, departureTime, arrivalTime }); - this.departureTime = departureTime; - this.arrivalTime = arrivalTime; - this.departureLocation = departureLocation; - this.arrivalLocation = arrivalLocation; - } - - public Location getDepartureLocation() { - return departureLocation; - } - - public Location getArrivalLocation() { - return arrivalLocation; - } - - public Date getDepartureTime() { - return new Date(departureTime.getTime()); - } - - public Date getArrivalTime() { - return new Date(arrivalTime.getTime()); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - CarrierMovement that = (CarrierMovement) o; - - return sameValueAs(that); - } - - @Override - public int hashCode() { - return new HashCodeBuilder().append(this.departureLocation).append(this.departureTime) - .append(this.arrivalLocation).append(this.arrivalTime).toHashCode(); - } - - private boolean sameValueAs(CarrierMovement other) { - return other != null && new EqualsBuilder().append(this.departureLocation, other.departureLocation) - .append(this.departureTime, other.departureTime).append(this.arrivalLocation, other.arrivalLocation) - .append(this.arrivalTime, other.arrivalTime).isEquals(); - } + private static final long serialVersionUID = 1L; + + // Null object pattern + public static final CarrierMovement NONE = + new CarrierMovement(Location.UNKNOWN, Location.UNKNOWN, new Date(0), new Date(0)); + + @Id @GeneratedValue private Long id; + + @ManyToOne + @JoinColumn(name = "departure_location_id") + @NotNull + private Location departureLocation; + + @ManyToOne + @JoinColumn(name = "arrival_location_id") + @NotNull + private Location arrivalLocation; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name = "departure_time") + @NotNull + private Date departureTime; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name = "arrival_time") + @NotNull + private Date arrivalTime; + + public CarrierMovement() { + // Nothing to initialize. + } + + public CarrierMovement( + Location departureLocation, Location arrivalLocation, Date departureTime, Date arrivalTime) { + Validate.noNullElements( + new Object[] {departureLocation, arrivalLocation, departureTime, arrivalTime}); + this.departureTime = departureTime; + this.arrivalTime = arrivalTime; + this.departureLocation = departureLocation; + this.arrivalLocation = arrivalLocation; + } + + public Location getDepartureLocation() { + return departureLocation; + } + + public Location getArrivalLocation() { + return arrivalLocation; + } + + public Date getDepartureTime() { + return new Date(departureTime.getTime()); + } + + public Date getArrivalTime() { + return new Date(arrivalTime.getTime()); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + CarrierMovement that = (CarrierMovement) o; + + return sameValueAs(that); + } + + @Override + public int hashCode() { + return new HashCodeBuilder() + .append(this.departureLocation) + .append(this.departureTime) + .append(this.arrivalLocation) + .append(this.arrivalTime) + .toHashCode(); + } + + private boolean sameValueAs(CarrierMovement other) { + return other != null + && new EqualsBuilder() + .append(this.departureLocation, other.departureLocation) + .append(this.departureTime, other.departureTime) + .append(this.arrivalLocation, other.arrivalLocation) + .append(this.arrivalTime, other.arrivalTime) + .isEquals(); + } } diff --git a/src/main/java/org/eclipse/cargotracker/domain/model/voyage/SampleVoyages.java b/src/main/java/org/eclipse/cargotracker/domain/model/voyage/SampleVoyages.java index 92f4a015c..def65d779 100644 --- a/src/main/java/org/eclipse/cargotracker/domain/model/voyage/SampleVoyages.java +++ b/src/main/java/org/eclipse/cargotracker/domain/model/voyage/SampleVoyages.java @@ -13,116 +13,155 @@ import org.eclipse.cargotracker.domain.model.location.Location; import org.eclipse.cargotracker.domain.model.location.SampleLocations; -/** - * Sample carrier movements, for test purposes. - */ -//TODO [Jakarta EE 8] Move to the Java Date-Time API for date manipulation. Also avoid hard-coded dates. +/** Sample carrier movements, for test purposes. */ +// TODO [Jakarta EE 8] Move to the Java Date-Time API for date manipulation. Also avoid hard-coded +// dates. public class SampleVoyages { - public static final Voyage CM001 = createVoyage("CM001", SampleLocations.STOCKHOLM, SampleLocations.HAMBURG); - public static final Voyage CM002 = createVoyage("CM002", SampleLocations.HAMBURG, SampleLocations.HONGKONG); - public static final Voyage CM003 = createVoyage("CM003", SampleLocations.HONGKONG, SampleLocations.NEWYORK); - public static final Voyage CM004 = createVoyage("CM004", SampleLocations.NEWYORK, SampleLocations.CHICAGO); - public static final Voyage CM005 = createVoyage("CM005", SampleLocations.CHICAGO, SampleLocations.HAMBURG); - public static final Voyage CM006 = createVoyage("CM006", SampleLocations.HAMBURG, SampleLocations.HANGZOU); + public static final Voyage CM001 = + createVoyage("CM001", SampleLocations.STOCKHOLM, SampleLocations.HAMBURG); + public static final Voyage CM002 = + createVoyage("CM002", SampleLocations.HAMBURG, SampleLocations.HONGKONG); + public static final Voyage CM003 = + createVoyage("CM003", SampleLocations.HONGKONG, SampleLocations.NEWYORK); + public static final Voyage CM004 = + createVoyage("CM004", SampleLocations.NEWYORK, SampleLocations.CHICAGO); + public static final Voyage CM005 = + createVoyage("CM005", SampleLocations.CHICAGO, SampleLocations.HAMBURG); + public static final Voyage CM006 = + createVoyage("CM006", SampleLocations.HAMBURG, SampleLocations.HANGZOU); - private static Voyage createVoyage(String id, Location from, Location to) { - return new Voyage(new VoyageNumber(id), - new Schedule(Arrays.asList(new CarrierMovement(from, to, new Date(), new Date())))); - } + private static Voyage createVoyage(String id, Location from, Location to) { + return new Voyage( + new VoyageNumber(id), + new Schedule(Arrays.asList(new CarrierMovement(from, to, new Date(), new Date())))); + } - public final static Voyage v100 = new Voyage.Builder(new VoyageNumber("V100"), SampleLocations.HONGKONG) - .addMovement(SampleLocations.TOKYO, toDate("2014-03-03"), toDate("2014-03-05")) - .addMovement(SampleLocations.NEWYORK, toDate("2014-03-06"), toDate("2014-03-09")).build(); - public final static Voyage v200 = new Voyage.Builder(new VoyageNumber("V200"), SampleLocations.TOKYO) - .addMovement(SampleLocations.NEWYORK, toDate("2014-03-06"), toDate("2014-03-08")) - .addMovement(SampleLocations.CHICAGO, toDate("2014-03-10"), toDate("2014-03-14")) - .addMovement(SampleLocations.STOCKHOLM, toDate("2014-03-14"), toDate("2014-03-16")).build(); - public final static Voyage v300 = new Voyage.Builder(new VoyageNumber("V300"), SampleLocations.TOKYO) - .addMovement(SampleLocations.ROTTERDAM, toDate("2014-03-08"), toDate("2014-03-11")) - .addMovement(SampleLocations.HAMBURG, toDate("2014-03-11"), toDate("2014-03-12")) - .addMovement(SampleLocations.MELBOURNE, toDate("2014-03-14"), toDate("2014-03-18")) - .addMovement(SampleLocations.TOKYO, toDate("2014-03-19"), toDate("2014-03-21")).build(); - public final static Voyage v400 = new Voyage.Builder(new VoyageNumber("V400"), SampleLocations.HAMBURG) - .addMovement(SampleLocations.STOCKHOLM, toDate("2014-03-14"), toDate("2014-03-15")) - .addMovement(SampleLocations.HELSINKI, toDate("2014-03-15"), toDate("2014-03-16")) - .addMovement(SampleLocations.HAMBURG, toDate("2014-03-20"), toDate("2014-03-22")).build(); - /** - * Voyage number 0100S (by ship) - *

- * Hongkong - Hangzou - Tokyo - Melbourne - New York - */ - public static final Voyage HONGKONG_TO_NEW_YORK = new Voyage.Builder(new VoyageNumber("0100S"), - SampleLocations.HONGKONG) - .addMovement(SampleLocations.HANGZOU, toDate("2013-10-01", "12:00"), toDate("2013-10-03", "14:30")) - .addMovement(SampleLocations.TOKYO, toDate("2013-10-03", "21:00"), toDate("2013-10-06", "06:15")) - .addMovement(SampleLocations.MELBOURNE, toDate("2013-10-06", "11:00"), - toDate("2013-10-12", "11:30")) - .addMovement(SampleLocations.NEWYORK, toDate("2013-10-14", "12:00"), toDate("2013-10-23", "23:10")) - .build(); - /** - * Voyage number 0200T (by train) - *

- * New York - Chicago - Dallas - */ - public static final Voyage NEW_YORK_TO_DALLAS = new Voyage.Builder(new VoyageNumber("0200T"), - SampleLocations.NEWYORK) - .addMovement(SampleLocations.CHICAGO, toDate("2013-10-24", "07:00"), toDate("2013-10-24", "17:45")) - .addMovement(SampleLocations.DALLAS, toDate("2013-10-24", "21:25"), toDate("2013-10-25", "19:30")) - .build(); - /** - * Voyage number 0300A (by airplane) - *

- * Dallas - Hamburg - Stockholm - Helsinki - */ - public static final Voyage DALLAS_TO_HELSINKI = new Voyage.Builder(new VoyageNumber("0300A"), - SampleLocations.DALLAS) - .addMovement(SampleLocations.HAMBURG, toDate("2013-10-29", "03:30"), toDate("2013-10-31", "14:00")) - .addMovement(SampleLocations.STOCKHOLM, toDate("2013-11-01", "15:20"), - toDate("2013-11-01", "18:40")) - .addMovement(SampleLocations.HELSINKI, toDate("2013-11-02", "09:00"), toDate("2013-11-02", "11:15")) - .build(); - /** - * Voyage number 0301S (by ship) - *

- * Dallas - Hamburg - Stockholm - Helsinki, alternate route - */ - public static final Voyage DALLAS_TO_HELSINKI_ALT = new Voyage.Builder(new VoyageNumber("0301S"), - SampleLocations.DALLAS) - .addMovement(SampleLocations.HELSINKI, toDate("2013-10-29", "03:30"), toDate("2013-11-05", "15:45")) - .build(); - /** - * Voyage number 0400S (by ship) - *

- * Helsinki - Rotterdam - Shanghai - Hongkong - */ - public static final Voyage HELSINKI_TO_HONGKONG = new Voyage.Builder(new VoyageNumber("0400S"), - SampleLocations.HELSINKI) - .addMovement(SampleLocations.ROTTERDAM, toDate("2013-11-04", "05:50"), - toDate("2013-11-06", "14:10")) - .addMovement(SampleLocations.SHANGHAI, toDate("2013-11-10", "21:45"), toDate("2013-11-22", "16:40")) - .addMovement(SampleLocations.HONGKONG, toDate("2013-11-24", "07:00"), toDate("2013-11-28", "13:37")) - .build(); - public static final Map ALL = new HashMap(); + public static final Voyage v100 = + new Voyage.Builder(new VoyageNumber("V100"), SampleLocations.HONGKONG) + .addMovement(SampleLocations.TOKYO, toDate("2014-03-03"), toDate("2014-03-05")) + .addMovement(SampleLocations.NEWYORK, toDate("2014-03-06"), toDate("2014-03-09")) + .build(); + public static final Voyage v200 = + new Voyage.Builder(new VoyageNumber("V200"), SampleLocations.TOKYO) + .addMovement(SampleLocations.NEWYORK, toDate("2014-03-06"), toDate("2014-03-08")) + .addMovement(SampleLocations.CHICAGO, toDate("2014-03-10"), toDate("2014-03-14")) + .addMovement(SampleLocations.STOCKHOLM, toDate("2014-03-14"), toDate("2014-03-16")) + .build(); + public static final Voyage v300 = + new Voyage.Builder(new VoyageNumber("V300"), SampleLocations.TOKYO) + .addMovement(SampleLocations.ROTTERDAM, toDate("2014-03-08"), toDate("2014-03-11")) + .addMovement(SampleLocations.HAMBURG, toDate("2014-03-11"), toDate("2014-03-12")) + .addMovement(SampleLocations.MELBOURNE, toDate("2014-03-14"), toDate("2014-03-18")) + .addMovement(SampleLocations.TOKYO, toDate("2014-03-19"), toDate("2014-03-21")) + .build(); + public static final Voyage v400 = + new Voyage.Builder(new VoyageNumber("V400"), SampleLocations.HAMBURG) + .addMovement(SampleLocations.STOCKHOLM, toDate("2014-03-14"), toDate("2014-03-15")) + .addMovement(SampleLocations.HELSINKI, toDate("2014-03-15"), toDate("2014-03-16")) + .addMovement(SampleLocations.HAMBURG, toDate("2014-03-20"), toDate("2014-03-22")) + .build(); + /** + * Voyage number 0100S (by ship) + * + *

Hongkong - Hangzou - Tokyo - Melbourne - New York + */ + public static final Voyage HONGKONG_TO_NEW_YORK = + new Voyage.Builder(new VoyageNumber("0100S"), SampleLocations.HONGKONG) + .addMovement( + SampleLocations.HANGZOU, toDate("2013-10-01", "12:00"), toDate("2013-10-03", "14:30")) + .addMovement( + SampleLocations.TOKYO, toDate("2013-10-03", "21:00"), toDate("2013-10-06", "06:15")) + .addMovement( + SampleLocations.MELBOURNE, + toDate("2013-10-06", "11:00"), + toDate("2013-10-12", "11:30")) + .addMovement( + SampleLocations.NEWYORK, toDate("2013-10-14", "12:00"), toDate("2013-10-23", "23:10")) + .build(); + /** + * Voyage number 0200T (by train) + * + *

New York - Chicago - Dallas + */ + public static final Voyage NEW_YORK_TO_DALLAS = + new Voyage.Builder(new VoyageNumber("0200T"), SampleLocations.NEWYORK) + .addMovement( + SampleLocations.CHICAGO, toDate("2013-10-24", "07:00"), toDate("2013-10-24", "17:45")) + .addMovement( + SampleLocations.DALLAS, toDate("2013-10-24", "21:25"), toDate("2013-10-25", "19:30")) + .build(); + /** + * Voyage number 0300A (by airplane) + * + *

Dallas - Hamburg - Stockholm - Helsinki + */ + public static final Voyage DALLAS_TO_HELSINKI = + new Voyage.Builder(new VoyageNumber("0300A"), SampleLocations.DALLAS) + .addMovement( + SampleLocations.HAMBURG, toDate("2013-10-29", "03:30"), toDate("2013-10-31", "14:00")) + .addMovement( + SampleLocations.STOCKHOLM, + toDate("2013-11-01", "15:20"), + toDate("2013-11-01", "18:40")) + .addMovement( + SampleLocations.HELSINKI, + toDate("2013-11-02", "09:00"), + toDate("2013-11-02", "11:15")) + .build(); + /** + * Voyage number 0301S (by ship) + * + *

Dallas - Hamburg - Stockholm - Helsinki, alternate route + */ + public static final Voyage DALLAS_TO_HELSINKI_ALT = + new Voyage.Builder(new VoyageNumber("0301S"), SampleLocations.DALLAS) + .addMovement( + SampleLocations.HELSINKI, + toDate("2013-10-29", "03:30"), + toDate("2013-11-05", "15:45")) + .build(); + /** + * Voyage number 0400S (by ship) + * + *

Helsinki - Rotterdam - Shanghai - Hongkong + */ + public static final Voyage HELSINKI_TO_HONGKONG = + new Voyage.Builder(new VoyageNumber("0400S"), SampleLocations.HELSINKI) + .addMovement( + SampleLocations.ROTTERDAM, + toDate("2013-11-04", "05:50"), + toDate("2013-11-06", "14:10")) + .addMovement( + SampleLocations.SHANGHAI, + toDate("2013-11-10", "21:45"), + toDate("2013-11-22", "16:40")) + .addMovement( + SampleLocations.HONGKONG, + toDate("2013-11-24", "07:00"), + toDate("2013-11-28", "13:37")) + .build(); - static { - for (Field field : SampleVoyages.class.getDeclaredFields()) { - if (field.getType().equals(Voyage.class)) { - try { - Voyage voyage = (Voyage) field.get(null); - ALL.put(voyage.getVoyageNumber(), voyage); - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } - } - } - } + public static final Map ALL = new HashMap(); - public static List getAll() { - return new ArrayList(ALL.values()); - } + static { + for (Field field : SampleVoyages.class.getDeclaredFields()) { + if (field.getType().equals(Voyage.class)) { + try { + Voyage voyage = (Voyage) field.get(null); + ALL.put(voyage.getVoyageNumber(), voyage); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } + } + } - public static Voyage lookup(VoyageNumber voyageNumber) { - return ALL.get(voyageNumber); - } + public static List getAll() { + return new ArrayList(ALL.values()); + } + + public static Voyage lookup(VoyageNumber voyageNumber) { + return ALL.get(voyageNumber); + } } diff --git a/src/main/java/org/eclipse/cargotracker/domain/model/voyage/Schedule.java b/src/main/java/org/eclipse/cargotracker/domain/model/voyage/Schedule.java index c28d76ec4..2f3905ed8 100644 --- a/src/main/java/org/eclipse/cargotracker/domain/model/voyage/Schedule.java +++ b/src/main/java/org/eclipse/cargotracker/domain/model/voyage/Schedule.java @@ -15,62 +15,60 @@ import org.apache.commons.lang3.builder.HashCodeBuilder; import org.eclipse.persistence.annotations.PrivateOwned; -/** - * A voyage schedule. - */ +/** A voyage schedule. */ @Embeddable public class Schedule implements Serializable { - private static final long serialVersionUID = 1L; - - // Null object pattern. - public static final Schedule EMPTY = new Schedule(); - - // TODO [Clean Code] Look into why cascade delete doesn't work. - @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true) - @JoinColumn(name = "voyage_id") - // TODO [Clean Code] Index as cm_index - @PrivateOwned - @NotNull - @Size(min = 1) - private List carrierMovements = Collections.emptyList(); - - public Schedule() { - // Nothing to initialize. - } - - Schedule(List carrierMovements) { - Validate.notNull(carrierMovements); - Validate.noNullElements(carrierMovements); - Validate.notEmpty(carrierMovements); - - this.carrierMovements = carrierMovements; - } - - public List getCarrierMovements() { - return Collections.unmodifiableList(carrierMovements); - } - - private boolean sameValueAs(Schedule other) { - return other != null && this.carrierMovements.equals(other.carrierMovements); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - Schedule that = (Schedule) o; - - return sameValueAs(that); - } - - @Override - public int hashCode() { - return new HashCodeBuilder().append(this.carrierMovements).toHashCode(); - } + private static final long serialVersionUID = 1L; + + // Null object pattern. + public static final Schedule EMPTY = new Schedule(); + + // TODO [Clean Code] Look into why cascade delete doesn't work. + @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true) + @JoinColumn(name = "voyage_id") + // TODO [Clean Code] Index as cm_index + @PrivateOwned + @NotNull + @Size(min = 1) + private List carrierMovements = Collections.emptyList(); + + public Schedule() { + // Nothing to initialize. + } + + Schedule(List carrierMovements) { + Validate.notNull(carrierMovements); + Validate.noNullElements(carrierMovements); + Validate.notEmpty(carrierMovements); + + this.carrierMovements = carrierMovements; + } + + public List getCarrierMovements() { + return Collections.unmodifiableList(carrierMovements); + } + + private boolean sameValueAs(Schedule other) { + return other != null && this.carrierMovements.equals(other.carrierMovements); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + Schedule that = (Schedule) o; + + return sameValueAs(that); + } + + @Override + public int hashCode() { + return new HashCodeBuilder().append(this.carrierMovements).toHashCode(); + } } diff --git a/src/main/java/org/eclipse/cargotracker/domain/model/voyage/Voyage.java b/src/main/java/org/eclipse/cargotracker/domain/model/voyage/Voyage.java index 053d90a63..33820e9b2 100644 --- a/src/main/java/org/eclipse/cargotracker/domain/model/voyage/Voyage.java +++ b/src/main/java/org/eclipse/cargotracker/domain/model/voyage/Voyage.java @@ -1,119 +1,122 @@ package org.eclipse.cargotracker.domain.model.voyage; -import org.eclipse.cargotracker.domain.model.location.Location; -import org.apache.commons.lang3.Validate; - -import javax.persistence.*; -import javax.validation.constraints.NotNull; import java.io.Serializable; import java.util.ArrayList; import java.util.Date; import java.util.List; +import javax.persistence.Embedded; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.NamedQueries; +import javax.persistence.NamedQuery; +import javax.validation.constraints.NotNull; + +import org.apache.commons.lang3.Validate; +import org.eclipse.cargotracker.domain.model.location.Location; + @Entity @NamedQueries({ - @NamedQuery(name = "Voyage.findByVoyageNumber", query = "Select v from Voyage v where v.voyageNumber = :voyageNumber"), - @NamedQuery(name = "Voyage.findAll", query = "Select v from Voyage v order by v.voyageNumber") }) - + @NamedQuery( + name = "Voyage.findByVoyageNumber", + query = "Select v from Voyage v where v.voyageNumber = :voyageNumber"), + @NamedQuery(name = "Voyage.findAll", query = "Select v from Voyage v order by v.voyageNumber") +}) public class Voyage implements Serializable { - private static final long serialVersionUID = 1L; - - // Null object pattern - public static final Voyage NONE = new Voyage(new VoyageNumber(""), Schedule.EMPTY); - - @Id - @GeneratedValue - private Long id; - - @Embedded - @NotNull - private VoyageNumber voyageNumber; - - @Embedded - @NotNull - private Schedule schedule; - - public Voyage() { - // Nothing to initialize - } - - public Voyage(VoyageNumber voyageNumber, Schedule schedule) { - Validate.notNull(voyageNumber, "Voyage number is required"); - Validate.notNull(schedule, "Schedule is required"); - - this.voyageNumber = voyageNumber; - this.schedule = schedule; - } - - public VoyageNumber getVoyageNumber() { - return voyageNumber; - } - - public Schedule getSchedule() { - return schedule; - } - - @Override - public int hashCode() { - return voyageNumber.hashCode(); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null) { - return false; - } - if (!(o instanceof Voyage)) { - return false; - } - - Voyage that = (Voyage) o; - - return sameIdentityAs(that); - } - - public boolean sameIdentityAs(Voyage other) { - return other != null && this.getVoyageNumber().sameValueAs(other.getVoyageNumber()); - } - - @Override - public String toString() { - return "Voyage " + voyageNumber; - } - - /** - * Builder pattern is used for incremental construction of a Voyage aggregate. - * This serves as an aggregate factory. - */ - public static class Builder { - - private List carrierMovements = new ArrayList<>(); - private VoyageNumber voyageNumber; - private Location departureLocation; - - public Builder(VoyageNumber voyageNumber, Location departureLocation) { - Validate.notNull(voyageNumber, "Voyage number is required"); - Validate.notNull(departureLocation, "Departure location is required"); - - this.voyageNumber = voyageNumber; - this.departureLocation = departureLocation; - } - - public Builder addMovement(Location arrivalLocation, Date departureTime, Date arrivalTime) { - carrierMovements.add(new CarrierMovement(departureLocation, arrivalLocation, departureTime, arrivalTime)); - - // Next departure location is the same as this arrival location - this.departureLocation = arrivalLocation; - - return this; - } - - public Voyage build() { - return new Voyage(voyageNumber, new Schedule(carrierMovements)); - } - } + private static final long serialVersionUID = 1L; + + // Null object pattern + public static final Voyage NONE = new Voyage(new VoyageNumber(""), Schedule.EMPTY); + + @Id @GeneratedValue private Long id; + + @Embedded @NotNull private VoyageNumber voyageNumber; + + @Embedded @NotNull private Schedule schedule; + + public Voyage() { + // Nothing to initialize + } + + public Voyage(VoyageNumber voyageNumber, Schedule schedule) { + Validate.notNull(voyageNumber, "Voyage number is required"); + Validate.notNull(schedule, "Schedule is required"); + + this.voyageNumber = voyageNumber; + this.schedule = schedule; + } + + public VoyageNumber getVoyageNumber() { + return voyageNumber; + } + + public Schedule getSchedule() { + return schedule; + } + + @Override + public int hashCode() { + return voyageNumber.hashCode(); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null) { + return false; + } + if (!(o instanceof Voyage)) { + return false; + } + + Voyage that = (Voyage) o; + + return sameIdentityAs(that); + } + + public boolean sameIdentityAs(Voyage other) { + return other != null && this.getVoyageNumber().sameValueAs(other.getVoyageNumber()); + } + + @Override + public String toString() { + return "Voyage " + voyageNumber; + } + + /** + * Builder pattern is used for incremental construction of a Voyage aggregate. This serves as an + * aggregate factory. + */ + public static class Builder { + + private List carrierMovements = new ArrayList<>(); + private VoyageNumber voyageNumber; + private Location departureLocation; + + public Builder(VoyageNumber voyageNumber, Location departureLocation) { + Validate.notNull(voyageNumber, "Voyage number is required"); + Validate.notNull(departureLocation, "Departure location is required"); + + this.voyageNumber = voyageNumber; + this.departureLocation = departureLocation; + } + + public Builder addMovement(Location arrivalLocation, Date departureTime, Date arrivalTime) { + carrierMovements.add( + new CarrierMovement(departureLocation, arrivalLocation, departureTime, arrivalTime)); + + // Next departure location is the same as this arrival location + this.departureLocation = arrivalLocation; + + return this; + } + + public Voyage build() { + return new Voyage(voyageNumber, new Schedule(carrierMovements)); + } + } } diff --git a/src/main/java/org/eclipse/cargotracker/domain/model/voyage/VoyageNumber.java b/src/main/java/org/eclipse/cargotracker/domain/model/voyage/VoyageNumber.java index 642dc56b4..b4dc4ec0f 100644 --- a/src/main/java/org/eclipse/cargotracker/domain/model/voyage/VoyageNumber.java +++ b/src/main/java/org/eclipse/cargotracker/domain/model/voyage/VoyageNumber.java @@ -11,54 +11,54 @@ @Embeddable public class VoyageNumber implements Serializable { - private static final long serialVersionUID = 1L; - - @Column(name = "voyage_number") - @NotNull - private String number; - - public VoyageNumber() { - // Nothing to initialize. - } - - public VoyageNumber(String number) { - Validate.notNull(number); - - this.number = number; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null) { - return false; - } - if (!(o instanceof VoyageNumber)) { - return false; - } - - VoyageNumber other = (VoyageNumber) o; - - return sameValueAs(other); - } - - @Override - public int hashCode() { - return number.hashCode(); - } - - boolean sameValueAs(VoyageNumber other) { - return other != null && this.number.equals(other.number); - } - - @Override - public String toString() { - return number; - } - - public String getIdString() { - return number; - } + private static final long serialVersionUID = 1L; + + @Column(name = "voyage_number") + @NotNull + private String number; + + public VoyageNumber() { + // Nothing to initialize. + } + + public VoyageNumber(String number) { + Validate.notNull(number); + + this.number = number; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null) { + return false; + } + if (!(o instanceof VoyageNumber)) { + return false; + } + + VoyageNumber other = (VoyageNumber) o; + + return sameValueAs(other); + } + + @Override + public int hashCode() { + return number.hashCode(); + } + + boolean sameValueAs(VoyageNumber other) { + return other != null && this.number.equals(other.number); + } + + @Override + public String toString() { + return number; + } + + public String getIdString() { + return number; + } } diff --git a/src/main/java/org/eclipse/cargotracker/domain/model/voyage/VoyageRepository.java b/src/main/java/org/eclipse/cargotracker/domain/model/voyage/VoyageRepository.java index 740ce6aef..4865f3103 100644 --- a/src/main/java/org/eclipse/cargotracker/domain/model/voyage/VoyageRepository.java +++ b/src/main/java/org/eclipse/cargotracker/domain/model/voyage/VoyageRepository.java @@ -4,7 +4,7 @@ public interface VoyageRepository { - Voyage find(VoyageNumber voyageNumber); + Voyage find(VoyageNumber voyageNumber); - List findAll(); + List findAll(); } diff --git a/src/main/java/org/eclipse/cargotracker/domain/service/RoutingService.java b/src/main/java/org/eclipse/cargotracker/domain/service/RoutingService.java index 22de97215..5aa2fc9ef 100644 --- a/src/main/java/org/eclipse/cargotracker/domain/service/RoutingService.java +++ b/src/main/java/org/eclipse/cargotracker/domain/service/RoutingService.java @@ -7,10 +7,10 @@ public interface RoutingService { - /** - * @param routeSpecification Route specification - * @return A list of itineraries that satisfy the specification. May be an empty - * list if no route is found. - */ - List fetchRoutesForSpecification(RouteSpecification routeSpecification); + /** + * @param routeSpecification Route specification + * @return A list of itineraries that satisfy the specification. May be an empty list if no route + * is found. + */ + List fetchRoutesForSpecification(RouteSpecification routeSpecification); } diff --git a/src/main/java/org/eclipse/cargotracker/domain/shared/AbstractSpecification.java b/src/main/java/org/eclipse/cargotracker/domain/shared/AbstractSpecification.java index f65ae66e6..34889108c 100644 --- a/src/main/java/org/eclipse/cargotracker/domain/shared/AbstractSpecification.java +++ b/src/main/java/org/eclipse/cargotracker/domain/shared/AbstractSpecification.java @@ -1,38 +1,30 @@ package org.eclipse.cargotracker.domain.shared; /** - * Abstract base implementation of composite {@link Specification} with default - * implementations for {@code and}, {@code or} and {@code not}. + * Abstract base implementation of composite {@link Specification} with default implementations for + * {@code and}, {@code or} and {@code not}. */ public abstract class AbstractSpecification implements Specification { - /** - * {@inheritDoc} - */ - @Override - public abstract boolean isSatisfiedBy(T t); + /** {@inheritDoc} */ + @Override + public abstract boolean isSatisfiedBy(T t); - /** - * {@inheritDoc} - */ - @Override - public Specification and(Specification specification) { - return new AndSpecification<>(this, specification); - } + /** {@inheritDoc} */ + @Override + public Specification and(Specification specification) { + return new AndSpecification<>(this, specification); + } - /** - * {@inheritDoc} - */ - @Override - public Specification or(Specification specification) { - return new OrSpecification<>(this, specification); - } + /** {@inheritDoc} */ + @Override + public Specification or(Specification specification) { + return new OrSpecification<>(this, specification); + } - /** - * {@inheritDoc} - */ - @Override - public Specification not(Specification specification) { - return new NotSpecification<>(specification); - } + /** {@inheritDoc} */ + @Override + public Specification not(Specification specification) { + return new NotSpecification<>(specification); + } } diff --git a/src/main/java/org/eclipse/cargotracker/domain/shared/AndSpecification.java b/src/main/java/org/eclipse/cargotracker/domain/shared/AndSpecification.java index dbd84bc4c..25c55fcb2 100644 --- a/src/main/java/org/eclipse/cargotracker/domain/shared/AndSpecification.java +++ b/src/main/java/org/eclipse/cargotracker/domain/shared/AndSpecification.java @@ -1,30 +1,28 @@ package org.eclipse.cargotracker.domain.shared; /** - * AND specification, used to create a new specification that is the AND of two - * other specifications. + * AND specification, used to create a new specification that is the AND of two other + * specifications. */ public class AndSpecification extends AbstractSpecification { - private final Specification spec1; - private final Specification spec2; + private final Specification spec1; + private final Specification spec2; - /** - * Create a new AND specification based on two other spec. - * - * @param spec1 Specification one. - * @param spec2 Specification two. - */ - public AndSpecification(Specification spec1, Specification spec2) { - this.spec1 = spec1; - this.spec2 = spec2; - } + /** + * Create a new AND specification based on two other spec. + * + * @param spec1 Specification one. + * @param spec2 Specification two. + */ + public AndSpecification(Specification spec1, Specification spec2) { + this.spec1 = spec1; + this.spec2 = spec2; + } - /** - * {@inheritDoc} - */ - @Override - public boolean isSatisfiedBy(T t) { - return spec1.isSatisfiedBy(t) && spec2.isSatisfiedBy(t); - } + /** {@inheritDoc} */ + @Override + public boolean isSatisfiedBy(T t) { + return spec1.isSatisfiedBy(t) && spec2.isSatisfiedBy(t); + } } diff --git a/src/main/java/org/eclipse/cargotracker/domain/shared/DomainObjectUtils.java b/src/main/java/org/eclipse/cargotracker/domain/shared/DomainObjectUtils.java index 224b3d332..0f09b4601 100644 --- a/src/main/java/org/eclipse/cargotracker/domain/shared/DomainObjectUtils.java +++ b/src/main/java/org/eclipse/cargotracker/domain/shared/DomainObjectUtils.java @@ -3,20 +3,16 @@ // TODO [Clean Code] Make this a CDI singleton? public class DomainObjectUtils { - /** - * @param actual actual value - * @param safe a null-safe value - * @param type - * @return actual value, if it's not null, or safe value if the actual value is - * null. - */ - public static T nullSafe(T actual, T safe) { - return actual == null ? safe : actual; - } + /** + * @param actual actual value + * @param safe a null-safe value + * @param type + * @return actual value, if it's not null, or safe value if the actual value is null. + */ + public static T nullSafe(T actual, T safe) { + return actual == null ? safe : actual; + } - /** - * Prevent instantiation. - */ - private DomainObjectUtils() { - } + /** Prevent instantiation. */ + private DomainObjectUtils() {} } diff --git a/src/main/java/org/eclipse/cargotracker/domain/shared/NotSpecification.java b/src/main/java/org/eclipse/cargotracker/domain/shared/NotSpecification.java index d65d1f103..299995082 100644 --- a/src/main/java/org/eclipse/cargotracker/domain/shared/NotSpecification.java +++ b/src/main/java/org/eclipse/cargotracker/domain/shared/NotSpecification.java @@ -1,27 +1,22 @@ package org.eclipse.cargotracker.domain.shared; -/** - * NOT decorator, used to create a new specifcation that is the inverse (NOT) of - * the given spec. - */ +/** NOT decorator, used to create a new specifcation that is the inverse (NOT) of the given spec. */ public class NotSpecification extends AbstractSpecification { - private final Specification spec1; + private final Specification spec1; - /** - * Create a new NOT specification based on another spec. - * - * @param spec1 Specification instance to not. - */ - public NotSpecification(Specification spec1) { - this.spec1 = spec1; - } + /** + * Create a new NOT specification based on another spec. + * + * @param spec1 Specification instance to not. + */ + public NotSpecification(Specification spec1) { + this.spec1 = spec1; + } - /** - * {@inheritDoc} - */ - @Override - public boolean isSatisfiedBy(T t) { - return !spec1.isSatisfiedBy(t); - } + /** {@inheritDoc} */ + @Override + public boolean isSatisfiedBy(T t) { + return !spec1.isSatisfiedBy(t); + } } diff --git a/src/main/java/org/eclipse/cargotracker/domain/shared/OrSpecification.java b/src/main/java/org/eclipse/cargotracker/domain/shared/OrSpecification.java index 961694dae..82730c11c 100644 --- a/src/main/java/org/eclipse/cargotracker/domain/shared/OrSpecification.java +++ b/src/main/java/org/eclipse/cargotracker/domain/shared/OrSpecification.java @@ -1,30 +1,27 @@ package org.eclipse.cargotracker.domain.shared; /** - * OR specification, used to create a new specification that is the OR of two - * other specifications. + * OR specification, used to create a new specification that is the OR of two other specifications. */ public class OrSpecification extends AbstractSpecification { - private final Specification spec1; - private final Specification spec2; + private final Specification spec1; + private final Specification spec2; - /** - * Create a new OR specification based on two other spec. - * - * @param spec1 Specification one. - * @param spec2 Specification two. - */ - public OrSpecification(Specification spec1, Specification spec2) { - this.spec1 = spec1; - this.spec2 = spec2; - } + /** + * Create a new OR specification based on two other spec. + * + * @param spec1 Specification one. + * @param spec2 Specification two. + */ + public OrSpecification(Specification spec1, Specification spec2) { + this.spec1 = spec1; + this.spec2 = spec2; + } - /** - * {@inheritDoc} - */ - @Override - public boolean isSatisfiedBy(T t) { - return spec1.isSatisfiedBy(t) || spec2.isSatisfiedBy(t); - } + /** {@inheritDoc} */ + @Override + public boolean isSatisfiedBy(T t) { + return spec1.isSatisfiedBy(t) || spec2.isSatisfiedBy(t); + } } diff --git a/src/main/java/org/eclipse/cargotracker/domain/shared/Specification.java b/src/main/java/org/eclipse/cargotracker/domain/shared/Specification.java index bd7790218..a51b6832c 100644 --- a/src/main/java/org/eclipse/cargotracker/domain/shared/Specification.java +++ b/src/main/java/org/eclipse/cargotracker/domain/shared/Specification.java @@ -2,44 +2,43 @@ /** * Specification interface. - *

- * Use {@link AbstractSpecification} as base for creating specifications, and - * only the method {@link #isSatisfiedBy(Object)} must be implemented. + * + *

Use {@link AbstractSpecification} as base for creating specifications, and only the method + * {@link #isSatisfiedBy(Object)} must be implemented. */ public interface Specification { - /** - * Check if {@code t} is satisfied by the specification. - * - * @param t Object to test. - * @return {@code true} if {@code t} satisfies the specification. - */ - boolean isSatisfiedBy(T t); + /** + * Check if {@code t} is satisfied by the specification. + * + * @param t Object to test. + * @return {@code true} if {@code t} satisfies the specification. + */ + boolean isSatisfiedBy(T t); - /** - * Create a new specification that is the AND operation of {@code this} - * specification and another specification. - * - * @param specification Specification to AND. - * @return A new specification. - */ - Specification and(Specification specification); + /** + * Create a new specification that is the AND operation of {@code this} specification and another + * specification. + * + * @param specification Specification to AND. + * @return A new specification. + */ + Specification and(Specification specification); - /** - * Create a new specification that is the OR operation of {@code this} - * specification and another specification. - * - * @param specification Specification to OR. - * @return A new specification. - */ - Specification or(Specification specification); + /** + * Create a new specification that is the OR operation of {@code this} specification and another + * specification. + * + * @param specification Specification to OR. + * @return A new specification. + */ + Specification or(Specification specification); - /** - * Create a new specification that is the NOT operation of {@code this} - * specification. - * - * @param specification Specification to NOT. - * @return A new specification. - */ - Specification not(Specification specification); + /** + * Create a new specification that is the NOT operation of {@code this} specification. + * + * @param specification Specification to NOT. + * @return A new specification. + */ + Specification not(Specification specification); } From a1d71ced6ed0ee9e004baf26085ad6bb37e7e828 Mon Sep 17 00:00:00 2001 From: Reza Rahman Date: Sun, 17 Jan 2021 09:55:11 -0500 Subject: [PATCH 05/22] Apply Google Java Style Guide --- .../events/cdi/CargoInspected.java | 5 +- .../logging/LoggerProducer.java | 30 +++--- .../messaging/jms/CargoHandledConsumer.java | 53 +++++----- .../messaging/jms/DeliveredCargoConsumer.java | 32 +++--- ...dlingEventRegistrationAttemptConsumer.java | 49 ++++++---- .../messaging/jms/JmsApplicationEvents.java | 97 +++++++++++-------- .../jms/MisdirectedCargoConsumer.java | 32 +++--- .../RejectedRegistrationAttemptsConsumer.java | 35 ++++--- .../infrastructure/messaging/jms/package.html | 4 +- .../persistence/jpa/JpaCargoRepository.java | 90 ++++++++--------- 10 files changed, 237 insertions(+), 190 deletions(-) diff --git a/src/main/java/org/eclipse/cargotracker/infrastructure/events/cdi/CargoInspected.java b/src/main/java/org/eclipse/cargotracker/infrastructure/events/cdi/CargoInspected.java index 26db628d3..781f44ed6 100644 --- a/src/main/java/org/eclipse/cargotracker/infrastructure/events/cdi/CargoInspected.java +++ b/src/main/java/org/eclipse/cargotracker/infrastructure/events/cdi/CargoInspected.java @@ -11,6 +11,5 @@ @Qualifier @Retention(RUNTIME) -@Target({ FIELD, PARAMETER }) -public @interface CargoInspected { -} +@Target({FIELD, PARAMETER}) +public @interface CargoInspected {} diff --git a/src/main/java/org/eclipse/cargotracker/infrastructure/logging/LoggerProducer.java b/src/main/java/org/eclipse/cargotracker/infrastructure/logging/LoggerProducer.java index 48ef4c495..8fbc7b7f8 100644 --- a/src/main/java/org/eclipse/cargotracker/infrastructure/logging/LoggerProducer.java +++ b/src/main/java/org/eclipse/cargotracker/infrastructure/logging/LoggerProducer.java @@ -10,24 +10,24 @@ @ApplicationScoped public class LoggerProducer implements Serializable { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - @Produces - public Logger produceLogger(InjectionPoint injectionPoint) { - String loggerName = extractLoggerName(injectionPoint); + @Produces + public Logger produceLogger(InjectionPoint injectionPoint) { + String loggerName = extractLoggerName(injectionPoint); - return Logger.getLogger(loggerName); - } + return Logger.getLogger(loggerName); + } - private String extractLoggerName(InjectionPoint injectionPoint) { - if (injectionPoint.getBean() == null) { - return injectionPoint.getMember().getDeclaringClass().getName(); - } + private String extractLoggerName(InjectionPoint injectionPoint) { + if (injectionPoint.getBean() == null) { + return injectionPoint.getMember().getDeclaringClass().getName(); + } - if (injectionPoint.getBean().getName() == null) { - return injectionPoint.getBean().getBeanClass().getName(); - } + if (injectionPoint.getBean().getName() == null) { + return injectionPoint.getBean().getBeanClass().getName(); + } - return injectionPoint.getBean().getName(); - } + return injectionPoint.getBean().getName(); + } } diff --git a/src/main/java/org/eclipse/cargotracker/infrastructure/messaging/jms/CargoHandledConsumer.java b/src/main/java/org/eclipse/cargotracker/infrastructure/messaging/jms/CargoHandledConsumer.java index a39f0f42d..45b025e9f 100644 --- a/src/main/java/org/eclipse/cargotracker/infrastructure/messaging/jms/CargoHandledConsumer.java +++ b/src/main/java/org/eclipse/cargotracker/infrastructure/messaging/jms/CargoHandledConsumer.java @@ -15,32 +15,35 @@ import org.eclipse.cargotracker.domain.model.cargo.TrackingId; /** - * Consumes JMS messages and delegates notification of misdirected cargo to the - * tracking service. - *

- * This is a programmatic hook into the JMS infrastructure to make cargo - * inspection message-driven. + * Consumes JMS messages and delegates notification of misdirected cargo to the tracking service. + * + *

This is a programmatic hook into the JMS infrastructure to make cargo inspection + * message-driven. */ -@MessageDriven(activationConfig = { - @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"), - @ActivationConfigProperty(propertyName = "destinationLookup", propertyValue = "java:app/jms/CargoHandledQueue") }) +@MessageDriven( + activationConfig = { + @ActivationConfigProperty( + propertyName = "destinationType", + propertyValue = "javax.jms.Queue"), + @ActivationConfigProperty( + propertyName = "destinationLookup", + propertyValue = "java:app/jms/CargoHandledQueue") + }) public class CargoHandledConsumer implements MessageListener { - @Inject - private Logger logger; - - @Inject - private CargoInspectionService cargoInspectionService; - - @Override - public void onMessage(Message message) { - try { - TextMessage textMessage = (TextMessage) message; - String trackingIdString = textMessage.getText(); - - cargoInspectionService.inspectCargo(new TrackingId(trackingIdString)); - } catch (JMSException e) { - logger.log(Level.SEVERE, "Error procesing JMS message", e); - } - } + @Inject private Logger logger; + + @Inject private CargoInspectionService cargoInspectionService; + + @Override + public void onMessage(Message message) { + try { + TextMessage textMessage = (TextMessage) message; + String trackingIdString = textMessage.getText(); + + cargoInspectionService.inspectCargo(new TrackingId(trackingIdString)); + } catch (JMSException e) { + logger.log(Level.SEVERE, "Error procesing JMS message", e); + } + } } diff --git a/src/main/java/org/eclipse/cargotracker/infrastructure/messaging/jms/DeliveredCargoConsumer.java b/src/main/java/org/eclipse/cargotracker/infrastructure/messaging/jms/DeliveredCargoConsumer.java index 6e66830f7..43998fd68 100644 --- a/src/main/java/org/eclipse/cargotracker/infrastructure/messaging/jms/DeliveredCargoConsumer.java +++ b/src/main/java/org/eclipse/cargotracker/infrastructure/messaging/jms/DeliveredCargoConsumer.java @@ -10,20 +10,26 @@ import javax.jms.Message; import javax.jms.MessageListener; -@MessageDriven(activationConfig = { - @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"), - @ActivationConfigProperty(propertyName = "destinationLookup", propertyValue = "java:app/jms/DeliveredCargoQueue") }) +@MessageDriven( + activationConfig = { + @ActivationConfigProperty( + propertyName = "destinationType", + propertyValue = "javax.jms.Queue"), + @ActivationConfigProperty( + propertyName = "destinationLookup", + propertyValue = "java:app/jms/DeliveredCargoQueue") + }) public class DeliveredCargoConsumer implements MessageListener { - @Inject - private Logger logger; + @Inject private Logger logger; - @Override - public void onMessage(Message message) { - try { - logger.log(Level.INFO, "Cargo with tracking ID {0} delivered.", message.getBody(String.class)); - } catch (JMSException ex) { - logger.log(Level.WARNING, "Error processing message.", ex); - } - } + @Override + public void onMessage(Message message) { + try { + logger.log( + Level.INFO, "Cargo with tracking ID {0} delivered.", message.getBody(String.class)); + } catch (JMSException ex) { + logger.log(Level.WARNING, "Error processing message.", ex); + } + } } diff --git a/src/main/java/org/eclipse/cargotracker/infrastructure/messaging/jms/HandlingEventRegistrationAttemptConsumer.java b/src/main/java/org/eclipse/cargotracker/infrastructure/messaging/jms/HandlingEventRegistrationAttemptConsumer.java index 597027653..ab838c9a4 100644 --- a/src/main/java/org/eclipse/cargotracker/infrastructure/messaging/jms/HandlingEventRegistrationAttemptConsumer.java +++ b/src/main/java/org/eclipse/cargotracker/infrastructure/messaging/jms/HandlingEventRegistrationAttemptConsumer.java @@ -12,28 +12,35 @@ import org.eclipse.cargotracker.domain.model.handling.CannotCreateHandlingEventException; import org.eclipse.cargotracker.interfaces.handling.HandlingEventRegistrationAttempt; -/** - * Consumes handling event registration attempt messages and delegates to proper - * registration. - */ -@MessageDriven(activationConfig = { - @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"), - @ActivationConfigProperty(propertyName = "destinationLookup", propertyValue = "java:app/jms/HandlingEventRegistrationAttemptQueue") }) +/** Consumes handling event registration attempt messages and delegates to proper registration. */ +@MessageDriven( + activationConfig = { + @ActivationConfigProperty( + propertyName = "destinationType", + propertyValue = "javax.jms.Queue"), + @ActivationConfigProperty( + propertyName = "destinationLookup", + propertyValue = "java:app/jms/HandlingEventRegistrationAttemptQueue") + }) public class HandlingEventRegistrationAttemptConsumer implements MessageListener { - @Inject - private HandlingEventService handlingEventService; + @Inject private HandlingEventService handlingEventService; - @Override - public void onMessage(Message message) { - try { - ObjectMessage objectMessage = (ObjectMessage) message; - HandlingEventRegistrationAttempt attempt = (HandlingEventRegistrationAttempt) objectMessage.getObject(); - handlingEventService.registerHandlingEvent(attempt.getCompletionTime(), attempt.getTrackingId(), - attempt.getVoyageNumber(), attempt.getUnLocode(), attempt.getType()); - } catch (JMSException | CannotCreateHandlingEventException e) { - // Poison messages will be placed on dead-letter queue. - throw new RuntimeException("Error occurred processing message", e); - } - } + @Override + public void onMessage(Message message) { + try { + ObjectMessage objectMessage = (ObjectMessage) message; + HandlingEventRegistrationAttempt attempt = + (HandlingEventRegistrationAttempt) objectMessage.getObject(); + handlingEventService.registerHandlingEvent( + attempt.getCompletionTime(), + attempt.getTrackingId(), + attempt.getVoyageNumber(), + attempt.getUnLocode(), + attempt.getType()); + } catch (JMSException | CannotCreateHandlingEventException e) { + // Poison messages will be placed on dead-letter queue. + throw new RuntimeException("Error occurred processing message", e); + } + } } diff --git a/src/main/java/org/eclipse/cargotracker/infrastructure/messaging/jms/JmsApplicationEvents.java b/src/main/java/org/eclipse/cargotracker/infrastructure/messaging/jms/JmsApplicationEvents.java index 54a31daed..0eec7d848 100644 --- a/src/main/java/org/eclipse/cargotracker/infrastructure/messaging/jms/JmsApplicationEvents.java +++ b/src/main/java/org/eclipse/cargotracker/infrastructure/messaging/jms/JmsApplicationEvents.java @@ -18,48 +18,67 @@ @ApplicationScoped public class JmsApplicationEvents implements ApplicationEvents, Serializable { - private static final long serialVersionUID = 1L; - private static final int LOW_PRIORITY = 0; - @Inject - JMSContext jmsContext; - @Resource(lookup = "java:app/jms/CargoHandledQueue") - private Destination cargoHandledQueue; - @Resource(lookup = "java:app/jms/MisdirectedCargoQueue") - private Destination misdirectedCargoQueue; - @Resource(lookup = "java:app/jms/DeliveredCargoQueue") - private Destination deliveredCargoQueue; - @Resource(lookup = "java:app/jms/HandlingEventRegistrationAttemptQueue") - private Destination handlingEventQueue; - @Inject - private Logger logger; + private static final long serialVersionUID = 1L; + private static final int LOW_PRIORITY = 0; + @Inject JMSContext jmsContext; - @Override - public void cargoWasHandled(HandlingEvent event) { - Cargo cargo = event.getCargo(); - logger.log(Level.INFO, "Cargo was handled {0}", cargo); - jmsContext.createProducer().setPriority(LOW_PRIORITY).setDisableMessageID(true).setDisableMessageTimestamp(true) - .send(cargoHandledQueue, cargo.getTrackingId().getIdString()); - } + @Resource(lookup = "java:app/jms/CargoHandledQueue") + private Destination cargoHandledQueue; - @Override - public void cargoWasMisdirected(Cargo cargo) { - logger.log(Level.INFO, "Cargo was misdirected {0}", cargo); - jmsContext.createProducer().setPriority(LOW_PRIORITY).setDisableMessageID(true).setDisableMessageTimestamp(true) - .send(misdirectedCargoQueue, cargo.getTrackingId().getIdString()); - } + @Resource(lookup = "java:app/jms/MisdirectedCargoQueue") + private Destination misdirectedCargoQueue; - @Override - public void cargoHasArrived(Cargo cargo) { - logger.log(Level.INFO, "Cargo has arrived {0}", cargo); - jmsContext.createProducer().setPriority(LOW_PRIORITY).setDisableMessageID(true).setDisableMessageTimestamp(true) - .send(deliveredCargoQueue, cargo.getTrackingId().getIdString()); - } + @Resource(lookup = "java:app/jms/DeliveredCargoQueue") + private Destination deliveredCargoQueue; - @Override - public void receivedHandlingEventRegistrationAttempt(HandlingEventRegistrationAttempt attempt) { - logger.log(Level.INFO, "Received handling event registration attempt {0}", attempt); - jmsContext.createProducer().setPriority(LOW_PRIORITY).setDisableMessageID(true).setDisableMessageTimestamp(true) - .setTimeToLive(1000).send(handlingEventQueue, attempt); - } + @Resource(lookup = "java:app/jms/HandlingEventRegistrationAttemptQueue") + private Destination handlingEventQueue; + @Inject private Logger logger; + + @Override + public void cargoWasHandled(HandlingEvent event) { + Cargo cargo = event.getCargo(); + logger.log(Level.INFO, "Cargo was handled {0}", cargo); + jmsContext + .createProducer() + .setPriority(LOW_PRIORITY) + .setDisableMessageID(true) + .setDisableMessageTimestamp(true) + .send(cargoHandledQueue, cargo.getTrackingId().getIdString()); + } + + @Override + public void cargoWasMisdirected(Cargo cargo) { + logger.log(Level.INFO, "Cargo was misdirected {0}", cargo); + jmsContext + .createProducer() + .setPriority(LOW_PRIORITY) + .setDisableMessageID(true) + .setDisableMessageTimestamp(true) + .send(misdirectedCargoQueue, cargo.getTrackingId().getIdString()); + } + + @Override + public void cargoHasArrived(Cargo cargo) { + logger.log(Level.INFO, "Cargo has arrived {0}", cargo); + jmsContext + .createProducer() + .setPriority(LOW_PRIORITY) + .setDisableMessageID(true) + .setDisableMessageTimestamp(true) + .send(deliveredCargoQueue, cargo.getTrackingId().getIdString()); + } + + @Override + public void receivedHandlingEventRegistrationAttempt(HandlingEventRegistrationAttempt attempt) { + logger.log(Level.INFO, "Received handling event registration attempt {0}", attempt); + jmsContext + .createProducer() + .setPriority(LOW_PRIORITY) + .setDisableMessageID(true) + .setDisableMessageTimestamp(true) + .setTimeToLive(1000) + .send(handlingEventQueue, attempt); + } } diff --git a/src/main/java/org/eclipse/cargotracker/infrastructure/messaging/jms/MisdirectedCargoConsumer.java b/src/main/java/org/eclipse/cargotracker/infrastructure/messaging/jms/MisdirectedCargoConsumer.java index aecc29e82..960373804 100644 --- a/src/main/java/org/eclipse/cargotracker/infrastructure/messaging/jms/MisdirectedCargoConsumer.java +++ b/src/main/java/org/eclipse/cargotracker/infrastructure/messaging/jms/MisdirectedCargoConsumer.java @@ -10,20 +10,26 @@ import javax.jms.Message; import javax.jms.MessageListener; -@MessageDriven(activationConfig = { - @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"), - @ActivationConfigProperty(propertyName = "destinationLookup", propertyValue = "java:app/jms/MisdirectedCargoQueue") }) +@MessageDriven( + activationConfig = { + @ActivationConfigProperty( + propertyName = "destinationType", + propertyValue = "javax.jms.Queue"), + @ActivationConfigProperty( + propertyName = "destinationLookup", + propertyValue = "java:app/jms/MisdirectedCargoQueue") + }) public class MisdirectedCargoConsumer implements MessageListener { - @Inject - private Logger logger; + @Inject private Logger logger; - @Override - public void onMessage(Message message) { - try { - logger.log(Level.INFO, "Cargo with tracking ID {0} misdirected.", message.getBody(String.class)); - } catch (JMSException ex) { - logger.log(Level.WARNING, "Error processing message.", ex); - } - } + @Override + public void onMessage(Message message) { + try { + logger.log( + Level.INFO, "Cargo with tracking ID {0} misdirected.", message.getBody(String.class)); + } catch (JMSException ex) { + logger.log(Level.WARNING, "Error processing message.", ex); + } + } } diff --git a/src/main/java/org/eclipse/cargotracker/infrastructure/messaging/jms/RejectedRegistrationAttemptsConsumer.java b/src/main/java/org/eclipse/cargotracker/infrastructure/messaging/jms/RejectedRegistrationAttemptsConsumer.java index b04d8838b..0f6d175e9 100644 --- a/src/main/java/org/eclipse/cargotracker/infrastructure/messaging/jms/RejectedRegistrationAttemptsConsumer.java +++ b/src/main/java/org/eclipse/cargotracker/infrastructure/messaging/jms/RejectedRegistrationAttemptsConsumer.java @@ -10,21 +10,28 @@ import javax.jms.Message; import javax.jms.MessageListener; -@MessageDriven(activationConfig = { - @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"), - @ActivationConfigProperty(propertyName = "destinationLookup", propertyValue = "java:app/jms/RejectedRegistrationAttemptsQueue") }) +@MessageDriven( + activationConfig = { + @ActivationConfigProperty( + propertyName = "destinationType", + propertyValue = "javax.jms.Queue"), + @ActivationConfigProperty( + propertyName = "destinationLookup", + propertyValue = "java:app/jms/RejectedRegistrationAttemptsQueue") + }) public class RejectedRegistrationAttemptsConsumer implements MessageListener { - @Inject - private Logger logger; + @Inject private Logger logger; - @Override - public void onMessage(Message message) { - try { - logger.log(Level.INFO, "Rejected registration attempt of cargo with tracking ID {0}.", - message.getBody(String.class)); - } catch (JMSException ex) { - logger.log(Level.WARNING, "Error processing message.", ex); - } - } + @Override + public void onMessage(Message message) { + try { + logger.log( + Level.INFO, + "Rejected registration attempt of cargo with tracking ID {0}.", + message.getBody(String.class)); + } catch (JMSException ex) { + logger.log(Level.WARNING, "Error processing message.", ex); + } + } } diff --git a/src/main/java/org/eclipse/cargotracker/infrastructure/messaging/jms/package.html b/src/main/java/org/eclipse/cargotracker/infrastructure/messaging/jms/package.html index 61b7d5c45..1a10514b4 100644 --- a/src/main/java/org/eclipse/cargotracker/infrastructure/messaging/jms/package.html +++ b/src/main/java/org/eclipse/cargotracker/infrastructure/messaging/jms/package.html @@ -1,6 +1,6 @@ -

Asynchronous messaging implemented using Jakarta Messaging. This is part of - the infrastructure.

+

Asynchronous messaging implemented using Jakarta Messaging. This + is part of the infrastructure.

diff --git a/src/main/java/org/eclipse/cargotracker/infrastructure/persistence/jpa/JpaCargoRepository.java b/src/main/java/org/eclipse/cargotracker/infrastructure/persistence/jpa/JpaCargoRepository.java index 22ca7faf4..7e912f18c 100644 --- a/src/main/java/org/eclipse/cargotracker/infrastructure/persistence/jpa/JpaCargoRepository.java +++ b/src/main/java/org/eclipse/cargotracker/infrastructure/persistence/jpa/JpaCargoRepository.java @@ -20,49 +20,49 @@ @ApplicationScoped public class JpaCargoRepository implements CargoRepository, Serializable { - private static final long serialVersionUID = 1L; - - @Inject - private Logger logger; - - @PersistenceContext - private EntityManager entityManager; - - @Override - public Cargo find(TrackingId trackingId) { - Cargo cargo; - - try { - cargo = entityManager.createNamedQuery("Cargo.findByTrackingId", Cargo.class) - .setParameter("trackingId", trackingId).getSingleResult(); - } catch (NoResultException e) { - logger.log(Level.FINE, "Find called on non-existant tracking ID.", e); - cargo = null; - } - - return cargo; - } - - @Override - public void store(Cargo cargo) { - // TODO [Clean Code] See why cascade is not working correctly for legs. - for (Leg leg : cargo.getItinerary().getLegs()) { - entityManager.persist(leg); - } - - entityManager.persist(cargo); - } - - @Override - public TrackingId nextTrackingId() { - String random = UUID.randomUUID().toString().toUpperCase(); - - return new TrackingId(random.substring(0, random.indexOf("-"))); - } - - @Override - public List findAll() { - return entityManager.createNamedQuery("Cargo.findAll", Cargo.class).getResultList(); - } - + private static final long serialVersionUID = 1L; + + @Inject private Logger logger; + + @PersistenceContext private EntityManager entityManager; + + @Override + public Cargo find(TrackingId trackingId) { + Cargo cargo; + + try { + cargo = + entityManager + .createNamedQuery("Cargo.findByTrackingId", Cargo.class) + .setParameter("trackingId", trackingId) + .getSingleResult(); + } catch (NoResultException e) { + logger.log(Level.FINE, "Find called on non-existant tracking ID.", e); + cargo = null; + } + + return cargo; + } + + @Override + public void store(Cargo cargo) { + // TODO [Clean Code] See why cascade is not working correctly for legs. + for (Leg leg : cargo.getItinerary().getLegs()) { + entityManager.persist(leg); + } + + entityManager.persist(cargo); + } + + @Override + public TrackingId nextTrackingId() { + String random = UUID.randomUUID().toString().toUpperCase(); + + return new TrackingId(random.substring(0, random.indexOf("-"))); + } + + @Override + public List findAll() { + return entityManager.createNamedQuery("Cargo.findAll", Cargo.class).getResultList(); + } } From ab91b64c5d12ffc59a650e3189d71e523f3db7cd Mon Sep 17 00:00:00 2001 From: Reza Rahman Date: Sun, 17 Jan 2021 09:59:25 -0500 Subject: [PATCH 06/22] Apply Google Java Style Guide --- .../jpa/JpaHandlingEventRepository.java | 32 +-- .../jpa/JpaLocationRepository.java | 31 +-- .../persistence/jpa/JpaVoyageRepository.java | 32 +-- .../persistence/jpa/package.html | 4 +- .../routing/ExternalRoutingService.java | 130 ++++----- .../booking/facade/BookingServiceFacade.java | 26 +- .../booking/facade/dto/CargoRoute.java | 246 +++++++++--------- .../booking/facade/dto/CargoStatus.java | 97 +++---- .../interfaces/booking/facade/dto/Leg.java | 180 +++++++------ .../booking/facade/dto/Location.java | 36 ++- .../booking/facade/dto/RouteCandidate.java | 29 +-- .../booking/facade/dto/TrackingEvents.java | 32 +-- 12 files changed, 454 insertions(+), 421 deletions(-) diff --git a/src/main/java/org/eclipse/cargotracker/infrastructure/persistence/jpa/JpaHandlingEventRepository.java b/src/main/java/org/eclipse/cargotracker/infrastructure/persistence/jpa/JpaHandlingEventRepository.java index 044f18e67..f72587f46 100644 --- a/src/main/java/org/eclipse/cargotracker/infrastructure/persistence/jpa/JpaHandlingEventRepository.java +++ b/src/main/java/org/eclipse/cargotracker/infrastructure/persistence/jpa/JpaHandlingEventRepository.java @@ -14,19 +14,21 @@ @ApplicationScoped public class JpaHandlingEventRepository implements HandlingEventRepository, Serializable { - private static final long serialVersionUID = 1L; - - @PersistenceContext - private EntityManager entityManager; - - @Override - public void store(HandlingEvent event) { - entityManager.persist(event); - } - - @Override - public HandlingHistory lookupHandlingHistoryOfCargo(TrackingId trackingId) { - return new HandlingHistory(entityManager.createNamedQuery("HandlingEvent.findByTrackingId", HandlingEvent.class) - .setParameter("trackingId", trackingId).getResultList()); - } + private static final long serialVersionUID = 1L; + + @PersistenceContext private EntityManager entityManager; + + @Override + public void store(HandlingEvent event) { + entityManager.persist(event); + } + + @Override + public HandlingHistory lookupHandlingHistoryOfCargo(TrackingId trackingId) { + return new HandlingHistory( + entityManager + .createNamedQuery("HandlingEvent.findByTrackingId", HandlingEvent.class) + .setParameter("trackingId", trackingId) + .getResultList()); + } } diff --git a/src/main/java/org/eclipse/cargotracker/infrastructure/persistence/jpa/JpaLocationRepository.java b/src/main/java/org/eclipse/cargotracker/infrastructure/persistence/jpa/JpaLocationRepository.java index f0f6721ef..080a31299 100644 --- a/src/main/java/org/eclipse/cargotracker/infrastructure/persistence/jpa/JpaLocationRepository.java +++ b/src/main/java/org/eclipse/cargotracker/infrastructure/persistence/jpa/JpaLocationRepository.java @@ -14,19 +14,20 @@ @ApplicationScoped public class JpaLocationRepository implements LocationRepository, Serializable { - private static final long serialVersionUID = 1L; - - @PersistenceContext - private EntityManager entityManager; - - @Override - public Location find(UnLocode unLocode) { - return entityManager.createNamedQuery("Location.findByUnLocode", Location.class) - .setParameter("unLocode", unLocode).getSingleResult(); - } - - @Override - public List findAll() { - return entityManager.createNamedQuery("Location.findAll", Location.class).getResultList(); - } + private static final long serialVersionUID = 1L; + + @PersistenceContext private EntityManager entityManager; + + @Override + public Location find(UnLocode unLocode) { + return entityManager + .createNamedQuery("Location.findByUnLocode", Location.class) + .setParameter("unLocode", unLocode) + .getSingleResult(); + } + + @Override + public List findAll() { + return entityManager.createNamedQuery("Location.findAll", Location.class).getResultList(); + } } diff --git a/src/main/java/org/eclipse/cargotracker/infrastructure/persistence/jpa/JpaVoyageRepository.java b/src/main/java/org/eclipse/cargotracker/infrastructure/persistence/jpa/JpaVoyageRepository.java index 02d7bee3f..1383f6959 100644 --- a/src/main/java/org/eclipse/cargotracker/infrastructure/persistence/jpa/JpaVoyageRepository.java +++ b/src/main/java/org/eclipse/cargotracker/infrastructure/persistence/jpa/JpaVoyageRepository.java @@ -14,20 +14,20 @@ @ApplicationScoped public class JpaVoyageRepository implements VoyageRepository, Serializable { - private static final long serialVersionUID = 1L; - - @PersistenceContext - private EntityManager entityManager; - - @Override - public Voyage find(VoyageNumber voyageNumber) { - return entityManager.createNamedQuery("Voyage.findByVoyageNumber", Voyage.class) - .setParameter("voyageNumber", voyageNumber).getSingleResult(); - } - - @Override - public List findAll() { - return entityManager.createNamedQuery("Voyage.findAll", Voyage.class).getResultList(); - } - + private static final long serialVersionUID = 1L; + + @PersistenceContext private EntityManager entityManager; + + @Override + public Voyage find(VoyageNumber voyageNumber) { + return entityManager + .createNamedQuery("Voyage.findByVoyageNumber", Voyage.class) + .setParameter("voyageNumber", voyageNumber) + .getSingleResult(); + } + + @Override + public List findAll() { + return entityManager.createNamedQuery("Voyage.findAll", Voyage.class).getResultList(); + } } diff --git a/src/main/java/org/eclipse/cargotracker/infrastructure/persistence/jpa/package.html b/src/main/java/org/eclipse/cargotracker/infrastructure/persistence/jpa/package.html index 5afbefc8d..c915df05a 100644 --- a/src/main/java/org/eclipse/cargotracker/infrastructure/persistence/jpa/package.html +++ b/src/main/java/org/eclipse/cargotracker/infrastructure/persistence/jpa/package.html @@ -1,6 +1,6 @@ -

Jakarta Persistence implementations of the repository interfaces. This is part - of the infrastructure.

+

Jakarta Persistence implementations of the repository + interfaces. This is part of the infrastructure.

diff --git a/src/main/java/org/eclipse/cargotracker/infrastructure/routing/ExternalRoutingService.java b/src/main/java/org/eclipse/cargotracker/infrastructure/routing/ExternalRoutingService.java index 5830c5097..83c20e14e 100644 --- a/src/main/java/org/eclipse/cargotracker/infrastructure/routing/ExternalRoutingService.java +++ b/src/main/java/org/eclipse/cargotracker/infrastructure/routing/ExternalRoutingService.java @@ -29,71 +29,75 @@ import org.glassfish.jersey.moxy.json.MoxyJsonFeature; /** - * Our end of the routing service. This is basically a data model translation - * layer between our domain model and the API put forward by the routing team, - * which operates in a different context from us. + * Our end of the routing service. This is basically a data model translation layer between our + * domain model and the API put forward by the routing team, which operates in a different context + * from us. */ @Stateless public class ExternalRoutingService implements RoutingService { - @Inject - private Logger logger; - - @Resource(lookup = "java:app/configuration/GraphTraversalUrl") - private String graphTraversalUrl; - - private final Client jaxrsClient = ClientBuilder.newClient(); - private WebTarget graphTraversalResource; - - @Inject - private LocationRepository locationRepository; - @Inject - private VoyageRepository voyageRepository; - - @PostConstruct - public void init() { - graphTraversalResource = jaxrsClient.target(graphTraversalUrl); - graphTraversalResource.register(new MoxyJsonFeature()).register(new JsonMoxyConfigurationContextResolver()); - } - - @Override - public List fetchRoutesForSpecification(RouteSpecification routeSpecification) { - // The RouteSpecification is picked apart and adapted to the external API. - String origin = routeSpecification.getOrigin().getUnLocode().getIdString(); - String destination = routeSpecification.getDestination().getUnLocode().getIdString(); - - List transitPaths = graphTraversalResource.queryParam("origin", origin) - .queryParam("destination", destination).request(MediaType.APPLICATION_JSON_TYPE) - .get(new GenericType>() { - }); - - // The returned result is then translated back into our domain model. - List itineraries = new ArrayList<>(); - - for (TransitPath transitPath : transitPaths) { - Itinerary itinerary = toItinerary(transitPath); - // Use the specification to safe-guard against invalid itineraries - if (routeSpecification.isSatisfiedBy(itinerary)) { - itineraries.add(itinerary); - } else { - logger.log(Level.FINE, "Received itinerary that did not satisfy the route specification"); - } - } - - return itineraries; - } - - private Itinerary toItinerary(TransitPath transitPath) { - List legs = new ArrayList<>(transitPath.getTransitEdges().size()); - for (TransitEdge edge : transitPath.getTransitEdges()) { - legs.add(toLeg(edge)); - } - return new Itinerary(legs); - } - - private Leg toLeg(TransitEdge edge) { - return new Leg(voyageRepository.find(new VoyageNumber(edge.getVoyageNumber())), - locationRepository.find(new UnLocode(edge.getFromUnLocode())), - locationRepository.find(new UnLocode(edge.getToUnLocode())), edge.getFromDate(), edge.getToDate()); - } + @Inject private Logger logger; + + @Resource(lookup = "java:app/configuration/GraphTraversalUrl") + private String graphTraversalUrl; + + private final Client jaxrsClient = ClientBuilder.newClient(); + private WebTarget graphTraversalResource; + + @Inject private LocationRepository locationRepository; + @Inject private VoyageRepository voyageRepository; + + @PostConstruct + public void init() { + graphTraversalResource = jaxrsClient.target(graphTraversalUrl); + graphTraversalResource + .register(new MoxyJsonFeature()) + .register(new JsonMoxyConfigurationContextResolver()); + } + + @Override + public List fetchRoutesForSpecification(RouteSpecification routeSpecification) { + // The RouteSpecification is picked apart and adapted to the external API. + String origin = routeSpecification.getOrigin().getUnLocode().getIdString(); + String destination = routeSpecification.getDestination().getUnLocode().getIdString(); + + List transitPaths = + graphTraversalResource + .queryParam("origin", origin) + .queryParam("destination", destination) + .request(MediaType.APPLICATION_JSON_TYPE) + .get(new GenericType>() {}); + + // The returned result is then translated back into our domain model. + List itineraries = new ArrayList<>(); + + for (TransitPath transitPath : transitPaths) { + Itinerary itinerary = toItinerary(transitPath); + // Use the specification to safe-guard against invalid itineraries + if (routeSpecification.isSatisfiedBy(itinerary)) { + itineraries.add(itinerary); + } else { + logger.log(Level.FINE, "Received itinerary that did not satisfy the route specification"); + } + } + + return itineraries; + } + + private Itinerary toItinerary(TransitPath transitPath) { + List legs = new ArrayList<>(transitPath.getTransitEdges().size()); + for (TransitEdge edge : transitPath.getTransitEdges()) { + legs.add(toLeg(edge)); + } + return new Itinerary(legs); + } + + private Leg toLeg(TransitEdge edge) { + return new Leg( + voyageRepository.find(new VoyageNumber(edge.getVoyageNumber())), + locationRepository.find(new UnLocode(edge.getFromUnLocode())), + locationRepository.find(new UnLocode(edge.getToUnLocode())), + edge.getFromDate(), + edge.getToDate()); + } } diff --git a/src/main/java/org/eclipse/cargotracker/interfaces/booking/facade/BookingServiceFacade.java b/src/main/java/org/eclipse/cargotracker/interfaces/booking/facade/BookingServiceFacade.java index b9233af8b..b8748f653 100644 --- a/src/main/java/org/eclipse/cargotracker/interfaces/booking/facade/BookingServiceFacade.java +++ b/src/main/java/org/eclipse/cargotracker/interfaces/booking/facade/BookingServiceFacade.java @@ -9,29 +9,29 @@ import org.eclipse.cargotracker.interfaces.booking.facade.dto.RouteCandidate; /** - * This facade shields the domain layer - model, services, repositories - from - * concerns about such things as the user interface and remote communication. + * This facade shields the domain layer - model, services, repositories - from concerns about such + * things as the user interface and remote communication. */ public interface BookingServiceFacade { - String bookNewCargo(String origin, String destination, Date arrivalDeadline); + String bookNewCargo(String origin, String destination, Date arrivalDeadline); - CargoRoute loadCargoForRouting(String trackingId); + CargoRoute loadCargoForRouting(String trackingId); - CargoStatus loadCargoForTracking(String trackingId); + CargoStatus loadCargoForTracking(String trackingId); - void assignCargoToRoute(String trackingId, RouteCandidate route); + void assignCargoToRoute(String trackingId, RouteCandidate route); - void changeDestination(String trackingId, String destinationUnLocode); + void changeDestination(String trackingId, String destinationUnLocode); - void changeDeadline(String trackingId, Date arrivalDeadline); + void changeDeadline(String trackingId, Date arrivalDeadline); - List requestPossibleRoutesForCargo(String trackingId); + List requestPossibleRoutesForCargo(String trackingId); - List listShippingLocations(); + List listShippingLocations(); - // TODO [DDD] Is this the right DTO here? - List listAllCargos(); + // TODO [DDD] Is this the right DTO here? + List listAllCargos(); - List listAllTrackingIds(); + List listAllTrackingIds(); } diff --git a/src/main/java/org/eclipse/cargotracker/interfaces/booking/facade/dto/CargoRoute.java b/src/main/java/org/eclipse/cargotracker/interfaces/booking/facade/dto/CargoRoute.java index 1c789f90b..744b773b4 100644 --- a/src/main/java/org/eclipse/cargotracker/interfaces/booking/facade/dto/CargoRoute.java +++ b/src/main/java/org/eclipse/cargotracker/interfaces/booking/facade/dto/CargoRoute.java @@ -10,123 +10,135 @@ import org.eclipse.cargotracker.application.util.DateUtil; import org.eclipse.cargotracker.application.util.LocationUtil; -/** - * DTO for registering and routing a cargo. - */ +/** DTO for registering and routing a cargo. */ public class CargoRoute implements Serializable { - private static final long serialVersionUID = 1L; - - private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("MM/dd/yyyy hh:mm a z"); - - private final String trackingId; - private final String origin; - private final String finalDestination; - private final String arrivalDeadline; - private final boolean misrouted; - private final List legs; - private final boolean claimed; - private final String lastKnownLocation; - private final String transportStatus; - private String nextLocation; - - public CargoRoute(String trackingId, String origin, String finalDestination, Date arrivalDeadline, - boolean misrouted, boolean claimed, String lastKnownLocation, String transportStatus) { - this.trackingId = trackingId; - this.origin = origin; - this.finalDestination = finalDestination; - this.arrivalDeadline = DATE_FORMAT.format(arrivalDeadline); - this.misrouted = misrouted; - this.claimed = claimed; - this.lastKnownLocation = lastKnownLocation; - this.transportStatus = transportStatus; - this.legs = new ArrayList<>(); - } - - public String getTrackingId() { - return trackingId; - } - - public String getOrigin() { - return origin; - } - - public String getOriginName() { - // TODO [Clean Code] See if this can be done in a more DDD friendly way. - return LocationUtil.getLocationName(origin); - } - - public String getOriginCode() { - // TODO [Clean Code] See if this can be done in a more DDD friendly way. - return LocationUtil.getLocationCode(origin); - } - - public String getFinalDestination() { - return finalDestination; - } - - public String getFinalDestinationName() { - // TODO [Clean Code] See if this can be done in a more DDD friendly way. - return LocationUtil.getLocationName(finalDestination); - } - - public String getFinalDestinationCode() { - // TODO [Clean Code] See if this can be done in a more DDD friendly way. - return LocationUtil.getLocationCode(finalDestination); - } - - // TODO [Clean Code] See if this can be done in a more DDD friendly way. - public void addLeg(String voyageNumber, String fromUnLocode, String fromName, String toUnLocode, String toName, - Date loadTime, Date unloadTime) { - legs.add(new Leg(voyageNumber, fromUnLocode, fromName, toUnLocode, toName, loadTime, unloadTime)); - } - - public List getLegs() { - return Collections.unmodifiableList(legs); - } - - public boolean isMisrouted() { - return misrouted; - } - - public boolean isRouted() { - return !legs.isEmpty(); - } - - public String getArrivalDeadline() { - return arrivalDeadline; - } - - public String getArrivalDeadlineDate() { - return DateUtil.getDateFromDateTime(arrivalDeadline); - } - - public String getArrivalDeadlineTime() { - return DateUtil.getTimeFromDateTime(arrivalDeadline); - } - - public boolean isClaimed() { - return claimed; - } - - public String getLastKnownLocation() { - return this.lastKnownLocation; - } - - public String getLastKnownLocationName() { - return LocationUtil.getLocationName(lastKnownLocation); - } - - public String getLastKnownLocationCode() { - return LocationUtil.getLocationCode(lastKnownLocation); - } - - public String getTransportStatus() { - // TODO [Clean Code] This needs to be a richer status, with a more readable description. - return this.transportStatus; - } - - public String getNextLocation() { - return this.nextLocation; - } + private static final long serialVersionUID = 1L; + + private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("MM/dd/yyyy hh:mm a z"); + + private final String trackingId; + private final String origin; + private final String finalDestination; + private final String arrivalDeadline; + private final boolean misrouted; + private final List legs; + private final boolean claimed; + private final String lastKnownLocation; + private final String transportStatus; + private String nextLocation; + + public CargoRoute( + String trackingId, + String origin, + String finalDestination, + Date arrivalDeadline, + boolean misrouted, + boolean claimed, + String lastKnownLocation, + String transportStatus) { + this.trackingId = trackingId; + this.origin = origin; + this.finalDestination = finalDestination; + this.arrivalDeadline = DATE_FORMAT.format(arrivalDeadline); + this.misrouted = misrouted; + this.claimed = claimed; + this.lastKnownLocation = lastKnownLocation; + this.transportStatus = transportStatus; + this.legs = new ArrayList<>(); + } + + public String getTrackingId() { + return trackingId; + } + + public String getOrigin() { + return origin; + } + + public String getOriginName() { + // TODO [Clean Code] See if this can be done in a more DDD friendly way. + return LocationUtil.getLocationName(origin); + } + + public String getOriginCode() { + // TODO [Clean Code] See if this can be done in a more DDD friendly way. + return LocationUtil.getLocationCode(origin); + } + + public String getFinalDestination() { + return finalDestination; + } + + public String getFinalDestinationName() { + // TODO [Clean Code] See if this can be done in a more DDD friendly way. + return LocationUtil.getLocationName(finalDestination); + } + + public String getFinalDestinationCode() { + // TODO [Clean Code] See if this can be done in a more DDD friendly way. + return LocationUtil.getLocationCode(finalDestination); + } + + // TODO [Clean Code] See if this can be done in a more DDD friendly way. + public void addLeg( + String voyageNumber, + String fromUnLocode, + String fromName, + String toUnLocode, + String toName, + Date loadTime, + Date unloadTime) { + legs.add( + new Leg(voyageNumber, fromUnLocode, fromName, toUnLocode, toName, loadTime, unloadTime)); + } + + public List getLegs() { + return Collections.unmodifiableList(legs); + } + + public boolean isMisrouted() { + return misrouted; + } + + public boolean isRouted() { + return !legs.isEmpty(); + } + + public String getArrivalDeadline() { + return arrivalDeadline; + } + + public String getArrivalDeadlineDate() { + return DateUtil.getDateFromDateTime(arrivalDeadline); + } + + public String getArrivalDeadlineTime() { + return DateUtil.getTimeFromDateTime(arrivalDeadline); + } + + public boolean isClaimed() { + return claimed; + } + + public String getLastKnownLocation() { + return this.lastKnownLocation; + } + + public String getLastKnownLocationName() { + return LocationUtil.getLocationName(lastKnownLocation); + } + + public String getLastKnownLocationCode() { + return LocationUtil.getLocationCode(lastKnownLocation); + } + + public String getTransportStatus() { + // TODO [Clean Code] This needs to be a richer status, with a more readable description. + return this.transportStatus; + } + + public String getNextLocation() { + return this.nextLocation; + } } diff --git a/src/main/java/org/eclipse/cargotracker/interfaces/booking/facade/dto/CargoStatus.java b/src/main/java/org/eclipse/cargotracker/interfaces/booking/facade/dto/CargoStatus.java index e53adc251..45fa97837 100644 --- a/src/main/java/org/eclipse/cargotracker/interfaces/booking/facade/dto/CargoStatus.java +++ b/src/main/java/org/eclipse/cargotracker/interfaces/booking/facade/dto/CargoStatus.java @@ -6,51 +6,54 @@ public class CargoStatus { - private final String destination; - private final String statusText; - private final boolean misdirected; - private final String eta; - private final String nextExpectedActivity; - private final List events; - - public CargoStatus(String destination, String statusText, boolean misdirected, String eta, - String nextExpectedActivity, List handlingEvents) { - this.destination = destination; - this.statusText = statusText; - this.misdirected = misdirected; - this.eta = eta; - this.nextExpectedActivity = nextExpectedActivity; - this.events = new ArrayList<>(handlingEvents.size()); - - for (TrackingEvents handlingEvent : handlingEvents) { - events.add(handlingEvent); - } - } - - public String getDestination() { - return destination; - } - - /** - * @return A readable string describing the cargo status. - */ - public String getStatusText() { - return statusText; - } - - public boolean isMisdirected() { - return misdirected; - } - - public String getEta() { - return eta; - } - - public String getNextExpectedActivity() { - return nextExpectedActivity; - } - - public List getEvents() { - return Collections.unmodifiableList(events); - } + private final String destination; + private final String statusText; + private final boolean misdirected; + private final String eta; + private final String nextExpectedActivity; + private final List events; + + public CargoStatus( + String destination, + String statusText, + boolean misdirected, + String eta, + String nextExpectedActivity, + List handlingEvents) { + this.destination = destination; + this.statusText = statusText; + this.misdirected = misdirected; + this.eta = eta; + this.nextExpectedActivity = nextExpectedActivity; + this.events = new ArrayList<>(handlingEvents.size()); + + for (TrackingEvents handlingEvent : handlingEvents) { + events.add(handlingEvent); + } + } + + public String getDestination() { + return destination; + } + + /** @return A readable string describing the cargo status. */ + public String getStatusText() { + return statusText; + } + + public boolean isMisdirected() { + return misdirected; + } + + public String getEta() { + return eta; + } + + public String getNextExpectedActivity() { + return nextExpectedActivity; + } + + public List getEvents() { + return Collections.unmodifiableList(events); + } } diff --git a/src/main/java/org/eclipse/cargotracker/interfaces/booking/facade/dto/Leg.java b/src/main/java/org/eclipse/cargotracker/interfaces/booking/facade/dto/Leg.java index ee0b266a1..ea5633ab1 100644 --- a/src/main/java/org/eclipse/cargotracker/interfaces/booking/facade/dto/Leg.java +++ b/src/main/java/org/eclipse/cargotracker/interfaces/booking/facade/dto/Leg.java @@ -6,89 +6,103 @@ import org.eclipse.cargotracker.application.util.DateUtil; -/** - * DTO for a leg in an itinerary. - */ +/** DTO for a leg in an itinerary. */ public class Leg implements Serializable { - private static final long serialVersionUID = 1L; - - private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("MM/dd/yyyy hh:mm a z"); - - private final String voyageNumber; - private final String fromUnLocode; - private final String fromName; - private final String toUnLocode; - private final String toName; - private final String loadTime; - private final String unloadTime; - - public Leg(String voyageNumber, String fromUnLocode, String fromName, String toUnLocode, String toName, - Date loadTime, Date unloadTime) { - this.voyageNumber = voyageNumber; - this.fromUnLocode = fromUnLocode; - this.fromName = fromName; - this.toUnLocode = toUnLocode; - this.toName = toName; - this.loadTime = DATE_FORMAT.format(loadTime); - this.unloadTime = DATE_FORMAT.format(unloadTime); - } - - public String getVoyageNumber() { - return voyageNumber; - } - - public String getFrom() { - return fromName + " (" + fromUnLocode + ")"; - } - - public String getFromUnLocode() { - return fromUnLocode; - } - - public String getFromName() { - return fromName; - } - - public String getTo() { - return toUnLocode + " (" + toName + ")"; - } - - public String getToName() { - return toName; - } - - public String getToUnLocode() { - return toUnLocode; - } - - public String getLoadTime() { - return loadTime; - } - - public String getLoadTimeDate() { - return DateUtil.getDateFromDateTime(loadTime); - } - - public String getLoadTimeTime() { - return DateUtil.getTimeFromDateTime(loadTime); - } - - public String getUnloadTime() { - return unloadTime; - } - - public String getUnloadTimeTime() { - return DateUtil.getTimeFromDateTime(unloadTime); - } - - public String getUnloadTimeDate() { - return DateUtil.getDateFromDateTime(unloadTime); - } - - @Override - public String toString() { - return "Leg{" + "voyageNumber=" + voyageNumber + ", from=" + fromUnLocode + ", to=" + toUnLocode + ", loadTime=" - + loadTime + ", unloadTime=" + unloadTime + '}'; - } + private static final long serialVersionUID = 1L; + + private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("MM/dd/yyyy hh:mm a z"); + + private final String voyageNumber; + private final String fromUnLocode; + private final String fromName; + private final String toUnLocode; + private final String toName; + private final String loadTime; + private final String unloadTime; + + public Leg( + String voyageNumber, + String fromUnLocode, + String fromName, + String toUnLocode, + String toName, + Date loadTime, + Date unloadTime) { + this.voyageNumber = voyageNumber; + this.fromUnLocode = fromUnLocode; + this.fromName = fromName; + this.toUnLocode = toUnLocode; + this.toName = toName; + this.loadTime = DATE_FORMAT.format(loadTime); + this.unloadTime = DATE_FORMAT.format(unloadTime); + } + + public String getVoyageNumber() { + return voyageNumber; + } + + public String getFrom() { + return fromName + " (" + fromUnLocode + ")"; + } + + public String getFromUnLocode() { + return fromUnLocode; + } + + public String getFromName() { + return fromName; + } + + public String getTo() { + return toUnLocode + " (" + toName + ")"; + } + + public String getToName() { + return toName; + } + + public String getToUnLocode() { + return toUnLocode; + } + + public String getLoadTime() { + return loadTime; + } + + public String getLoadTimeDate() { + return DateUtil.getDateFromDateTime(loadTime); + } + + public String getLoadTimeTime() { + return DateUtil.getTimeFromDateTime(loadTime); + } + + public String getUnloadTime() { + return unloadTime; + } + + public String getUnloadTimeTime() { + return DateUtil.getTimeFromDateTime(unloadTime); + } + + public String getUnloadTimeDate() { + return DateUtil.getDateFromDateTime(unloadTime); + } + + @Override + public String toString() { + return "Leg{" + + "voyageNumber=" + + voyageNumber + + ", from=" + + fromUnLocode + + ", to=" + + toUnLocode + + ", loadTime=" + + loadTime + + ", unloadTime=" + + unloadTime + + '}'; + } } diff --git a/src/main/java/org/eclipse/cargotracker/interfaces/booking/facade/dto/Location.java b/src/main/java/org/eclipse/cargotracker/interfaces/booking/facade/dto/Location.java index 668e9b9c2..590ad25e9 100644 --- a/src/main/java/org/eclipse/cargotracker/interfaces/booking/facade/dto/Location.java +++ b/src/main/java/org/eclipse/cargotracker/interfaces/booking/facade/dto/Location.java @@ -2,29 +2,27 @@ import java.io.Serializable; -/** - * Location DTO. - */ +/** Location DTO. */ public class Location implements Serializable { - private static final long serialVersionUID = 1L; - private String unLocode; - private String name; + private static final long serialVersionUID = 1L; + private String unLocode; + private String name; - public Location(String unLocode, String name) { - this.unLocode = unLocode; - this.name = name; - } + public Location(String unLocode, String name) { + this.unLocode = unLocode; + this.name = name; + } - public String getUnLocode() { - return unLocode; - } + public String getUnLocode() { + return unLocode; + } - public String getName() { - return name + " (" + unLocode + ")"; - } + public String getName() { + return name + " (" + unLocode + ")"; + } - public String getNameOnly() { - return name; - } + public String getNameOnly() { + return name; + } } diff --git a/src/main/java/org/eclipse/cargotracker/interfaces/booking/facade/dto/RouteCandidate.java b/src/main/java/org/eclipse/cargotracker/interfaces/booking/facade/dto/RouteCandidate.java index ef6dade32..cdcb2f051 100644 --- a/src/main/java/org/eclipse/cargotracker/interfaces/booking/facade/dto/RouteCandidate.java +++ b/src/main/java/org/eclipse/cargotracker/interfaces/booking/facade/dto/RouteCandidate.java @@ -4,26 +4,23 @@ import java.util.Collections; import java.util.List; -/** - * DTO for presenting and selecting an itinerary from a collection of - * candidates. - */ +/** DTO for presenting and selecting an itinerary from a collection of candidates. */ public class RouteCandidate implements Serializable { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - private List legs; + private List legs; - public RouteCandidate(List legs) { - this.legs = legs; - } + public RouteCandidate(List legs) { + this.legs = legs; + } - public List getLegs() { - return Collections.unmodifiableList(legs); - } + public List getLegs() { + return Collections.unmodifiableList(legs); + } - @Override - public String toString() { - return "RouteCandidate{" + "legs=" + legs + '}'; - } + @Override + public String toString() { + return "RouteCandidate{" + "legs=" + legs + '}'; + } } diff --git a/src/main/java/org/eclipse/cargotracker/interfaces/booking/facade/dto/TrackingEvents.java b/src/main/java/org/eclipse/cargotracker/interfaces/booking/facade/dto/TrackingEvents.java index 659ff53c6..977ddfafd 100644 --- a/src/main/java/org/eclipse/cargotracker/interfaces/booking/facade/dto/TrackingEvents.java +++ b/src/main/java/org/eclipse/cargotracker/interfaces/booking/facade/dto/TrackingEvents.java @@ -2,23 +2,25 @@ public class TrackingEvents { - private final boolean expected; - private final String description; - private final String time; + private final boolean expected; + private final String description; + private final String time; - public TrackingEvents(boolean expected, String description, String time) { - this.expected = expected; - this.description = description; - this.time = time; - } + public TrackingEvents(boolean expected, String description, String time) { + this.expected = expected; + this.description = description; + this.time = time; + } - public boolean isExpected() { - return expected; - } + public boolean isExpected() { + return expected; + } - public String getDescription() { - return description; - } + public String getDescription() { + return description; + } - public String getTime() { return time; } + public String getTime() { + return time; + } } From 84b5c28005cb31ce49d17715914a6294c93e2683 Mon Sep 17 00:00:00 2001 From: Reza Rahman Date: Sun, 17 Jan 2021 10:05:47 -0500 Subject: [PATCH 07/22] Apply Google Java Style Guide --- .../internal/DefaultBookingServiceFacade.java | 215 +++++++------- .../assembler/CargoRouteDtoAssembler.java | 51 ++-- .../assembler/CargoStatusDtoAssembler.java | 151 +++++----- .../ItineraryCandidateDtoAssembler.java | 92 +++--- .../assembler/LocationDtoAssembler.java | 53 ++-- .../assembler/TrackingEventsDtoAssembler.java | 84 +++--- .../booking/rest/CargoMonitoringService.java | 62 ++-- .../socket/RealtimeCargoTrackingService.java | 69 +++-- .../interfaces/booking/web/Booking.java | 275 +++++++++--------- .../interfaces/booking/web/CargoDetails.java | 47 ++- .../web/ChangeArrivalDeadlineDate.java | 85 +++--- .../web/ChangeArrivalDeadlineDateDialog.java | 51 ++-- .../booking/web/ChangeDestination.java | 133 +++++---- .../booking/web/ChangeDestinationDialog.java | 51 ++-- .../interfaces/booking/web/DashboardView.java | 44 ++- .../booking/web/ItinerarySelection.java | 75 +++-- .../interfaces/booking/web/ListCargo.java | 108 ++++--- .../interfaces/booking/web/Registration.java | 151 +++++----- .../interfaces/booking/web/Track.java | 79 +++-- 19 files changed, 954 insertions(+), 922 deletions(-) diff --git a/src/main/java/org/eclipse/cargotracker/interfaces/booking/facade/internal/DefaultBookingServiceFacade.java b/src/main/java/org/eclipse/cargotracker/interfaces/booking/facade/internal/DefaultBookingServiceFacade.java index af712de71..5e89acc65 100644 --- a/src/main/java/org/eclipse/cargotracker/interfaces/booking/facade/internal/DefaultBookingServiceFacade.java +++ b/src/main/java/org/eclipse/cargotracker/interfaces/booking/facade/internal/DefaultBookingServiceFacade.java @@ -31,115 +31,116 @@ @ApplicationScoped public class DefaultBookingServiceFacade implements BookingServiceFacade, Serializable { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - @Inject - private BookingService bookingService; + @Inject private BookingService bookingService; - @Inject - private LocationRepository locationRepository; - - @Inject - private CargoRepository cargoRepository; + @Inject private LocationRepository locationRepository; - @Inject - private VoyageRepository voyageRepository; + @Inject private CargoRepository cargoRepository; + + @Inject private VoyageRepository voyageRepository; - @Inject - private HandlingEventRepository handlingEventRepository; - - @Override - public List listShippingLocations() { - List allLocations = locationRepository.findAll(); - LocationDtoAssembler assembler = new LocationDtoAssembler(); - return assembler.toDtoList(allLocations); - } - - @Override - public String bookNewCargo(String origin, String destination, Date arrivalDeadline) { - TrackingId trackingId = bookingService.bookNewCargo(new UnLocode(origin), new UnLocode(destination), - arrivalDeadline); - return trackingId.getIdString(); - } - - @Override - public CargoRoute loadCargoForRouting(String trackingId) { - Cargo cargo = cargoRepository.find(new TrackingId(trackingId)); - CargoRouteDtoAssembler assembler = new CargoRouteDtoAssembler(); - return assembler.toDto(cargo); - } - - @Override - public void assignCargoToRoute(String trackingIdStr, RouteCandidate routeCandidateDTO) { - Itinerary itinerary = new ItineraryCandidateDtoAssembler().fromDTO(routeCandidateDTO, voyageRepository, - locationRepository); - TrackingId trackingId = new TrackingId(trackingIdStr); - - bookingService.assignCargoToRoute(itinerary, trackingId); - } - - @Override - public void changeDestination(String trackingId, String destinationUnLocode) { - bookingService.changeDestination(new TrackingId(trackingId), new UnLocode(destinationUnLocode)); - } - - @Override - public void changeDeadline(String trackingId, Date arrivalDeadline) { - bookingService.changeDeadline(new TrackingId(trackingId), arrivalDeadline); - } - - @Override - // TODO [DDD] Is this the correct DTO here? - public List listAllCargos() { - List cargos = cargoRepository.findAll(); - List routes = new ArrayList<>(cargos.size()); - - CargoRouteDtoAssembler assembler = new CargoRouteDtoAssembler(); - - for (Cargo cargo : cargos) { - routes.add(assembler.toDto(cargo)); - } - - return routes; - } - - @Override - public List listAllTrackingIds() { - List trackingIds = new ArrayList<>(); - - for (Cargo cargo : cargoRepository.findAll()) - trackingIds.add(cargo.getTrackingId().getIdString()); - - return trackingIds; - } - - @Override - public CargoStatus loadCargoForTracking(String trackingIdValue) { - TrackingId trackingId = new TrackingId(trackingIdValue); - Cargo cargo = cargoRepository.find(trackingId); - - if (cargo == null) { - return null; - } - - CargoStatusDtoAssembler assembler = new CargoStatusDtoAssembler(); - - List handlingEvents = handlingEventRepository.lookupHandlingHistoryOfCargo(trackingId) - .getDistinctEventsByCompletionTime(); - - return assembler.toDto(cargo, handlingEvents); - } - - @Override - public List requestPossibleRoutesForCargo(String trackingId) { - List itineraries = bookingService.requestPossibleRoutesForCargo(new TrackingId(trackingId)); - - List routeCandidates = new ArrayList<>(itineraries.size()); - ItineraryCandidateDtoAssembler dtoAssembler = new ItineraryCandidateDtoAssembler(); - for (Itinerary itinerary : itineraries) { - routeCandidates.add(dtoAssembler.toDto(itinerary)); - } - - return routeCandidates; - } + @Inject private HandlingEventRepository handlingEventRepository; + + @Override + public List + listShippingLocations() { + List allLocations = locationRepository.findAll(); + LocationDtoAssembler assembler = new LocationDtoAssembler(); + return assembler.toDtoList(allLocations); + } + + @Override + public String bookNewCargo(String origin, String destination, Date arrivalDeadline) { + TrackingId trackingId = + bookingService.bookNewCargo( + new UnLocode(origin), new UnLocode(destination), arrivalDeadline); + return trackingId.getIdString(); + } + + @Override + public CargoRoute loadCargoForRouting(String trackingId) { + Cargo cargo = cargoRepository.find(new TrackingId(trackingId)); + CargoRouteDtoAssembler assembler = new CargoRouteDtoAssembler(); + return assembler.toDto(cargo); + } + + @Override + public void assignCargoToRoute(String trackingIdStr, RouteCandidate routeCandidateDTO) { + Itinerary itinerary = + new ItineraryCandidateDtoAssembler() + .fromDTO(routeCandidateDTO, voyageRepository, locationRepository); + TrackingId trackingId = new TrackingId(trackingIdStr); + + bookingService.assignCargoToRoute(itinerary, trackingId); + } + + @Override + public void changeDestination(String trackingId, String destinationUnLocode) { + bookingService.changeDestination(new TrackingId(trackingId), new UnLocode(destinationUnLocode)); + } + + @Override + public void changeDeadline(String trackingId, Date arrivalDeadline) { + bookingService.changeDeadline(new TrackingId(trackingId), arrivalDeadline); + } + + @Override + // TODO [DDD] Is this the correct DTO here? + public List listAllCargos() { + List cargos = cargoRepository.findAll(); + List routes = new ArrayList<>(cargos.size()); + + CargoRouteDtoAssembler assembler = new CargoRouteDtoAssembler(); + + for (Cargo cargo : cargos) { + routes.add(assembler.toDto(cargo)); + } + + return routes; + } + + @Override + public List listAllTrackingIds() { + List trackingIds = new ArrayList<>(); + + for (Cargo cargo : cargoRepository.findAll()) + trackingIds.add(cargo.getTrackingId().getIdString()); + + return trackingIds; + } + + @Override + public CargoStatus loadCargoForTracking(String trackingIdValue) { + TrackingId trackingId = new TrackingId(trackingIdValue); + Cargo cargo = cargoRepository.find(trackingId); + + if (cargo == null) { + return null; + } + + CargoStatusDtoAssembler assembler = new CargoStatusDtoAssembler(); + + List handlingEvents = + handlingEventRepository + .lookupHandlingHistoryOfCargo(trackingId) + .getDistinctEventsByCompletionTime(); + + return assembler.toDto(cargo, handlingEvents); + } + + @Override + public List requestPossibleRoutesForCargo(String trackingId) { + List itineraries = + bookingService.requestPossibleRoutesForCargo(new TrackingId(trackingId)); + + List routeCandidates = new ArrayList<>(itineraries.size()); + ItineraryCandidateDtoAssembler dtoAssembler = new ItineraryCandidateDtoAssembler(); + for (Itinerary itinerary : itineraries) { + routeCandidates.add(dtoAssembler.toDto(itinerary)); + } + + return routeCandidates; + } } diff --git a/src/main/java/org/eclipse/cargotracker/interfaces/booking/facade/internal/assembler/CargoRouteDtoAssembler.java b/src/main/java/org/eclipse/cargotracker/interfaces/booking/facade/internal/assembler/CargoRouteDtoAssembler.java index 0ed6994bd..7ef2790a2 100644 --- a/src/main/java/org/eclipse/cargotracker/interfaces/booking/facade/internal/assembler/CargoRouteDtoAssembler.java +++ b/src/main/java/org/eclipse/cargotracker/interfaces/booking/facade/internal/assembler/CargoRouteDtoAssembler.java @@ -9,25 +9,38 @@ // TODO [Clean Code] Convert to a singleton and inject? public class CargoRouteDtoAssembler { - public CargoRoute toDto(Cargo cargo) { - CargoRoute dto = new CargoRoute(cargo.getTrackingId().getIdString(), - cargo.getOrigin().getName() + " (" + cargo.getOrigin().getUnLocode().getIdString() + ")", - cargo.getRouteSpecification().getDestination().getName() + " (" - + cargo.getRouteSpecification().getDestination().getUnLocode().getIdString() + ")", - cargo.getRouteSpecification().getArrivalDeadline(), - cargo.getDelivery().getRoutingStatus().sameValueAs(RoutingStatus.MISROUTED), - cargo.getDelivery().getTransportStatus().sameValueAs(TransportStatus.CLAIMED), - cargo.getDelivery().getLastKnownLocation().getName() + " (" - + cargo.getDelivery().getLastKnownLocation().getUnLocode().getIdString() + ")", - cargo.getDelivery().getTransportStatus().name()); + public CargoRoute toDto(Cargo cargo) { + CargoRoute dto = + new CargoRoute( + cargo.getTrackingId().getIdString(), + cargo.getOrigin().getName() + + " (" + + cargo.getOrigin().getUnLocode().getIdString() + + ")", + cargo.getRouteSpecification().getDestination().getName() + + " (" + + cargo.getRouteSpecification().getDestination().getUnLocode().getIdString() + + ")", + cargo.getRouteSpecification().getArrivalDeadline(), + cargo.getDelivery().getRoutingStatus().sameValueAs(RoutingStatus.MISROUTED), + cargo.getDelivery().getTransportStatus().sameValueAs(TransportStatus.CLAIMED), + cargo.getDelivery().getLastKnownLocation().getName() + + " (" + + cargo.getDelivery().getLastKnownLocation().getUnLocode().getIdString() + + ")", + cargo.getDelivery().getTransportStatus().name()); - for (Leg leg : cargo.getItinerary().getLegs()) { - dto.addLeg(leg.getVoyage().getVoyageNumber().getIdString(), - leg.getLoadLocation().getUnLocode().getIdString(), leg.getLoadLocation().getName(), - leg.getUnloadLocation().getUnLocode().getIdString(), leg.getUnloadLocation().getName(), - leg.getLoadTime(), leg.getUnloadTime()); - } + for (Leg leg : cargo.getItinerary().getLegs()) { + dto.addLeg( + leg.getVoyage().getVoyageNumber().getIdString(), + leg.getLoadLocation().getUnLocode().getIdString(), + leg.getLoadLocation().getName(), + leg.getUnloadLocation().getUnLocode().getIdString(), + leg.getUnloadLocation().getName(), + leg.getLoadTime(), + leg.getUnloadTime()); + } - return dto; - } + return dto; + } } diff --git a/src/main/java/org/eclipse/cargotracker/interfaces/booking/facade/internal/assembler/CargoStatusDtoAssembler.java b/src/main/java/org/eclipse/cargotracker/interfaces/booking/facade/internal/assembler/CargoStatusDtoAssembler.java index e1bdd4d64..7a360684a 100644 --- a/src/main/java/org/eclipse/cargotracker/interfaces/booking/facade/internal/assembler/CargoStatusDtoAssembler.java +++ b/src/main/java/org/eclipse/cargotracker/interfaces/booking/facade/internal/assembler/CargoStatusDtoAssembler.java @@ -1,5 +1,10 @@ package org.eclipse.cargotracker.interfaces.booking.facade.internal.assembler; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + import org.eclipse.cargotracker.domain.model.cargo.Cargo; import org.eclipse.cargotracker.domain.model.cargo.Delivery; import org.eclipse.cargotracker.domain.model.cargo.HandlingActivity; @@ -7,76 +12,84 @@ import org.eclipse.cargotracker.interfaces.booking.facade.dto.CargoStatus; import org.eclipse.cargotracker.interfaces.booking.facade.dto.TrackingEvents; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - // TODO [Clean Code] Could this be a CDI singleton? public class CargoStatusDtoAssembler { - private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("MM/dd/yyyy hh:mm a z"); - - public CargoStatus toDto(Cargo cargo, List handlingEvents) { - List trackingEvents = new ArrayList<>(handlingEvents.size()); - - TrackingEventsDtoAssembler assembler = new TrackingEventsDtoAssembler(); - - for (HandlingEvent handlingEvent : handlingEvents) { - trackingEvents.add(assembler.toDto(cargo, handlingEvent)); - } - - return new CargoStatus(cargo.getRouteSpecification().getDestination().getName(), getCargoStatusText(cargo), - cargo.getDelivery().isMisdirected(), getEta(cargo), getNextExpectedActivity(cargo), trackingEvents); - } - - private String getCargoStatusText(Cargo cargo) { - Delivery delivery = cargo.getDelivery(); - - switch (delivery.getTransportStatus()) { - case IN_PORT: - return "In port " + delivery.getLastKnownLocation().getName(); - case ONBOARD_CARRIER: - return "Onboard voyage " + delivery.getCurrentVoyage().getVoyageNumber().getIdString(); - case CLAIMED: - return "Claimed"; - case NOT_RECEIVED: - return "Not received"; - case UNKNOWN: - return "Unknown"; - default: - return "[Unknown status]"; // Should never happen. - } - } - - private String getEta(Cargo cargo) { - Date eta = cargo.getDelivery().getEstimatedTimeOfArrival(); - - if (eta == null) { - return "?"; - } else { - return DATE_FORMAT.format(eta); - } - } - - private String getNextExpectedActivity(Cargo cargo) { - HandlingActivity activity = cargo.getDelivery().getNextExpectedActivity(); - - if ((activity == null) || (activity.isEmpty())) { - return ""; - } - - String text = "Next expected activity is to "; - HandlingEvent.Type type = activity.getType(); - - if (type.sameValueAs(HandlingEvent.Type.LOAD)) { - return text + type.name().toLowerCase() + " cargo onto voyage " + activity.getVoyage().getVoyageNumber() - + " in " + activity.getLocation().getName(); - } else if (type.sameValueAs(HandlingEvent.Type.UNLOAD)) { - return text + type.name().toLowerCase() + " cargo off of " + activity.getVoyage().getVoyageNumber() + " in " - + activity.getLocation().getName(); - } else { - return text + type.name().toLowerCase() + " cargo in " + activity.getLocation().getName(); - } - } + private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("MM/dd/yyyy hh:mm a z"); + + public CargoStatus toDto(Cargo cargo, List handlingEvents) { + List trackingEvents = new ArrayList<>(handlingEvents.size()); + + TrackingEventsDtoAssembler assembler = new TrackingEventsDtoAssembler(); + + for (HandlingEvent handlingEvent : handlingEvents) { + trackingEvents.add(assembler.toDto(cargo, handlingEvent)); + } + + return new CargoStatus( + cargo.getRouteSpecification().getDestination().getName(), + getCargoStatusText(cargo), + cargo.getDelivery().isMisdirected(), + getEta(cargo), + getNextExpectedActivity(cargo), + trackingEvents); + } + + private String getCargoStatusText(Cargo cargo) { + Delivery delivery = cargo.getDelivery(); + + switch (delivery.getTransportStatus()) { + case IN_PORT: + return "In port " + delivery.getLastKnownLocation().getName(); + case ONBOARD_CARRIER: + return "Onboard voyage " + delivery.getCurrentVoyage().getVoyageNumber().getIdString(); + case CLAIMED: + return "Claimed"; + case NOT_RECEIVED: + return "Not received"; + case UNKNOWN: + return "Unknown"; + default: + return "[Unknown status]"; // Should never happen. + } + } + + private String getEta(Cargo cargo) { + Date eta = cargo.getDelivery().getEstimatedTimeOfArrival(); + + if (eta == null) { + return "?"; + } else { + return DATE_FORMAT.format(eta); + } + } + + private String getNextExpectedActivity(Cargo cargo) { + HandlingActivity activity = cargo.getDelivery().getNextExpectedActivity(); + + if ((activity == null) || (activity.isEmpty())) { + return ""; + } + + String text = "Next expected activity is to "; + HandlingEvent.Type type = activity.getType(); + + if (type.sameValueAs(HandlingEvent.Type.LOAD)) { + return text + + type.name().toLowerCase() + + " cargo onto voyage " + + activity.getVoyage().getVoyageNumber() + + " in " + + activity.getLocation().getName(); + } else if (type.sameValueAs(HandlingEvent.Type.UNLOAD)) { + return text + + type.name().toLowerCase() + + " cargo off of " + + activity.getVoyage().getVoyageNumber() + + " in " + + activity.getLocation().getName(); + } else { + return text + type.name().toLowerCase() + " cargo in " + activity.getLocation().getName(); + } + } } diff --git a/src/main/java/org/eclipse/cargotracker/interfaces/booking/facade/internal/assembler/ItineraryCandidateDtoAssembler.java b/src/main/java/org/eclipse/cargotracker/interfaces/booking/facade/internal/assembler/ItineraryCandidateDtoAssembler.java index 714924934..aa48d4dad 100644 --- a/src/main/java/org/eclipse/cargotracker/interfaces/booking/facade/internal/assembler/ItineraryCandidateDtoAssembler.java +++ b/src/main/java/org/eclipse/cargotracker/interfaces/booking/facade/internal/assembler/ItineraryCandidateDtoAssembler.java @@ -15,46 +15,58 @@ import org.eclipse.cargotracker.domain.model.voyage.VoyageRepository; import org.eclipse.cargotracker.interfaces.booking.facade.dto.RouteCandidate; -//TODO [Clean Code] Could this be a CDI singleton? +// TODO [Clean Code] Could this be a CDI singleton? public class ItineraryCandidateDtoAssembler { - private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("MM/dd/yyyy hh:mm a z"); - - public RouteCandidate toDto(Itinerary itinerary) { - List legDTOs = new ArrayList<>( - itinerary.getLegs().size()); - for (Leg leg : itinerary.getLegs()) { - legDTOs.add(toLegDTO(leg)); - } - return new RouteCandidate(legDTOs); - } - - protected org.eclipse.cargotracker.interfaces.booking.facade.dto.Leg toLegDTO(Leg leg) { - VoyageNumber voyageNumber = leg.getVoyage().getVoyageNumber(); - return new org.eclipse.cargotracker.interfaces.booking.facade.dto.Leg(voyageNumber.getIdString(), - leg.getLoadLocation().getUnLocode().getIdString(), leg.getLoadLocation().getName(), - leg.getUnloadLocation().getUnLocode().getIdString(), leg.getUnloadLocation().getName(), - leg.getLoadTime(), leg.getUnloadTime()); - } - - public Itinerary fromDTO(RouteCandidate routeCandidateDTO, VoyageRepository voyageRepository, - LocationRepository locationRepository) { - List legs = new ArrayList<>(routeCandidateDTO.getLegs().size()); - - for (org.eclipse.cargotracker.interfaces.booking.facade.dto.Leg legDTO : routeCandidateDTO.getLegs()) { - VoyageNumber voyageNumber = new VoyageNumber(legDTO.getVoyageNumber()); - Voyage voyage = voyageRepository.find(voyageNumber); - Location from = locationRepository.find(new UnLocode(legDTO.getFromUnLocode())); - Location to = locationRepository.find(new UnLocode(legDTO.getToUnLocode())); - - try { - legs.add(new Leg(voyage, from, to, DATE_FORMAT.parse(legDTO.getLoadTime()), - DATE_FORMAT.parse(legDTO.getUnloadTime()))); - } catch (ParseException ex) { - throw new RuntimeException("Could not parse date", ex); - } - } - - return new Itinerary(legs); - } + private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("MM/dd/yyyy hh:mm a z"); + + public RouteCandidate toDto(Itinerary itinerary) { + List legDTOs = + new ArrayList<>(itinerary.getLegs().size()); + for (Leg leg : itinerary.getLegs()) { + legDTOs.add(toLegDTO(leg)); + } + return new RouteCandidate(legDTOs); + } + + protected org.eclipse.cargotracker.interfaces.booking.facade.dto.Leg toLegDTO(Leg leg) { + VoyageNumber voyageNumber = leg.getVoyage().getVoyageNumber(); + return new org.eclipse.cargotracker.interfaces.booking.facade.dto.Leg( + voyageNumber.getIdString(), + leg.getLoadLocation().getUnLocode().getIdString(), + leg.getLoadLocation().getName(), + leg.getUnloadLocation().getUnLocode().getIdString(), + leg.getUnloadLocation().getName(), + leg.getLoadTime(), + leg.getUnloadTime()); + } + + public Itinerary fromDTO( + RouteCandidate routeCandidateDTO, + VoyageRepository voyageRepository, + LocationRepository locationRepository) { + List legs = new ArrayList<>(routeCandidateDTO.getLegs().size()); + + for (org.eclipse.cargotracker.interfaces.booking.facade.dto.Leg legDTO : + routeCandidateDTO.getLegs()) { + VoyageNumber voyageNumber = new VoyageNumber(legDTO.getVoyageNumber()); + Voyage voyage = voyageRepository.find(voyageNumber); + Location from = locationRepository.find(new UnLocode(legDTO.getFromUnLocode())); + Location to = locationRepository.find(new UnLocode(legDTO.getToUnLocode())); + + try { + legs.add( + new Leg( + voyage, + from, + to, + DATE_FORMAT.parse(legDTO.getLoadTime()), + DATE_FORMAT.parse(legDTO.getUnloadTime()))); + } catch (ParseException ex) { + throw new RuntimeException("Could not parse date", ex); + } + } + + return new Itinerary(legs); + } } diff --git a/src/main/java/org/eclipse/cargotracker/interfaces/booking/facade/internal/assembler/LocationDtoAssembler.java b/src/main/java/org/eclipse/cargotracker/interfaces/booking/facade/internal/assembler/LocationDtoAssembler.java index 04cd90260..af33946b8 100644 --- a/src/main/java/org/eclipse/cargotracker/interfaces/booking/facade/internal/assembler/LocationDtoAssembler.java +++ b/src/main/java/org/eclipse/cargotracker/interfaces/booking/facade/internal/assembler/LocationDtoAssembler.java @@ -9,29 +9,32 @@ public class LocationDtoAssembler { - public org.eclipse.cargotracker.interfaces.booking.facade.dto.Location toDto(Location location) { - return new org.eclipse.cargotracker.interfaces.booking.facade.dto.Location(location.getUnLocode().getIdString(), - location.getName()); - } - - public List toDtoList( - List allLocations) { - List dtoList = new ArrayList<>( - allLocations.size()); - - for (Location location : allLocations) { - dtoList.add(toDto(location)); - } - - Collections.sort(dtoList, new Comparator() { - - @Override - public int compare(org.eclipse.cargotracker.interfaces.booking.facade.dto.Location location1, - org.eclipse.cargotracker.interfaces.booking.facade.dto.Location location2) { - return location1.getName().compareTo(location2.getName()); - } - }); - - return dtoList; - } + public org.eclipse.cargotracker.interfaces.booking.facade.dto.Location toDto(Location location) { + return new org.eclipse.cargotracker.interfaces.booking.facade.dto.Location( + location.getUnLocode().getIdString(), location.getName()); + } + + public List toDtoList( + List allLocations) { + List dtoList = + new ArrayList<>(allLocations.size()); + + for (Location location : allLocations) { + dtoList.add(toDto(location)); + } + + Collections.sort( + dtoList, + new Comparator() { + + @Override + public int compare( + org.eclipse.cargotracker.interfaces.booking.facade.dto.Location location1, + org.eclipse.cargotracker.interfaces.booking.facade.dto.Location location2) { + return location1.getName().compareTo(location2.getName()); + } + }); + + return dtoList; + } } diff --git a/src/main/java/org/eclipse/cargotracker/interfaces/booking/facade/internal/assembler/TrackingEventsDtoAssembler.java b/src/main/java/org/eclipse/cargotracker/interfaces/booking/facade/internal/assembler/TrackingEventsDtoAssembler.java index 264acecf9..02d2bf2a8 100644 --- a/src/main/java/org/eclipse/cargotracker/interfaces/booking/facade/internal/assembler/TrackingEventsDtoAssembler.java +++ b/src/main/java/org/eclipse/cargotracker/interfaces/booking/facade/internal/assembler/TrackingEventsDtoAssembler.java @@ -1,51 +1,53 @@ package org.eclipse.cargotracker.interfaces.booking.facade.internal.assembler; +import java.text.SimpleDateFormat; + import org.eclipse.cargotracker.domain.model.cargo.Cargo; import org.eclipse.cargotracker.domain.model.handling.HandlingEvent; import org.eclipse.cargotracker.domain.model.voyage.Voyage; import org.eclipse.cargotracker.interfaces.booking.facade.dto.TrackingEvents; -import java.text.SimpleDateFormat; - public class TrackingEventsDtoAssembler { - private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("MM/dd/yyyy hh:mm a z"); - - public TrackingEvents toDto(Cargo cargo, HandlingEvent handlingEvent) { - String location = locationFrom(handlingEvent); - HandlingEvent.Type type = handlingEvent.getType(); - String voyageNumber = voyageNumberFrom(handlingEvent); - return new TrackingEvents(cargo.getItinerary().isExpected(handlingEvent), - descriptionFrom(type, location, voyageNumber), timeFrom(handlingEvent)); - } - - private String timeFrom(HandlingEvent event) { - return DATE_FORMAT.format(event.getCompletionTime()); - } - - private String descriptionFrom(HandlingEvent.Type type, String location, String voyageNumber) { - switch (type) { - case LOAD: - return "Loaded onto voyage " + voyageNumber + " in " + location; - case UNLOAD: - return "Unloaded off voyage " + voyageNumber + " in " + location; - case RECEIVE: - return "Received in " + location; - case CLAIM: - return "Claimed in " + location; - case CUSTOMS: - return "Cleared customs in " + location; - default: - return "[Unknown]"; - } - } - - private String voyageNumberFrom(HandlingEvent handlingEvent) { - Voyage voyage = handlingEvent.getVoyage(); - return voyage.getVoyageNumber().getIdString(); - } - - private String locationFrom(HandlingEvent handlingEvent) { - return handlingEvent.getLocation().getName(); - } + private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("MM/dd/yyyy hh:mm a z"); + + public TrackingEvents toDto(Cargo cargo, HandlingEvent handlingEvent) { + String location = locationFrom(handlingEvent); + HandlingEvent.Type type = handlingEvent.getType(); + String voyageNumber = voyageNumberFrom(handlingEvent); + return new TrackingEvents( + cargo.getItinerary().isExpected(handlingEvent), + descriptionFrom(type, location, voyageNumber), + timeFrom(handlingEvent)); + } + + private String timeFrom(HandlingEvent event) { + return DATE_FORMAT.format(event.getCompletionTime()); + } + + private String descriptionFrom(HandlingEvent.Type type, String location, String voyageNumber) { + switch (type) { + case LOAD: + return "Loaded onto voyage " + voyageNumber + " in " + location; + case UNLOAD: + return "Unloaded off voyage " + voyageNumber + " in " + location; + case RECEIVE: + return "Received in " + location; + case CLAIM: + return "Claimed in " + location; + case CUSTOMS: + return "Cleared customs in " + location; + default: + return "[Unknown]"; + } + } + + private String voyageNumberFrom(HandlingEvent handlingEvent) { + Voyage voyage = handlingEvent.getVoyage(); + return voyage.getVoyageNumber().getIdString(); + } + + private String locationFrom(HandlingEvent handlingEvent) { + return handlingEvent.getLocation().getName(); + } } diff --git a/src/main/java/org/eclipse/cargotracker/interfaces/booking/rest/CargoMonitoringService.java b/src/main/java/org/eclipse/cargotracker/interfaces/booking/rest/CargoMonitoringService.java index 940ec8c6d..d05e10aae 100644 --- a/src/main/java/org/eclipse/cargotracker/interfaces/booking/rest/CargoMonitoringService.java +++ b/src/main/java/org/eclipse/cargotracker/interfaces/booking/rest/CargoMonitoringService.java @@ -20,34 +20,36 @@ @Path("/cargo") public class CargoMonitoringService { - public static final String ISO_8601_FORMAT = "yyyy-MM-dd HH:mm"; - - @Inject - private CargoRepository cargoRepository; - - @GET - @Produces(MediaType.APPLICATION_JSON) - public JsonArray getAllCargo() { - List cargos = cargoRepository.findAll(); - - JsonArrayBuilder builder = Json.createArrayBuilder(); - - for (Cargo cargo : cargos) { - builder.add(cargoToJson(cargo)); - } - - return builder.build(); - } - - private JsonObjectBuilder cargoToJson(Cargo cargo) { - return Json.createObjectBuilder().add("trackingId", cargo.getTrackingId().getIdString()) - .add("routingStatus", cargo.getDelivery().getRoutingStatus().toString()) - .add("misdirected", cargo.getDelivery().isMisdirected()) - .add("transportStatus", cargo.getDelivery().getTransportStatus().toString()) - .add("atDestination", cargo.getDelivery().isUnloadedAtDestination()) - .add("origin", cargo.getOrigin().getUnLocode().getIdString()).add("lastKnownLocation", - cargo.getDelivery().getLastKnownLocation().getUnLocode().getIdString().equals("XXXXX") - ? "Unknown" - : cargo.getDelivery().getLastKnownLocation().getUnLocode().getIdString()); - } + public static final String ISO_8601_FORMAT = "yyyy-MM-dd HH:mm"; + + @Inject private CargoRepository cargoRepository; + + @GET + @Produces(MediaType.APPLICATION_JSON) + public JsonArray getAllCargo() { + List cargos = cargoRepository.findAll(); + + JsonArrayBuilder builder = Json.createArrayBuilder(); + + for (Cargo cargo : cargos) { + builder.add(cargoToJson(cargo)); + } + + return builder.build(); + } + + private JsonObjectBuilder cargoToJson(Cargo cargo) { + return Json.createObjectBuilder() + .add("trackingId", cargo.getTrackingId().getIdString()) + .add("routingStatus", cargo.getDelivery().getRoutingStatus().toString()) + .add("misdirected", cargo.getDelivery().isMisdirected()) + .add("transportStatus", cargo.getDelivery().getTransportStatus().toString()) + .add("atDestination", cargo.getDelivery().isUnloadedAtDestination()) + .add("origin", cargo.getOrigin().getUnLocode().getIdString()) + .add( + "lastKnownLocation", + cargo.getDelivery().getLastKnownLocation().getUnLocode().getIdString().equals("XXXXX") + ? "Unknown" + : cargo.getDelivery().getLastKnownLocation().getUnLocode().getIdString()); + } } diff --git a/src/main/java/org/eclipse/cargotracker/interfaces/booking/socket/RealtimeCargoTrackingService.java b/src/main/java/org/eclipse/cargotracker/interfaces/booking/socket/RealtimeCargoTrackingService.java index c529cbc91..4520c0c45 100644 --- a/src/main/java/org/eclipse/cargotracker/interfaces/booking/socket/RealtimeCargoTrackingService.java +++ b/src/main/java/org/eclipse/cargotracker/interfaces/booking/socket/RealtimeCargoTrackingService.java @@ -21,50 +21,49 @@ import org.eclipse.cargotracker.domain.model.cargo.Cargo; import org.eclipse.cargotracker.infrastructure.events.cdi.CargoInspected; -/** - * WebSocket service for tracking all cargoes in real time. - */ +/** WebSocket service for tracking all cargoes in real time. */ @Singleton @ServerEndpoint("/tracking") public class RealtimeCargoTrackingService { - @Inject - private Logger logger; + @Inject private Logger logger; - private final Set sessions = new HashSet<>(); + private final Set sessions = new HashSet<>(); - @OnOpen - public void onOpen(final Session session) { - // Infinite by default on GlassFish. We need this principally for WebLogic. - session.setMaxIdleTimeout(5 * 60 * 1000); - sessions.add(session); - } + @OnOpen + public void onOpen(final Session session) { + // Infinite by default on GlassFish. We need this principally for WebLogic. + session.setMaxIdleTimeout(5 * 60 * 1000); + sessions.add(session); + } - @OnClose - public void onClose(final Session session) { - sessions.remove(session); - } + @OnClose + public void onClose(final Session session) { + sessions.remove(session); + } - public void onCargoInspected(@Observes @CargoInspected Cargo cargo) { - Writer writer = new StringWriter(); + public void onCargoInspected(@Observes @CargoInspected Cargo cargo) { + Writer writer = new StringWriter(); - try (JsonGenerator generator = Json.createGenerator(writer)) { - generator.writeStartObject().write("trackingId", cargo.getTrackingId().getIdString()) - .write("origin", cargo.getOrigin().getName()) - .write("destination", cargo.getRouteSpecification().getDestination().getName()) - .write("lastKnownLocation", cargo.getDelivery().getLastKnownLocation().getName()) - .write("transportStatus", cargo.getDelivery().getTransportStatus().toString()).writeEnd(); - } + try (JsonGenerator generator = Json.createGenerator(writer)) { + generator + .writeStartObject() + .write("trackingId", cargo.getTrackingId().getIdString()) + .write("origin", cargo.getOrigin().getName()) + .write("destination", cargo.getRouteSpecification().getDestination().getName()) + .write("lastKnownLocation", cargo.getDelivery().getLastKnownLocation().getName()) + .write("transportStatus", cargo.getDelivery().getTransportStatus().toString()) + .writeEnd(); + } - String jsonValue = writer.toString(); + String jsonValue = writer.toString(); - for (Session session : sessions) { - try { - session.getBasicRemote().sendText(jsonValue); - } catch (IOException ex) { - logger.log(Level.WARNING, "Unable to publish WebSocket message", ex); - } - } - - } + for (Session session : sessions) { + try { + session.getBasicRemote().sendText(jsonValue); + } catch (IOException ex) { + logger.log(Level.WARNING, "Unable to publish WebSocket message", ex); + } + } + } } diff --git a/src/main/java/org/eclipse/cargotracker/interfaces/booking/web/Booking.java b/src/main/java/org/eclipse/cargotracker/interfaces/booking/web/Booking.java index 78282a61d..4222020a9 100644 --- a/src/main/java/org/eclipse/cargotracker/interfaces/booking/web/Booking.java +++ b/src/main/java/org/eclipse/cargotracker/interfaces/booking/web/Booking.java @@ -23,141 +23,142 @@ @FlowScoped("booking") public class Booking implements Serializable { - private static final long serialVersionUID = 1L; - - private static final long MIN_JOURNEY_DURATION = 1; // Journey should be 1 day minimum. - private static final long GRACE_PERIOD = DateTimeConstants.MILLIS_PER_HOUR * 4; - - private Date today = null; - private List locations; - - private String originUnlocode; - private String originName; - private String destinationName; - private String destinationUnlocode; - private Date arrivalDeadline; - - private boolean bookable = false; - private long duration = -1; - - @Inject - private BookingServiceFacade bookingServiceFacade; - - @PostConstruct - public void init() { - today = LocalDate.now().toDate(); - locations = bookingServiceFacade.listShippingLocations(); - } - - public List getLocations() { - List filteredLocations = new ArrayList<>(); - String locationToRemove = null; - - // TODO [Jakarta EE 8] Use injection instead? - if (FacesContext.getCurrentInstance().getViewRoot().getViewId().endsWith("destination.xhtml")) { - // In the destination menu, origin can't be selected. - locationToRemove = originUnlocode; - } else { // Vice-versa. - if (destinationUnlocode != null) { - locationToRemove = destinationUnlocode; - } - } - - for (Location location : locations) { - if (!location.getUnLocode().equalsIgnoreCase(locationToRemove)) { - filteredLocations.add(location); - } - } - - return filteredLocations; - } - - public String getOriginUnlocode() { - return originUnlocode; - } - - public void setOriginUnlocode(String originUnlocode) { - this.originUnlocode = originUnlocode; - for (Location location : locations) { - if (location.getUnLocode().equalsIgnoreCase(originUnlocode)) { - this.originName = location.getNameOnly(); - } - } - } - - public String getOriginName() { - return originName; - } - - public String getDestinationUnlocode() { - return destinationUnlocode; - } - - public void setDestinationUnlocode(String destinationUnlocode) { - this.destinationUnlocode = destinationUnlocode; - for (Location location : locations) { - if (location.getUnLocode().equalsIgnoreCase(destinationUnlocode)) { - destinationName = location.getNameOnly(); - } - } - } - - public String getDestinationName() { - return destinationName; - } - - public Date getArrivalDeadline() { - return arrivalDeadline; - } - - public void setArrivalDeadline(Date arrivalDeadline) { - this.arrivalDeadline = arrivalDeadline; - } - - public Date getToday() { - return today; - } - - public long getDuration() { - return duration; - } - - public boolean isBookable() { - return bookable; - } - - public void deadlineUpdated() { - // TODO [Jakarta EE 8] Use Date-Time API instead. - duration = new Interval(today.getTime(), arrivalDeadline.getTime() + GRACE_PERIOD).toDuration() - .getStandardDays(); - - if (duration >= MIN_JOURNEY_DURATION) { - bookable = true; - } else { - bookable = false; - } - - PrimeFaces.current().ajax().update("dateForm:durationPanel"); - PrimeFaces.current().ajax().update("dateForm:bookBtn"); - } - - public String register() { - if (!originUnlocode.equals(destinationUnlocode)) { - bookingServiceFacade.bookNewCargo(originUnlocode, destinationUnlocode, arrivalDeadline); - } else { - // TODO [Jakarta EE 8] See if this can be injected. - FacesContext context = FacesContext.getCurrentInstance(); - // UI now prevents from selecting same origin/destination - FacesMessage message = new FacesMessage("Origin and destination cannot be the same."); - message.setSeverity(FacesMessage.SEVERITY_ERROR); - context.addMessage(null, message); - return null; - } - - return "/admin/dashboard.xhtml"; - } - - public String getReturnValue() { - return "/admin/dashboard.xhtml"; - } + private static final long serialVersionUID = 1L; + + private static final long MIN_JOURNEY_DURATION = 1; // Journey should be 1 day minimum. + private static final long GRACE_PERIOD = DateTimeConstants.MILLIS_PER_HOUR * 4; + + private Date today = null; + private List locations; + + private String originUnlocode; + private String originName; + private String destinationName; + private String destinationUnlocode; + private Date arrivalDeadline; + + private boolean bookable = false; + private long duration = -1; + + @Inject private BookingServiceFacade bookingServiceFacade; + + @PostConstruct + public void init() { + today = LocalDate.now().toDate(); + locations = bookingServiceFacade.listShippingLocations(); + } + + public List getLocations() { + List filteredLocations = new ArrayList<>(); + String locationToRemove = null; + + // TODO [Jakarta EE 8] Use injection instead? + if (FacesContext.getCurrentInstance().getViewRoot().getViewId().endsWith("destination.xhtml")) { + // In the destination menu, origin can't be selected. + locationToRemove = originUnlocode; + } else { // Vice-versa. + if (destinationUnlocode != null) { + locationToRemove = destinationUnlocode; + } + } + + for (Location location : locations) { + if (!location.getUnLocode().equalsIgnoreCase(locationToRemove)) { + filteredLocations.add(location); + } + } + + return filteredLocations; + } + + public String getOriginUnlocode() { + return originUnlocode; + } + + public void setOriginUnlocode(String originUnlocode) { + this.originUnlocode = originUnlocode; + for (Location location : locations) { + if (location.getUnLocode().equalsIgnoreCase(originUnlocode)) { + this.originName = location.getNameOnly(); + } + } + } + + public String getOriginName() { + return originName; + } + + public String getDestinationUnlocode() { + return destinationUnlocode; + } + + public void setDestinationUnlocode(String destinationUnlocode) { + this.destinationUnlocode = destinationUnlocode; + for (Location location : locations) { + if (location.getUnLocode().equalsIgnoreCase(destinationUnlocode)) { + destinationName = location.getNameOnly(); + } + } + } + + public String getDestinationName() { + return destinationName; + } + + public Date getArrivalDeadline() { + return arrivalDeadline; + } + + public void setArrivalDeadline(Date arrivalDeadline) { + this.arrivalDeadline = arrivalDeadline; + } + + public Date getToday() { + return today; + } + + public long getDuration() { + return duration; + } + + public boolean isBookable() { + return bookable; + } + + public void deadlineUpdated() { + // TODO [Jakarta EE 8] Use Date-Time API instead. + duration = + new Interval(today.getTime(), arrivalDeadline.getTime() + GRACE_PERIOD) + .toDuration() + .getStandardDays(); + + if (duration >= MIN_JOURNEY_DURATION) { + bookable = true; + } else { + bookable = false; + } + + PrimeFaces.current().ajax().update("dateForm:durationPanel"); + PrimeFaces.current().ajax().update("dateForm:bookBtn"); + } + + public String register() { + if (!originUnlocode.equals(destinationUnlocode)) { + bookingServiceFacade.bookNewCargo(originUnlocode, destinationUnlocode, arrivalDeadline); + } else { + // TODO [Jakarta EE 8] See if this can be injected. + FacesContext context = FacesContext.getCurrentInstance(); + // UI now prevents from selecting same origin/destination + FacesMessage message = new FacesMessage("Origin and destination cannot be the same."); + message.setSeverity(FacesMessage.SEVERITY_ERROR); + context.addMessage(null, message); + return null; + } + + return "/admin/dashboard.xhtml"; + } + + public String getReturnValue() { + return "/admin/dashboard.xhtml"; + } } diff --git a/src/main/java/org/eclipse/cargotracker/interfaces/booking/web/CargoDetails.java b/src/main/java/org/eclipse/cargotracker/interfaces/booking/web/CargoDetails.java index 588d6e87a..399c44c8f 100644 --- a/src/main/java/org/eclipse/cargotracker/interfaces/booking/web/CargoDetails.java +++ b/src/main/java/org/eclipse/cargotracker/interfaces/booking/web/CargoDetails.java @@ -8,39 +8,36 @@ import org.eclipse.cargotracker.interfaces.booking.facade.dto.CargoRoute; /** - * Handles viewing cargo details. Operates against a dedicated service facade, - * and could easily be rewritten as a thick Swing client. Completely separated - * from the domain layer, unlike the tracking user interface. - *

- * In order to successfully keep the domain model shielded from user interface - * considerations, this approach is generally preferred to the one taken in the - * tracking controller. However, there is never any one perfect solution for all - * situations, so we've chosen to demonstrate two polarized ways to build user - * interfaces. + * Handles viewing cargo details. Operates against a dedicated service facade, and could easily be + * rewritten as a thick Swing client. Completely separated from the domain layer, unlike the + * tracking user interface. * + *

In order to successfully keep the domain model shielded from user interface considerations, + * this approach is generally preferred to the one taken in the tracking controller. However, there + * is never any one perfect solution for all situations, so we've chosen to demonstrate two + * polarized ways to build user interfaces. */ @Named @RequestScoped public class CargoDetails { - private String trackingId; - private CargoRoute cargo; - @Inject - private BookingServiceFacade bookingServiceFacade; + private String trackingId; + private CargoRoute cargo; + @Inject private BookingServiceFacade bookingServiceFacade; - public String getTrackingId() { - return trackingId; - } + public String getTrackingId() { + return trackingId; + } - public void setTrackingId(String trackingId) { - this.trackingId = trackingId; - } + public void setTrackingId(String trackingId) { + this.trackingId = trackingId; + } - public CargoRoute getCargo() { - return cargo; - } + public CargoRoute getCargo() { + return cargo; + } - public void load() { - cargo = bookingServiceFacade.loadCargoForRouting(trackingId); - } + public void load() { + cargo = bookingServiceFacade.loadCargoForRouting(trackingId); + } } diff --git a/src/main/java/org/eclipse/cargotracker/interfaces/booking/web/ChangeArrivalDeadlineDate.java b/src/main/java/org/eclipse/cargotracker/interfaces/booking/web/ChangeArrivalDeadlineDate.java index ce2a842c1..fe7597389 100644 --- a/src/main/java/org/eclipse/cargotracker/interfaces/booking/web/ChangeArrivalDeadlineDate.java +++ b/src/main/java/org/eclipse/cargotracker/interfaces/booking/web/ChangeArrivalDeadlineDate.java @@ -15,62 +15,59 @@ import org.primefaces.PrimeFaces; /** - * Handles changing the cargo destination. Operates against a dedicated service - * facade, and could easily be rewritten as a thick Swing client. Completely - * separated from the domain layer, unlike the tracking user interface. - *

- * In order to successfully keep the domain model shielded from user interface - * considerations, this approach is generally preferred to the one taken in the - * tracking controller. However, there is never any one perfect solution for all - * situations, so we've chosen to demonstrate two polarized ways to build user - * interfaces. + * Handles changing the cargo destination. Operates against a dedicated service facade, and could + * easily be rewritten as a thick Swing client. Completely separated from the domain layer, unlike + * the tracking user interface. * + *

In order to successfully keep the domain model shielded from user interface considerations, + * this approach is generally preferred to the one taken in the tracking controller. However, there + * is never any one perfect solution for all situations, so we've chosen to demonstrate two + * polarized ways to build user interfaces. */ @Named @ViewScoped public class ChangeArrivalDeadlineDate implements Serializable { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - private String trackingId; - private CargoRoute cargo; - private Date arrivalDeadlineDate; + private String trackingId; + private CargoRoute cargo; + private Date arrivalDeadlineDate; - @Inject - private BookingServiceFacade bookingServiceFacade; + @Inject private BookingServiceFacade bookingServiceFacade; - public String getTrackingId() { - return trackingId; - } + public String getTrackingId() { + return trackingId; + } - public void setTrackingId(String trackingId) { - this.trackingId = trackingId; - } + public void setTrackingId(String trackingId) { + this.trackingId = trackingId; + } - public CargoRoute getCargo() { - return cargo; - } + public CargoRoute getCargo() { + return cargo; + } - public Date getArrivalDeadlineDate() { - return this.arrivalDeadlineDate; - } + public Date getArrivalDeadlineDate() { + return this.arrivalDeadlineDate; + } - public void setArrivalDeadlineDate(Date arrivalDeadlineDate) { - this.arrivalDeadlineDate = arrivalDeadlineDate; - } + public void setArrivalDeadlineDate(Date arrivalDeadlineDate) { + this.arrivalDeadlineDate = arrivalDeadlineDate; + } - public void load() { - cargo = bookingServiceFacade.loadCargoForRouting(trackingId); - DateFormat df = new SimpleDateFormat("MM/dd/yyyy"); - try { - arrivalDeadlineDate = df.parse(cargo.getArrivalDeadline()); - } catch (ParseException e) { - e.printStackTrace(); - } - } + public void load() { + cargo = bookingServiceFacade.loadCargoForRouting(trackingId); + DateFormat df = new SimpleDateFormat("MM/dd/yyyy"); + try { + arrivalDeadlineDate = df.parse(cargo.getArrivalDeadline()); + } catch (ParseException e) { + e.printStackTrace(); + } + } - public void changeArrivalDeadline() { - bookingServiceFacade.changeDeadline(trackingId, arrivalDeadlineDate); - PrimeFaces.current().dialog().closeDynamic("DONE"); - } -} \ No newline at end of file + public void changeArrivalDeadline() { + bookingServiceFacade.changeDeadline(trackingId, arrivalDeadlineDate); + PrimeFaces.current().dialog().closeDynamic("DONE"); + } +} diff --git a/src/main/java/org/eclipse/cargotracker/interfaces/booking/web/ChangeArrivalDeadlineDateDialog.java b/src/main/java/org/eclipse/cargotracker/interfaces/booking/web/ChangeArrivalDeadlineDateDialog.java index 0fc871c9f..3a4a6336a 100644 --- a/src/main/java/org/eclipse/cargotracker/interfaces/booking/web/ChangeArrivalDeadlineDateDialog.java +++ b/src/main/java/org/eclipse/cargotracker/interfaces/booking/web/ChangeArrivalDeadlineDateDialog.java @@ -16,29 +16,30 @@ @SessionScoped public class ChangeArrivalDeadlineDateDialog implements Serializable { - private static final long serialVersionUID = 1L; - - public void showDialog(String trackingId) { - Map options = new HashMap<>(); - options.put("modal", true); - options.put("draggable", true); - options.put("resizable", false); - options.put("contentWidth", 410); - options.put("contentHeight", 280); - - Map> params = new HashMap<>(); - List values = new ArrayList<>(); - values.add(trackingId); - params.put("trackingId", values); - - PrimeFaces.current().dialog().openDynamic("/admin/dialogs/changeArrivalDeadlineDate.xhtml", options, params); - } - - public void handleReturn(@SuppressWarnings("rawtypes") SelectEvent event) { - } - - public void cancel() { - // just kill the dialog - PrimeFaces.current().dialog().closeDynamic(""); - } + private static final long serialVersionUID = 1L; + + public void showDialog(String trackingId) { + Map options = new HashMap<>(); + options.put("modal", true); + options.put("draggable", true); + options.put("resizable", false); + options.put("contentWidth", 410); + options.put("contentHeight", 280); + + Map> params = new HashMap<>(); + List values = new ArrayList<>(); + values.add(trackingId); + params.put("trackingId", values); + + PrimeFaces.current() + .dialog() + .openDynamic("/admin/dialogs/changeArrivalDeadlineDate.xhtml", options, params); + } + + public void handleReturn(@SuppressWarnings("rawtypes") SelectEvent event) {} + + public void cancel() { + // just kill the dialog + PrimeFaces.current().dialog().closeDynamic(""); + } } diff --git a/src/main/java/org/eclipse/cargotracker/interfaces/booking/web/ChangeDestination.java b/src/main/java/org/eclipse/cargotracker/interfaces/booking/web/ChangeDestination.java index e11ac11c3..6243d869d 100644 --- a/src/main/java/org/eclipse/cargotracker/interfaces/booking/web/ChangeDestination.java +++ b/src/main/java/org/eclipse/cargotracker/interfaces/booking/web/ChangeDestination.java @@ -14,77 +14,76 @@ import org.primefaces.PrimeFaces; /** - * Handles changing the cargo destination. Operates against a dedicated service - * facade, and could easily be rewritten as a thick Swing client. Completely - * separated from the domain layer, unlike the tracking user interface. - *

- * In order to successfully keep the domain model shielded from user interface - * considerations, this approach is generally preferred to the one taken in the - * tracking controller. However, there is never any one perfect solution for all - * situations, so we've chosen to demonstrate two polarized ways to build user - * interfaces. + * Handles changing the cargo destination. Operates against a dedicated service facade, and could + * easily be rewritten as a thick Swing client. Completely separated from the domain layer, unlike + * the tracking user interface. * + *

In order to successfully keep the domain model shielded from user interface considerations, + * this approach is generally preferred to the one taken in the tracking controller. However, there + * is never any one perfect solution for all situations, so we've chosen to demonstrate two + * polarized ways to build user interfaces. */ @Named @ViewScoped public class ChangeDestination implements Serializable { - private static final long serialVersionUID = 1L; - - private String trackingId; - private CargoRoute cargo; - private List locations; - private String destinationUnlocode; - - @Inject - private BookingServiceFacade bookingServiceFacade; - - public String getTrackingId() { - return trackingId; - } - - public void setTrackingId(String trackingId) { - this.trackingId = trackingId; - } - - public CargoRoute getCargo() { - return cargo; - } - - public List getLocations() { - return locations; - } - - public List getPotentialDestinations() { - // Potential destination = All Locations - Origin - Current Destination - List destinationsToRemove = new ArrayList(); - for (Location loc : locations) { - if (loc.getName().equalsIgnoreCase(cargo.getOrigin()) - || loc.getName().equalsIgnoreCase(cargo.getFinalDestination())) { - destinationsToRemove.add(loc); - } - } - locations.removeAll(destinationsToRemove); - return locations; - } - - public String getDestinationUnlocode() { - return destinationUnlocode; - } - - public void setDestinationUnlocode(String destinationUnlocode) { - this.destinationUnlocode = destinationUnlocode; - } - - public void load() { - locations = bookingServiceFacade.listShippingLocations(); - cargo = bookingServiceFacade.loadCargoForRouting(trackingId); - } - - public void changeDestination() { - bookingServiceFacade.changeDestination(trackingId, destinationUnlocode); - // PF.current().dialog().closeDynamic("DONE"); - PrimeFaces.current().dialog().closeDynamic("DONE"); - // RequestContext.getCurrentInstance().closeDialog("DONE"); - } + private static final long serialVersionUID = 1L; + + private String trackingId; + private CargoRoute cargo; + private List locations; + private String destinationUnlocode; + + @Inject private BookingServiceFacade bookingServiceFacade; + + public String getTrackingId() { + return trackingId; + } + + public void setTrackingId(String trackingId) { + this.trackingId = trackingId; + } + + public CargoRoute getCargo() { + return cargo; + } + + public List getLocations() { + return locations; + } + + public List getPotentialDestinations() { + // Potential destination = All Locations - Origin - Current Destination + List destinationsToRemove = new ArrayList(); + for (Location loc : locations) { + if (loc.getName().equalsIgnoreCase(cargo.getOrigin()) + || loc.getName().equalsIgnoreCase(cargo.getFinalDestination())) { + destinationsToRemove.add(loc); + } + } + + locations.removeAll(destinationsToRemove); + + return locations; + } + + public String getDestinationUnlocode() { + return destinationUnlocode; + } + + public void setDestinationUnlocode(String destinationUnlocode) { + this.destinationUnlocode = destinationUnlocode; + } + + public void load() { + locations = bookingServiceFacade.listShippingLocations(); + cargo = bookingServiceFacade.loadCargoForRouting(trackingId); + } + + public void changeDestination() { + bookingServiceFacade.changeDestination(trackingId, destinationUnlocode); + // PF.current().dialog().closeDynamic("DONE"); + PrimeFaces.current().dialog().closeDynamic("DONE"); + // RequestContext.getCurrentInstance().closeDialog("DONE"); + } } diff --git a/src/main/java/org/eclipse/cargotracker/interfaces/booking/web/ChangeDestinationDialog.java b/src/main/java/org/eclipse/cargotracker/interfaces/booking/web/ChangeDestinationDialog.java index 353dbfb2e..57c423663 100644 --- a/src/main/java/org/eclipse/cargotracker/interfaces/booking/web/ChangeDestinationDialog.java +++ b/src/main/java/org/eclipse/cargotracker/interfaces/booking/web/ChangeDestinationDialog.java @@ -16,29 +16,30 @@ @SessionScoped public class ChangeDestinationDialog implements Serializable { - private static final long serialVersionUID = 1L; - - public void showDialog(String trackingId) { - Map options = new HashMap<>(); - options.put("modal", true); - options.put("draggable", true); - options.put("resizable", false); - options.put("contentWidth", 410); - options.put("contentHeight", 280); - - Map> params = new HashMap<>(); - List values = new ArrayList<>(); - values.add(trackingId); - params.put("trackingId", values); - - PrimeFaces.current().dialog().openDynamic("/admin/dialogs/changeDestination.xhtml", options, params); - } - - public void handleReturn(@SuppressWarnings("rawtypes") SelectEvent event) { - } - - public void cancel() { - // just kill the dialog - PrimeFaces.current().dialog().closeDynamic(""); - } + private static final long serialVersionUID = 1L; + + public void showDialog(String trackingId) { + Map options = new HashMap<>(); + options.put("modal", true); + options.put("draggable", true); + options.put("resizable", false); + options.put("contentWidth", 410); + options.put("contentHeight", 280); + + Map> params = new HashMap<>(); + List values = new ArrayList<>(); + values.add(trackingId); + params.put("trackingId", values); + + PrimeFaces.current() + .dialog() + .openDynamic("/admin/dialogs/changeDestination.xhtml", options, params); + } + + public void handleReturn(@SuppressWarnings("rawtypes") SelectEvent event) {} + + public void cancel() { + // just kill the dialog + PrimeFaces.current().dialog().closeDynamic(""); + } } diff --git a/src/main/java/org/eclipse/cargotracker/interfaces/booking/web/DashboardView.java b/src/main/java/org/eclipse/cargotracker/interfaces/booking/web/DashboardView.java index 3da9410b5..ff9a94ba2 100644 --- a/src/main/java/org/eclipse/cargotracker/interfaces/booking/web/DashboardView.java +++ b/src/main/java/org/eclipse/cargotracker/interfaces/booking/web/DashboardView.java @@ -14,35 +14,33 @@ @ViewScoped public class DashboardView implements Serializable { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - private DashboardModel model; + private DashboardModel model; - private String name = "TestDD"; + private String name = "TestDD"; - public String getName() { - return name; - } + public String getName() { + return name; + } - public DashboardView() { - // Initialize the dashboard model - this.model = new DefaultDashboardModel(); - DashboardColumn mainColumn = new DefaultDashboardColumn(); + public DashboardView() { + // Initialize the dashboard model + this.model = new DefaultDashboardModel(); + DashboardColumn mainColumn = new DefaultDashboardColumn(); - mainColumn.addWidget("Routed"); - mainColumn.addWidget("NotRouted"); - mainColumn.addWidget("Claimed"); + mainColumn.addWidget("Routed"); + mainColumn.addWidget("NotRouted"); + mainColumn.addWidget("Claimed"); - this.model.addColumn(mainColumn); + this.model.addColumn(mainColumn); + } - } - - public DashboardModel getModel() { - return model; - } - - public void setModel(DashboardModel model) { - this.model = model; - } + public DashboardModel getModel() { + return model; + } + public void setModel(DashboardModel model) { + this.model = model; + } } diff --git a/src/main/java/org/eclipse/cargotracker/interfaces/booking/web/ItinerarySelection.java b/src/main/java/org/eclipse/cargotracker/interfaces/booking/web/ItinerarySelection.java index a4b2706c0..a49ea1a13 100644 --- a/src/main/java/org/eclipse/cargotracker/interfaces/booking/web/ItinerarySelection.java +++ b/src/main/java/org/eclipse/cargotracker/interfaces/booking/web/ItinerarySelection.java @@ -12,59 +12,56 @@ import org.eclipse.cargotracker.interfaces.booking.facade.dto.RouteCandidate; /** - * Handles itinerary selection. Operates against a dedicated service facade, and - * could easily be rewritten as a thick Swing client. Completely separated from - * the domain layer, unlike the tracking user interface. - *

- * In order to successfully keep the domain model shielded from user interface - * considerations, this approach is generally preferred to the one taken in the - * tracking controller. However, there is never any one perfect solution for all - * situations, so we've chosen to demonstrate two polarized ways to build user - * interfaces. + * Handles itinerary selection. Operates against a dedicated service facade, and could easily be + * rewritten as a thick Swing client. Completely separated from the domain layer, unlike the + * tracking user interface. * + *

In order to successfully keep the domain model shielded from user interface considerations, + * this approach is generally preferred to the one taken in the tracking controller. However, there + * is never any one perfect solution for all situations, so we've chosen to demonstrate two + * polarized ways to build user interfaces. */ @Named @ViewScoped public class ItinerarySelection implements Serializable { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - private String trackingId; - private CargoRoute cargo; - List routeCandidates; + private String trackingId; + private CargoRoute cargo; + List routeCandidates; - @Inject - private BookingServiceFacade bookingServiceFacade; + @Inject private BookingServiceFacade bookingServiceFacade; - public List getRouteCandidates() { - return routeCandidates; - } + public List getRouteCandidates() { + return routeCandidates; + } - public String getTrackingId() { - return trackingId; - } + public String getTrackingId() { + return trackingId; + } - public void setTrackingId(String trackingId) { - this.trackingId = trackingId; - } + public void setTrackingId(String trackingId) { + this.trackingId = trackingId; + } - public CargoRoute getCargo() { - return cargo; - } + public CargoRoute getCargo() { + return cargo; + } - public List getRouteCanditates() { - return routeCandidates; - } + public List getRouteCanditates() { + return routeCandidates; + } - public void load() { - cargo = bookingServiceFacade.loadCargoForRouting(trackingId); - routeCandidates = bookingServiceFacade.requestPossibleRoutesForCargo(trackingId); - } + public void load() { + cargo = bookingServiceFacade.loadCargoForRouting(trackingId); + routeCandidates = bookingServiceFacade.requestPossibleRoutesForCargo(trackingId); + } - public String assignItinerary(int routeIndex) { - RouteCandidate route = routeCandidates.get(routeIndex); - bookingServiceFacade.assignCargoToRoute(trackingId, route); + public String assignItinerary(int routeIndex) { + RouteCandidate route = routeCandidates.get(routeIndex); + bookingServiceFacade.assignCargoToRoute(trackingId, route); - return "show.html?faces-redirect=true&trackingId=" + trackingId; - } + return "show.html?faces-redirect=true&trackingId=" + trackingId; + } } diff --git a/src/main/java/org/eclipse/cargotracker/interfaces/booking/web/ListCargo.java b/src/main/java/org/eclipse/cargotracker/interfaces/booking/web/ListCargo.java index 02705c5a0..5e8ab166a 100644 --- a/src/main/java/org/eclipse/cargotracker/interfaces/booking/web/ListCargo.java +++ b/src/main/java/org/eclipse/cargotracker/interfaces/booking/web/ListCargo.java @@ -12,79 +12,75 @@ import org.eclipse.cargotracker.interfaces.booking.facade.dto.CargoRoute; /** - * Handles listing cargo. Operates against a dedicated service facade, and could - * easily be rewritten as a thick Swing client. Completely separated from the - * domain layer, unlike the tracking user interface. - *

- * In order to successfully keep the domain model shielded from user interface - * considerations, this approach is generally preferred to the one taken in the - * tracking controller. However, there is never any one perfect solution for all - * situations, so we've chosen to demonstrate two polarized ways to build user - * interfaces. + * Handles listing cargo. Operates against a dedicated service facade, and could easily be rewritten + * as a thick Swing client. Completely separated from the domain layer, unlike the tracking user + * interface. + * + *

In order to successfully keep the domain model shielded from user interface considerations, + * this approach is generally preferred to the one taken in the tracking controller. However, there + * is never any one perfect solution for all situations, so we've chosen to demonstrate two + * polarized ways to build user interfaces. */ @Named @RequestScoped public class ListCargo { - private List cargos; - private List routedCargos; - private List claimedCargos; - private List routedUnclaimedCargos; + private List cargos; + private List routedCargos; + private List claimedCargos; + private List routedUnclaimedCargos; - @Inject - private BookingServiceFacade bookingServiceFacade; + @Inject private BookingServiceFacade bookingServiceFacade; - public List getCargos() { - return cargos; - } + public List getCargos() { + return cargos; + } - @PostConstruct - public void init() { - cargos = bookingServiceFacade.listAllCargos(); - } + @PostConstruct + public void init() { + cargos = bookingServiceFacade.listAllCargos(); + } - public List getRoutedCargos() { - routedCargos = new ArrayList<>(); + public List getRoutedCargos() { + routedCargos = new ArrayList<>(); - for (CargoRoute route : cargos) { - if (route.isRouted()) { - routedCargos.add(route); - } - } + for (CargoRoute route : cargos) { + if (route.isRouted()) { + routedCargos.add(route); + } + } - return routedCargos; - } + return routedCargos; + } - public List getRoutedUnclaimedCargos() { - routedUnclaimedCargos = new ArrayList<>(); - for (CargoRoute route : cargos) { - if (route.isRouted() && !route.isClaimed()) { - routedUnclaimedCargos.add(route); - } - } + public List getRoutedUnclaimedCargos() { + routedUnclaimedCargos = new ArrayList<>(); + for (CargoRoute route : cargos) { + if (route.isRouted() && !route.isClaimed()) { + routedUnclaimedCargos.add(route); + } + } - return routedUnclaimedCargos; - } + return routedUnclaimedCargos; + } - public List getClaimedCargos() { - claimedCargos = new ArrayList<>(); + public List getClaimedCargos() { + claimedCargos = new ArrayList<>(); - for (CargoRoute route : cargos) { - if (route.isClaimed()) { - claimedCargos.add(route); - } - } + for (CargoRoute route : cargos) { + if (route.isClaimed()) { + claimedCargos.add(route); + } + } - return claimedCargos; - } + return claimedCargos; + } - public List getNotRoutedCargos() { - List notRoutedCargos = new ArrayList<>(); + public List getNotRoutedCargos() { + List notRoutedCargos = new ArrayList<>(); - for (CargoRoute route : cargos) - if (!route.isRouted()) - notRoutedCargos.add(route); + for (CargoRoute route : cargos) if (!route.isRouted()) notRoutedCargos.add(route); - return notRoutedCargos; - } + return notRoutedCargos; + } } diff --git a/src/main/java/org/eclipse/cargotracker/interfaces/booking/web/Registration.java b/src/main/java/org/eclipse/cargotracker/interfaces/booking/web/Registration.java index 19f5a35b7..1605c5bef 100644 --- a/src/main/java/org/eclipse/cargotracker/interfaces/booking/web/Registration.java +++ b/src/main/java/org/eclipse/cargotracker/interfaces/booking/web/Registration.java @@ -16,84 +16,85 @@ import org.eclipse.cargotracker.interfaces.booking.facade.dto.Location; /** - * Handles registering cargo. Operates against a dedicated service facade, and - * could easily be rewritten as a thick Swing client. Completely separated from - * the domain layer, unlike the tracking user interface. - *

- * In order to successfully keep the domain model shielded from user interface - * considerations, this approach is generally preferred to the one taken in the - * tracking controller. However, there is never any one perfect solution for all - * situations, so we've chosen to demonstrate two polarized ways to build user - * interfaces. + * Handles registering cargo. Operates against a dedicated service facade, and could easily be + * rewritten as a thick Swing client. Completely separated from the domain layer, unlike the + * tracking user interface. + * + *

In order to successfully keep the domain model shielded from user interface considerations, + * this approach is generally preferred to the one taken in the tracking controller. However, there + * is never any one perfect solution for all situations, so we've chosen to demonstrate two + * polarized ways to build user interfaces. */ @Named @ViewScoped public class Registration implements Serializable { - private static final long serialVersionUID = 1L; - - private static final String FORMAT = "yyyy-MM-dd"; - - List locations; - private String arrivalDeadline; - private String originUnlocode; - private String destinationUnlocode; - - @Inject - private BookingServiceFacade bookingServiceFacade; - - public List getLocations() { - return locations; - } - - public String getArrivalDeadline() { - return arrivalDeadline; - } - - public void setArrivalDeadline(String arrivalDeadline) { - this.arrivalDeadline = arrivalDeadline; - } - - public String getOriginUnlocode() { - return originUnlocode; - } - - public void setOriginUnlocode(String originUnlocode) { - this.originUnlocode = originUnlocode; - } - - public String getDestinationUnlocode() { - return destinationUnlocode; - } - - public void setDestinationUnlocode(String destinationUnlocode) { - this.destinationUnlocode = destinationUnlocode; - } - - @PostConstruct - public void init() { - locations = bookingServiceFacade.listShippingLocations(); - } - - public String register() { - String trackingId = null; - - try { - if (!originUnlocode.equals(destinationUnlocode)) { - trackingId = bookingServiceFacade.bookNewCargo(originUnlocode, destinationUnlocode, - new SimpleDateFormat(FORMAT).parse(arrivalDeadline)); - } else { - // TODO [Jakarta EE 8] See if this can be injected. - FacesContext context = FacesContext.getCurrentInstance(); - FacesMessage message = new FacesMessage("Origin and destination cannot be the same."); - message.setSeverity(FacesMessage.SEVERITY_ERROR); - context.addMessage(null, message); - return null; - } - } catch (ParseException e) { - throw new RuntimeException("Error parsing date", e); - } - - return "show.xhtml?faces-redirect=true&trackingId=" + trackingId; - } + private static final long serialVersionUID = 1L; + + private static final String FORMAT = "yyyy-MM-dd"; + + List locations; + private String arrivalDeadline; + private String originUnlocode; + private String destinationUnlocode; + + @Inject private BookingServiceFacade bookingServiceFacade; + + public List getLocations() { + return locations; + } + + public String getArrivalDeadline() { + return arrivalDeadline; + } + + public void setArrivalDeadline(String arrivalDeadline) { + this.arrivalDeadline = arrivalDeadline; + } + + public String getOriginUnlocode() { + return originUnlocode; + } + + public void setOriginUnlocode(String originUnlocode) { + this.originUnlocode = originUnlocode; + } + + public String getDestinationUnlocode() { + return destinationUnlocode; + } + + public void setDestinationUnlocode(String destinationUnlocode) { + this.destinationUnlocode = destinationUnlocode; + } + + @PostConstruct + public void init() { + locations = bookingServiceFacade.listShippingLocations(); + } + + public String register() { + String trackingId = null; + + try { + if (!originUnlocode.equals(destinationUnlocode)) { + trackingId = + bookingServiceFacade.bookNewCargo( + originUnlocode, + destinationUnlocode, + new SimpleDateFormat(FORMAT).parse(arrivalDeadline)); + } else { + // TODO [Jakarta EE 8] See if this can be injected. + FacesContext context = FacesContext.getCurrentInstance(); + FacesMessage message = new FacesMessage("Origin and destination cannot be the same."); + message.setSeverity(FacesMessage.SEVERITY_ERROR); + context.addMessage(null, message); + return null; + } + } catch (ParseException e) { + throw new RuntimeException("Error parsing date", e); + } + + return "show.xhtml?faces-redirect=true&trackingId=" + trackingId; + } } diff --git a/src/main/java/org/eclipse/cargotracker/interfaces/booking/web/Track.java b/src/main/java/org/eclipse/cargotracker/interfaces/booking/web/Track.java index 3234a16c5..923150892 100644 --- a/src/main/java/org/eclipse/cargotracker/interfaces/booking/web/Track.java +++ b/src/main/java/org/eclipse/cargotracker/interfaces/booking/web/Track.java @@ -14,58 +14,57 @@ import org.eclipse.cargotracker.interfaces.booking.facade.dto.CargoStatus; /** - * Handles tracking cargo. Operates against a dedicated service facade, and - * could easily be rewritten as a thick Swing client. Completely separated from - * the domain layer, unlike the public tracking user interface. - *

- * In order to successfully keep the domain model shielded from user interface - * considerations, this approach is generally preferred to the one taken in the - * public tracking controller. However, there is never any one perfect solution - * for all situations, so we've chosen to demonstrate two polarized ways to - * build user interfaces. + * Handles tracking cargo. Operates against a dedicated service facade, and could easily be + * rewritten as a thick Swing client. Completely separated from the domain layer, unlike the public + * tracking user interface. + * + *

In order to successfully keep the domain model shielded from user interface considerations, + * this approach is generally preferred to the one taken in the public tracking controller. However, + * there is never any one perfect solution for all situations, so we've chosen to demonstrate two + * polarized ways to build user interfaces. */ @Named("admin.track") @ViewScoped public class Track implements Serializable { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - @Inject - private BookingServiceFacade bookingServiceFacade; + @Inject private BookingServiceFacade bookingServiceFacade; - private List trackingIds; - private String trackingId; - private CargoStatus cargo; + private List trackingIds; + private String trackingId; + private CargoStatus cargo; - public List getTrackingIds(String query) { - return trackingIds; - } + public List getTrackingIds(String query) { + return trackingIds; + } - public String getTrackingId() { - return trackingId; - } + public String getTrackingId() { + return trackingId; + } - public void setTrackingId(String trackingId) { - this.trackingId = trackingId; - } + public void setTrackingId(String trackingId) { + this.trackingId = trackingId; + } - public CargoStatus getCargo() { - return this.cargo; - } + public CargoStatus getCargo() { + return this.cargo; + } - @PostConstruct - public void init() { - trackingIds = bookingServiceFacade.listAllTrackingIds(); - } + @PostConstruct + public void init() { + trackingIds = bookingServiceFacade.listAllTrackingIds(); + } - public void onTrackById() { - cargo = bookingServiceFacade.loadCargoForTracking(this.trackingId); + public void onTrackById() { + cargo = bookingServiceFacade.loadCargoForTracking(this.trackingId); - if (cargo == null) { - FacesContext context = FacesContext.getCurrentInstance(); - FacesMessage message = new FacesMessage("Cargo with tracking ID: " + this.trackingId + " not found."); - message.setSeverity(FacesMessage.SEVERITY_ERROR); - context.addMessage(null, message); - } - } + if (cargo == null) { + FacesContext context = FacesContext.getCurrentInstance(); + FacesMessage message = + new FacesMessage("Cargo with tracking ID: " + this.trackingId + " not found."); + message.setSeverity(FacesMessage.SEVERITY_ERROR); + context.addMessage(null, message); + } + } } From 353db0712ed8055e37f1c2caf272361eabc287a9 Mon Sep 17 00:00:00 2001 From: Reza Rahman Date: Sun, 17 Jan 2021 10:12:09 -0500 Subject: [PATCH 08/22] Apply Google Java Style Guide --- .../HandlingEventRegistrationAttempt.java | 104 +++--- .../handling/file/EventFilesCheckpoint.java | 70 ++-- .../handling/file/EventItemReader.java | 259 +++++++------- .../handling/file/EventItemWriter.java | 81 +++-- .../file/EventLineParseException.java | 26 +- .../file/FileProcessorJobListener.java | 26 +- .../file/LineParseExceptionListener.java | 62 ++-- .../handling/file/UploadDirectoryScanner.java | 19 +- .../handling/mobile/EventLogger.java | 311 ++++++++-------- .../handling/rest/HandlingReport.java | 116 +++--- .../handling/rest/HandlingReportService.java | 59 ++- .../web/CargoTrackingViewAdapter.java | 337 +++++++++--------- .../interfaces/tracking/web/Track.java | 93 +++-- .../pathfinder/api/GraphTraversalService.java | 150 ++++---- .../eclipse/pathfinder/api/TransitEdge.java | 146 ++++---- .../eclipse/pathfinder/api/TransitPath.java | 36 +- .../eclipse/pathfinder/internal/GraphDao.java | 52 +-- 17 files changed, 1001 insertions(+), 946 deletions(-) diff --git a/src/main/java/org/eclipse/cargotracker/interfaces/handling/HandlingEventRegistrationAttempt.java b/src/main/java/org/eclipse/cargotracker/interfaces/handling/HandlingEventRegistrationAttempt.java index 8c418bb03..68ce61cff 100644 --- a/src/main/java/org/eclipse/cargotracker/interfaces/handling/HandlingEventRegistrationAttempt.java +++ b/src/main/java/org/eclipse/cargotracker/interfaces/handling/HandlingEventRegistrationAttempt.java @@ -9,60 +9,76 @@ import org.eclipse.cargotracker.domain.model.voyage.VoyageNumber; /** - * This is a simple transfer object for passing incoming handling event - * registration attempts to the proper registration procedure. - *

- * It is used as a message queue element. + * This is a simple transfer object for passing incoming handling event registration attempts to the + * proper registration procedure. + * + *

It is used as a message queue element. */ public class HandlingEventRegistrationAttempt implements Serializable { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - private final Date registrationTime; - private final Date completionTime; - private final TrackingId trackingId; - private final VoyageNumber voyageNumber; - private final HandlingEvent.Type type; - private final UnLocode unLocode; + private final Date registrationTime; + private final Date completionTime; + private final TrackingId trackingId; + private final VoyageNumber voyageNumber; + private final HandlingEvent.Type type; + private final UnLocode unLocode; - public HandlingEventRegistrationAttempt(Date registrationDate, Date completionDate, TrackingId trackingId, - VoyageNumber voyageNumber, HandlingEvent.Type type, UnLocode unLocode) { - this.registrationTime = registrationDate; - this.completionTime = completionDate; - this.trackingId = trackingId; - this.voyageNumber = voyageNumber; - this.type = type; - this.unLocode = unLocode; - } + public HandlingEventRegistrationAttempt( + Date registrationDate, + Date completionDate, + TrackingId trackingId, + VoyageNumber voyageNumber, + HandlingEvent.Type type, + UnLocode unLocode) { + this.registrationTime = registrationDate; + this.completionTime = completionDate; + this.trackingId = trackingId; + this.voyageNumber = voyageNumber; + this.type = type; + this.unLocode = unLocode; + } - public Date getCompletionTime() { - return new Date(completionTime.getTime()); - } + public Date getCompletionTime() { + return new Date(completionTime.getTime()); + } - public TrackingId getTrackingId() { - return trackingId; - } + public TrackingId getTrackingId() { + return trackingId; + } - public VoyageNumber getVoyageNumber() { - return voyageNumber; - } + public VoyageNumber getVoyageNumber() { + return voyageNumber; + } - public HandlingEvent.Type getType() { - return type; - } + public HandlingEvent.Type getType() { + return type; + } - public UnLocode getUnLocode() { - return unLocode; - } + public UnLocode getUnLocode() { + return unLocode; + } - public Date getRegistrationTime() { - return registrationTime; - } + public Date getRegistrationTime() { + return registrationTime; + } - @Override - public String toString() { - return "HandlingEventRegistrationAttempt{" + "registrationTime=" + registrationTime + ", completionTime=" - + completionTime + ", trackingId=" + trackingId + ", voyageNumber=" + voyageNumber + ", type=" + type - + ", unLocode=" + unLocode + '}'; - } + @Override + public String toString() { + return "HandlingEventRegistrationAttempt{" + + "registrationTime=" + + registrationTime + + ", completionTime=" + + completionTime + + ", trackingId=" + + trackingId + + ", voyageNumber=" + + voyageNumber + + ", type=" + + type + + ", unLocode=" + + unLocode + + '}'; + } } diff --git a/src/main/java/org/eclipse/cargotracker/interfaces/handling/file/EventFilesCheckpoint.java b/src/main/java/org/eclipse/cargotracker/interfaces/handling/file/EventFilesCheckpoint.java index e48ce5e05..57f8988de 100644 --- a/src/main/java/org/eclipse/cargotracker/interfaces/handling/file/EventFilesCheckpoint.java +++ b/src/main/java/org/eclipse/cargotracker/interfaces/handling/file/EventFilesCheckpoint.java @@ -7,39 +7,39 @@ public class EventFilesCheckpoint implements Serializable { - private static final long serialVersionUID = 1L; - - private List files = new LinkedList<>(); - private int fileIndex = 0; - private long filePointer = 0; - - public void setFiles(List files) { - this.files = files; - } - - public long getFilePointer() { - return filePointer; - } - - public void setFilePointer(long filePointer) { - this.filePointer = filePointer; - } - - public File currentFile() { - if (files.size() > fileIndex) { - return files.get(fileIndex); - } else { - return null; - } - } - - public File nextFile() { - filePointer = 0; - - if (files.size() > ++fileIndex) { - return files.get(fileIndex); - } else { - return null; - } - } + private static final long serialVersionUID = 1L; + + private List files = new LinkedList<>(); + private int fileIndex = 0; + private long filePointer = 0; + + public void setFiles(List files) { + this.files = files; + } + + public long getFilePointer() { + return filePointer; + } + + public void setFilePointer(long filePointer) { + this.filePointer = filePointer; + } + + public File currentFile() { + if (files.size() > fileIndex) { + return files.get(fileIndex); + } else { + return null; + } + } + + public File nextFile() { + filePointer = 0; + + if (files.size() > ++fileIndex) { + return files.get(fileIndex); + } else { + return null; + } + } } diff --git a/src/main/java/org/eclipse/cargotracker/interfaces/handling/file/EventItemReader.java b/src/main/java/org/eclipse/cargotracker/interfaces/handling/file/EventItemReader.java index 61ae61663..5da3657d6 100644 --- a/src/main/java/org/eclipse/cargotracker/interfaces/handling/file/EventItemReader.java +++ b/src/main/java/org/eclipse/cargotracker/interfaces/handling/file/EventItemReader.java @@ -26,134 +26,133 @@ @Named("EventItemReader") public class EventItemReader extends AbstractItemReader { - private static final String UPLOAD_DIRECTORY = "upload_directory"; - private static final String ISO_8601_FORMAT = "yyyy-MM-dd HH:mm"; - - @Inject - private Logger logger; - - @Inject - private JobContext jobContext; - private EventFilesCheckpoint checkpoint; - private RandomAccessFile currentFile; - - @Override - public void open(Serializable checkpoint) throws Exception { - File uploadDirectory = new File(jobContext.getProperties().getProperty(UPLOAD_DIRECTORY)); - - if (checkpoint == null) { - this.checkpoint = new EventFilesCheckpoint(); - logger.log(Level.INFO, "Scanning upload directory: {0}", uploadDirectory); - - if (!uploadDirectory.exists()) { - logger.log(Level.INFO, "Upload directory does not exist, creating it"); - uploadDirectory.mkdirs(); - } else { - this.checkpoint.setFiles(Arrays.asList(uploadDirectory.listFiles())); - } - } else { - logger.log(Level.INFO, "Starting from previous checkpoint"); - this.checkpoint = (EventFilesCheckpoint) checkpoint; - } - - File file = this.checkpoint.currentFile(); - - if (file == null) { - logger.log(Level.INFO, "No files to process"); - currentFile = null; - } else { - currentFile = new RandomAccessFile(file, "r"); - logger.log(Level.INFO, "Processing file: {0}", file); - currentFile.seek(this.checkpoint.getFilePointer()); - } - } - - @Override - public Object readItem() throws Exception { - if (currentFile != null) { - String line = currentFile.readLine(); - - if (line != null) { - this.checkpoint.setFilePointer(currentFile.getFilePointer()); - return parseLine(line); - } else { - logger.log(Level.INFO, "Finished processing file, deleting: {0}", this.checkpoint.currentFile()); - currentFile.close(); - this.checkpoint.currentFile().delete(); - File nextFile = this.checkpoint.nextFile(); - - if (nextFile == null) { - logger.log(Level.INFO, "No more files to process"); - return null; - } else { - currentFile = new RandomAccessFile(nextFile, "r"); - logger.log(Level.INFO, "Processing file: {0}", nextFile); - return readItem(); - } - } - } else { - return null; - } - } - - private Object parseLine(String line) throws EventLineParseException { - String[] result = line.split(","); - - if (result.length != 5) { - throw new EventLineParseException("Wrong number of data elements", line); - } - - Date completionTime = null; - - try { - completionTime = new SimpleDateFormat(ISO_8601_FORMAT).parse(result[0]); - } catch (ParseException e) { - throw new EventLineParseException("Cannot parse completion time", e, line); - } - - TrackingId trackingId = null; - - try { - trackingId = new TrackingId(result[1]); - } catch (NullPointerException e) { - throw new EventLineParseException("Cannot parse tracking ID", e, line); - } - - VoyageNumber voyageNumber = null; - - try { - if (!result[2].isEmpty()) { - voyageNumber = new VoyageNumber(result[2]); - } - } catch (NullPointerException e) { - throw new EventLineParseException("Cannot parse voyage number", e, line); - } - - UnLocode unLocode = null; - - try { - unLocode = new UnLocode(result[3]); - } catch (IllegalArgumentException | NullPointerException e) { - throw new EventLineParseException("Cannot parse UN location code", e, line); - } - - HandlingEvent.Type eventType = null; - - try { - eventType = HandlingEvent.Type.valueOf(result[4]); - } catch (IllegalArgumentException | NullPointerException e) { - throw new EventLineParseException("Cannot parse event type", e, line); - } - - HandlingEventRegistrationAttempt attempt = new HandlingEventRegistrationAttempt(new Date(), completionTime, - trackingId, voyageNumber, eventType, unLocode); - - return attempt; - } - - @Override - public Serializable checkpointInfo() throws Exception { - return this.checkpoint; - } - + private static final String UPLOAD_DIRECTORY = "upload_directory"; + private static final String ISO_8601_FORMAT = "yyyy-MM-dd HH:mm"; + + @Inject private Logger logger; + + @Inject private JobContext jobContext; + private EventFilesCheckpoint checkpoint; + private RandomAccessFile currentFile; + + @Override + public void open(Serializable checkpoint) throws Exception { + File uploadDirectory = new File(jobContext.getProperties().getProperty(UPLOAD_DIRECTORY)); + + if (checkpoint == null) { + this.checkpoint = new EventFilesCheckpoint(); + logger.log(Level.INFO, "Scanning upload directory: {0}", uploadDirectory); + + if (!uploadDirectory.exists()) { + logger.log(Level.INFO, "Upload directory does not exist, creating it"); + uploadDirectory.mkdirs(); + } else { + this.checkpoint.setFiles(Arrays.asList(uploadDirectory.listFiles())); + } + } else { + logger.log(Level.INFO, "Starting from previous checkpoint"); + this.checkpoint = (EventFilesCheckpoint) checkpoint; + } + + File file = this.checkpoint.currentFile(); + + if (file == null) { + logger.log(Level.INFO, "No files to process"); + currentFile = null; + } else { + currentFile = new RandomAccessFile(file, "r"); + logger.log(Level.INFO, "Processing file: {0}", file); + currentFile.seek(this.checkpoint.getFilePointer()); + } + } + + @Override + public Object readItem() throws Exception { + if (currentFile != null) { + String line = currentFile.readLine(); + + if (line != null) { + this.checkpoint.setFilePointer(currentFile.getFilePointer()); + return parseLine(line); + } else { + logger.log( + Level.INFO, "Finished processing file, deleting: {0}", this.checkpoint.currentFile()); + currentFile.close(); + this.checkpoint.currentFile().delete(); + File nextFile = this.checkpoint.nextFile(); + + if (nextFile == null) { + logger.log(Level.INFO, "No more files to process"); + return null; + } else { + currentFile = new RandomAccessFile(nextFile, "r"); + logger.log(Level.INFO, "Processing file: {0}", nextFile); + return readItem(); + } + } + } else { + return null; + } + } + + private Object parseLine(String line) throws EventLineParseException { + String[] result = line.split(","); + + if (result.length != 5) { + throw new EventLineParseException("Wrong number of data elements", line); + } + + Date completionTime = null; + + try { + completionTime = new SimpleDateFormat(ISO_8601_FORMAT).parse(result[0]); + } catch (ParseException e) { + throw new EventLineParseException("Cannot parse completion time", e, line); + } + + TrackingId trackingId = null; + + try { + trackingId = new TrackingId(result[1]); + } catch (NullPointerException e) { + throw new EventLineParseException("Cannot parse tracking ID", e, line); + } + + VoyageNumber voyageNumber = null; + + try { + if (!result[2].isEmpty()) { + voyageNumber = new VoyageNumber(result[2]); + } + } catch (NullPointerException e) { + throw new EventLineParseException("Cannot parse voyage number", e, line); + } + + UnLocode unLocode = null; + + try { + unLocode = new UnLocode(result[3]); + } catch (IllegalArgumentException | NullPointerException e) { + throw new EventLineParseException("Cannot parse UN location code", e, line); + } + + HandlingEvent.Type eventType = null; + + try { + eventType = HandlingEvent.Type.valueOf(result[4]); + } catch (IllegalArgumentException | NullPointerException e) { + throw new EventLineParseException("Cannot parse event type", e, line); + } + + HandlingEventRegistrationAttempt attempt = + new HandlingEventRegistrationAttempt( + new Date(), completionTime, trackingId, voyageNumber, eventType, unLocode); + + return attempt; + } + + @Override + public Serializable checkpointInfo() throws Exception { + return this.checkpoint; + } } diff --git a/src/main/java/org/eclipse/cargotracker/interfaces/handling/file/EventItemWriter.java b/src/main/java/org/eclipse/cargotracker/interfaces/handling/file/EventItemWriter.java index cd3b72957..771d8be2f 100644 --- a/src/main/java/org/eclipse/cargotracker/interfaces/handling/file/EventItemWriter.java +++ b/src/main/java/org/eclipse/cargotracker/interfaces/handling/file/EventItemWriter.java @@ -21,38 +21,51 @@ @Named("EventItemWriter") public class EventItemWriter extends AbstractItemWriter { - private static final String ARCHIVE_DIRECTORY = "archive_directory"; - - @Inject - private JobContext jobContext; - @Inject - private ApplicationEvents applicationEvents; - - @Override - public void open(Serializable checkpoint) throws Exception { - File archiveDirectory = new File(jobContext.getProperties().getProperty(ARCHIVE_DIRECTORY)); - - if (!archiveDirectory.exists()) { - archiveDirectory.mkdirs(); - } - } - - @Override - @Transactional - public void writeItems(List items) throws Exception { - try (PrintWriter archive = new PrintWriter( - new BufferedWriter( - new FileWriter( - new File(jobContext.getProperties().getProperty(ARCHIVE_DIRECTORY) + "/archive_" - + jobContext.getJobName() + "_" + jobContext.getInstanceId() + ".csv"), - true)))) { - for (Object item : items) { - HandlingEventRegistrationAttempt attempt = (HandlingEventRegistrationAttempt) item; - applicationEvents.receivedHandlingEventRegistrationAttempt(attempt); - archive.println(attempt.getRegistrationTime() + "," + attempt.getCompletionTime() + "," - + attempt.getTrackingId() + "," + attempt.getVoyageNumber() + "," + attempt.getUnLocode() + "," - + attempt.getType()); - } - } - } + private static final String ARCHIVE_DIRECTORY = "archive_directory"; + + @Inject private JobContext jobContext; + @Inject private ApplicationEvents applicationEvents; + + @Override + public void open(Serializable checkpoint) throws Exception { + File archiveDirectory = new File(jobContext.getProperties().getProperty(ARCHIVE_DIRECTORY)); + + if (!archiveDirectory.exists()) { + archiveDirectory.mkdirs(); + } + } + + @Override + @Transactional + public void writeItems(List items) throws Exception { + try (PrintWriter archive = + new PrintWriter( + new BufferedWriter( + new FileWriter( + new File( + jobContext.getProperties().getProperty(ARCHIVE_DIRECTORY) + + "/archive_" + + jobContext.getJobName() + + "_" + + jobContext.getInstanceId() + + ".csv"), + true)))) { + for (Object item : items) { + HandlingEventRegistrationAttempt attempt = (HandlingEventRegistrationAttempt) item; + applicationEvents.receivedHandlingEventRegistrationAttempt(attempt); + archive.println( + attempt.getRegistrationTime() + + "," + + attempt.getCompletionTime() + + "," + + attempt.getTrackingId() + + "," + + attempt.getVoyageNumber() + + "," + + attempt.getUnLocode() + + "," + + attempt.getType()); + } + } + } } diff --git a/src/main/java/org/eclipse/cargotracker/interfaces/handling/file/EventLineParseException.java b/src/main/java/org/eclipse/cargotracker/interfaces/handling/file/EventLineParseException.java index fb42d53ad..c953dfbc7 100644 --- a/src/main/java/org/eclipse/cargotracker/interfaces/handling/file/EventLineParseException.java +++ b/src/main/java/org/eclipse/cargotracker/interfaces/handling/file/EventLineParseException.java @@ -2,21 +2,21 @@ public class EventLineParseException extends RuntimeException { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - private final String line; + private final String line; - public EventLineParseException(String message, Throwable cause, String line) { - super(message, cause); - this.line = line; - } + public EventLineParseException(String message, Throwable cause, String line) { + super(message, cause); + this.line = line; + } - public EventLineParseException(String message, String line) { - super(message); - this.line = line; - } + public EventLineParseException(String message, String line) { + super(message); + this.line = line; + } - public String getLine() { - return line; - } + public String getLine() { + return line; + } } diff --git a/src/main/java/org/eclipse/cargotracker/interfaces/handling/file/FileProcessorJobListener.java b/src/main/java/org/eclipse/cargotracker/interfaces/handling/file/FileProcessorJobListener.java index 29eba2308..da9ba2194 100644 --- a/src/main/java/org/eclipse/cargotracker/interfaces/handling/file/FileProcessorJobListener.java +++ b/src/main/java/org/eclipse/cargotracker/interfaces/handling/file/FileProcessorJobListener.java @@ -1,27 +1,27 @@ package org.eclipse.cargotracker.interfaces.handling.file; +import java.util.Date; +import java.util.logging.Level; +import java.util.logging.Logger; + import javax.batch.api.listener.JobListener; import javax.enterprise.context.Dependent; import javax.inject.Inject; import javax.inject.Named; -import java.util.Date; -import java.util.logging.Level; -import java.util.logging.Logger; @Dependent @Named("FileProcessorJobListener") public class FileProcessorJobListener implements JobListener { - @Inject - private Logger logger; + @Inject private Logger logger; - @Override - public void beforeJob() throws Exception { - logger.log(Level.INFO, "Handling event file processor batch job starting at {0}", new Date()); - } + @Override + public void beforeJob() throws Exception { + logger.log(Level.INFO, "Handling event file processor batch job starting at {0}", new Date()); + } - @Override - public void afterJob() throws Exception { - logger.log(Level.INFO, "Handling event file processor batch job completed at {0}", new Date()); - } + @Override + public void afterJob() throws Exception { + logger.log(Level.INFO, "Handling event file processor batch job completed at {0}", new Date()); + } } diff --git a/src/main/java/org/eclipse/cargotracker/interfaces/handling/file/LineParseExceptionListener.java b/src/main/java/org/eclipse/cargotracker/interfaces/handling/file/LineParseExceptionListener.java index 64c80c2b9..5bfdb7895 100644 --- a/src/main/java/org/eclipse/cargotracker/interfaces/handling/file/LineParseExceptionListener.java +++ b/src/main/java/org/eclipse/cargotracker/interfaces/handling/file/LineParseExceptionListener.java @@ -17,33 +17,37 @@ @Named("LineParseExceptionListener") public class LineParseExceptionListener implements SkipReadListener { - private static final String FAILED_DIRECTORY = "failed_directory"; - - @Inject - private Logger logger; - - @Inject - private JobContext jobContext; - - @Override - public void onSkipReadItem(Exception e) throws Exception { - File failedDirectory = new File(jobContext.getProperties().getProperty(FAILED_DIRECTORY)); - - if (!failedDirectory.exists()) { - failedDirectory.mkdirs(); - } - - EventLineParseException parseException = (EventLineParseException) e; - - logger.log(Level.WARNING, "Problem parsing event file line", parseException); - - try (PrintWriter failed = new PrintWriter( - new BufferedWriter(new FileWriter( - new File(failedDirectory, - "failed_" + jobContext.getJobName() + "_" + jobContext.getInstanceId() + ".csv"), - true)))) { - failed.println(parseException.getLine()); - } - } - + private static final String FAILED_DIRECTORY = "failed_directory"; + + @Inject private Logger logger; + + @Inject private JobContext jobContext; + + @Override + public void onSkipReadItem(Exception e) throws Exception { + File failedDirectory = new File(jobContext.getProperties().getProperty(FAILED_DIRECTORY)); + + if (!failedDirectory.exists()) { + failedDirectory.mkdirs(); + } + + EventLineParseException parseException = (EventLineParseException) e; + + logger.log(Level.WARNING, "Problem parsing event file line", parseException); + + try (PrintWriter failed = + new PrintWriter( + new BufferedWriter( + new FileWriter( + new File( + failedDirectory, + "failed_" + + jobContext.getJobName() + + "_" + + jobContext.getInstanceId() + + ".csv"), + true)))) { + failed.println(parseException.getLine()); + } + } } diff --git a/src/main/java/org/eclipse/cargotracker/interfaces/handling/file/UploadDirectoryScanner.java b/src/main/java/org/eclipse/cargotracker/interfaces/handling/file/UploadDirectoryScanner.java index 124ed7678..576bf3cf9 100644 --- a/src/main/java/org/eclipse/cargotracker/interfaces/handling/file/UploadDirectoryScanner.java +++ b/src/main/java/org/eclipse/cargotracker/interfaces/handling/file/UploadDirectoryScanner.java @@ -6,18 +6,17 @@ import javax.ejb.Stateless; /** - * Periodically scans a certain directory for files and attempts to parse - * handling event registrations from the contents by calling a batch job. - *

- * Files that fail to parse are moved into a separate directory, successful - * files are deleted. + * Periodically scans a certain directory for files and attempts to parse handling event + * registrations from the contents by calling a batch job. + * + *

Files that fail to parse are moved into a separate directory, successful files are deleted. */ @Stateless public class UploadDirectoryScanner { - @Schedule(minute = "*/2", hour = "*") // Runs every fifteen minutes - public void processFiles() { - JobOperator jobOperator = BatchRuntime.getJobOperator(); - jobOperator.start("EventFilesProcessorJob", null); - } + @Schedule(minute = "*/2", hour = "*") // Runs every fifteen minutes + public void processFiles() { + JobOperator jobOperator = BatchRuntime.getJobOperator(); + jobOperator.start("EventFilesProcessorJob", null); + } } diff --git a/src/main/java/org/eclipse/cargotracker/interfaces/handling/mobile/EventLogger.java b/src/main/java/org/eclipse/cargotracker/interfaces/handling/mobile/EventLogger.java index c248858a4..61a92ad48 100644 --- a/src/main/java/org/eclipse/cargotracker/interfaces/handling/mobile/EventLogger.java +++ b/src/main/java/org/eclipse/cargotracker/interfaces/handling/mobile/EventLogger.java @@ -34,160 +34,161 @@ @ViewScoped public class EventLogger implements Serializable { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - @Inject - private CargoRepository cargoRepository; - - @Inject - private LocationRepository locationRepository; - - @Inject - private VoyageRepository voyageRepository; + @Inject private CargoRepository cargoRepository; + + @Inject private LocationRepository locationRepository; - @Inject - private ApplicationEvents applicationEvents; - - private List trackingIds; - private List locations; - private List voyages; - - private String trackingId; - private String location; - private String eventType; - private String voyageNumber; - private Date completionDate; - - public void setTrackingId(String trackingId) { - this.trackingId = trackingId; - } - - public String getTrackingId() { - return trackingId; - } - - public List getTrackingIds() { - return trackingIds; - } - - public void setLocation(String location) { - this.location = location; - } - - public String getLocation() { - return location; - } - - public List getLocations() { - return locations; - } - - public String getEventType() { - return eventType; - } - - public void setEventType(String eventType) { - this.eventType = eventType; - } - - public void setVoyageNumber(String voyageNumber) { - this.voyageNumber = voyageNumber; - } - - public String getVoyageNumber() { - return voyageNumber; - } - - public List getVoyages() { - return voyages; - } - - public void setCompletionDate(Date completionDate) { - this.completionDate = completionDate; - } - - public Date getCompletionDate() { - return completionDate; - } - - @PostConstruct - @Transactional - public void init() { - List cargos = cargoRepository.findAll(); - - trackingIds = new ArrayList<>(cargos.size()); - for (Cargo cargo : cargos) { - // List only routed cargo that is not claimed yet. - if (!cargo.getItinerary().getLegs().isEmpty() - && !(cargo.getDelivery().getTransportStatus().sameValueAs(TransportStatus.CLAIMED))) { - String trackingId = cargo.getTrackingId().getIdString(); - trackingIds.add(new SelectItem(trackingId, trackingId)); - } - } - - List locations = locationRepository.findAll(); - - this.locations = new ArrayList<>(locations.size()); - for (Location location : locations) { - String locationCode = location.getUnLocode().getIdString(); - this.locations.add(new SelectItem(locationCode, location.getName() + " (" + locationCode + ")")); - } - - List voyages = voyageRepository.findAll(); - - this.voyages = new ArrayList<>(voyages.size()); - for (Voyage voyage : voyages) { - this.voyages.add( - new SelectItem(voyage.getVoyageNumber().getIdString(), voyage.getVoyageNumber().getIdString())); - } - - } - - public String onFlowProcess(FlowEvent event) { - if (!validate(event.getOldStep())) { - return event.getOldStep(); - } - - if ("dateTab".equals(event.getNewStep())) { - completionDate = Calendar.getInstance().getTime(); - } - - return event.getNewStep(); - } - - private boolean validate(final String step) { - if ("voyageTab".equals(step) && ("LOAD".equals(eventType) || "UNLOAD".equals(eventType)) - && voyageNumber == null) { - FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, - "When a cargo is LOADed or UNLOADed a Voyage should be selected, please fix errors to continue.", - ""); - FacesContext.getCurrentInstance().addMessage(null, message); - return false; - } - - return true; - } - - public void submit() { - VoyageNumber voyage; - - Date registrationTime = new Date(); - TrackingId trackingId = new TrackingId(this.trackingId); - UnLocode location = new UnLocode(this.location); - HandlingEvent.Type type = HandlingEvent.Type.valueOf(eventType); - - // Only Load & Unload could have a Voyage set - if ("LOAD".equals(eventType) || "UNLOAD".equals(eventType)) { - voyage = new VoyageNumber(voyageNumber); - } else { - voyage = null; - } - - HandlingEventRegistrationAttempt attempt = new HandlingEventRegistrationAttempt(registrationTime, - completionDate, trackingId, voyage, type, location); - - applicationEvents.receivedHandlingEventRegistrationAttempt(attempt); - - FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Event submitted", "")); - } -} \ No newline at end of file + @Inject private VoyageRepository voyageRepository; + + @Inject private ApplicationEvents applicationEvents; + + private List trackingIds; + private List locations; + private List voyages; + + private String trackingId; + private String location; + private String eventType; + private String voyageNumber; + private Date completionDate; + + public void setTrackingId(String trackingId) { + this.trackingId = trackingId; + } + + public String getTrackingId() { + return trackingId; + } + + public List getTrackingIds() { + return trackingIds; + } + + public void setLocation(String location) { + this.location = location; + } + + public String getLocation() { + return location; + } + + public List getLocations() { + return locations; + } + + public String getEventType() { + return eventType; + } + + public void setEventType(String eventType) { + this.eventType = eventType; + } + + public void setVoyageNumber(String voyageNumber) { + this.voyageNumber = voyageNumber; + } + + public String getVoyageNumber() { + return voyageNumber; + } + + public List getVoyages() { + return voyages; + } + + public void setCompletionDate(Date completionDate) { + this.completionDate = completionDate; + } + + public Date getCompletionDate() { + return completionDate; + } + + @PostConstruct + @Transactional + public void init() { + List cargos = cargoRepository.findAll(); + + trackingIds = new ArrayList<>(cargos.size()); + for (Cargo cargo : cargos) { + // List only routed cargo that is not claimed yet. + if (!cargo.getItinerary().getLegs().isEmpty() + && !(cargo.getDelivery().getTransportStatus().sameValueAs(TransportStatus.CLAIMED))) { + String trackingId = cargo.getTrackingId().getIdString(); + trackingIds.add(new SelectItem(trackingId, trackingId)); + } + } + + List locations = locationRepository.findAll(); + + this.locations = new ArrayList<>(locations.size()); + for (Location location : locations) { + String locationCode = location.getUnLocode().getIdString(); + this.locations.add( + new SelectItem(locationCode, location.getName() + " (" + locationCode + ")")); + } + + List voyages = voyageRepository.findAll(); + + this.voyages = new ArrayList<>(voyages.size()); + for (Voyage voyage : voyages) { + this.voyages.add( + new SelectItem( + voyage.getVoyageNumber().getIdString(), voyage.getVoyageNumber().getIdString())); + } + } + + public String onFlowProcess(FlowEvent event) { + if (!validate(event.getOldStep())) { + return event.getOldStep(); + } + + if ("dateTab".equals(event.getNewStep())) { + completionDate = Calendar.getInstance().getTime(); + } + + return event.getNewStep(); + } + + private boolean validate(final String step) { + if ("voyageTab".equals(step) + && ("LOAD".equals(eventType) || "UNLOAD".equals(eventType)) + && voyageNumber == null) { + FacesMessage message = + new FacesMessage( + FacesMessage.SEVERITY_ERROR, + "When a cargo is LOADed or UNLOADed a Voyage should be selected, please fix errors to continue.", + ""); + FacesContext.getCurrentInstance().addMessage(null, message); + return false; + } + + return true; + } + + public void submit() { + VoyageNumber voyage; + + Date registrationTime = new Date(); + TrackingId trackingId = new TrackingId(this.trackingId); + UnLocode location = new UnLocode(this.location); + HandlingEvent.Type type = HandlingEvent.Type.valueOf(eventType); + + // Only Load & Unload could have a Voyage set + if ("LOAD".equals(eventType) || "UNLOAD".equals(eventType)) { + voyage = new VoyageNumber(voyageNumber); + } else { + voyage = null; + } + + HandlingEventRegistrationAttempt attempt = + new HandlingEventRegistrationAttempt( + registrationTime, completionDate, trackingId, voyage, type, location); + + applicationEvents.receivedHandlingEventRegistrationAttempt(attempt); + + FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Event submitted", "")); + } +} diff --git a/src/main/java/org/eclipse/cargotracker/interfaces/handling/rest/HandlingReport.java b/src/main/java/org/eclipse/cargotracker/interfaces/handling/rest/HandlingReport.java index a8923fd9d..0881d55aa 100644 --- a/src/main/java/org/eclipse/cargotracker/interfaces/handling/rest/HandlingReport.java +++ b/src/main/java/org/eclipse/cargotracker/interfaces/handling/rest/HandlingReport.java @@ -4,64 +4,66 @@ import javax.validation.constraints.Size; import javax.xml.bind.annotation.XmlRootElement; -/** - * Transfer object for handling reports. - */ +/** Transfer object for handling reports. */ @XmlRootElement public class HandlingReport { - @NotNull - @Size(min = 16, max = 16) - private String completionTime; - @NotNull - @Size(min = 4) - private String trackingId; - @NotNull - @Size(min = 4, max = 7) - private String eventType; - @NotNull - @Size(min = 5, max = 5) - private String unLocode; - @Size(min = 4, max = 5) - private String voyageNumber; - - public String getCompletionTime() { - return completionTime; - } - - public void setCompletionTime(String value) { - this.completionTime = value; - } - - public String getTrackingId() { - return trackingId; - } - - public void setTrackingId(String trackingId) { - this.trackingId = trackingId; - } - - public String getEventType() { - return eventType; - } - - public void setEventType(String value) { - this.eventType = value; - } - - public String getUnLocode() { - return unLocode; - } - - public void setUnLocode(String value) { - this.unLocode = value; - } - - public String getVoyageNumber() { - return voyageNumber; - } - - public void setVoyageNumber(String value) { - this.voyageNumber = value; - } + @NotNull + @Size(min = 16, max = 16) + private String completionTime; + + @NotNull + @Size(min = 4) + private String trackingId; + + @NotNull + @Size(min = 4, max = 7) + private String eventType; + + @NotNull + @Size(min = 5, max = 5) + private String unLocode; + + @Size(min = 4, max = 5) + private String voyageNumber; + + public String getCompletionTime() { + return completionTime; + } + + public void setCompletionTime(String value) { + this.completionTime = value; + } + + public String getTrackingId() { + return trackingId; + } + + public void setTrackingId(String trackingId) { + this.trackingId = trackingId; + } + + public String getEventType() { + return eventType; + } + + public void setEventType(String value) { + this.eventType = value; + } + + public String getUnLocode() { + return unLocode; + } + + public void setUnLocode(String value) { + this.unLocode = value; + } + + public String getVoyageNumber() { + return voyageNumber; + } + + public void setVoyageNumber(String value) { + this.voyageNumber = value; + } } diff --git a/src/main/java/org/eclipse/cargotracker/interfaces/handling/rest/HandlingReportService.java b/src/main/java/org/eclipse/cargotracker/interfaces/handling/rest/HandlingReportService.java index 4c84cce42..218896563 100644 --- a/src/main/java/org/eclipse/cargotracker/interfaces/handling/rest/HandlingReportService.java +++ b/src/main/java/org/eclipse/cargotracker/interfaces/handling/rest/HandlingReportService.java @@ -21,47 +21,46 @@ import org.eclipse.cargotracker.interfaces.handling.HandlingEventRegistrationAttempt; /** - * This REST end-point implementation performs basic validation and parsing of - * incoming data, and in case of a valid registration attempt, sends an - * asynchronous message with the information to the handling event registration - * system for proper registration. + * This REST end-point implementation performs basic validation and parsing of incoming data, and in + * case of a valid registration attempt, sends an asynchronous message with the information to the + * handling event registration system for proper registration. */ @Stateless @Path("/handling") public class HandlingReportService { - public static final String ISO_8601_FORMAT = "yyyy-MM-dd HH:mm"; + public static final String ISO_8601_FORMAT = "yyyy-MM-dd HH:mm"; - @Inject - private ApplicationEvents applicationEvents; + @Inject private ApplicationEvents applicationEvents; - public HandlingReportService() { - } + public HandlingReportService() {} - @POST - @Path("/reports") - @Consumes(MediaType.APPLICATION_JSON) - public void submitReport(@NotNull @Valid HandlingReport handlingReport) { - try { - Date completionTime = new SimpleDateFormat(ISO_8601_FORMAT).parse(handlingReport.getCompletionTime()); - VoyageNumber voyageNumber = null; + @POST + @Path("/reports") + @Consumes(MediaType.APPLICATION_JSON) + public void submitReport(@NotNull @Valid HandlingReport handlingReport) { + try { + Date completionTime = + new SimpleDateFormat(ISO_8601_FORMAT).parse(handlingReport.getCompletionTime()); + VoyageNumber voyageNumber = null; - if (handlingReport.getVoyageNumber() != null) { - voyageNumber = new VoyageNumber(handlingReport.getVoyageNumber()); - } + if (handlingReport.getVoyageNumber() != null) { + voyageNumber = new VoyageNumber(handlingReport.getVoyageNumber()); + } - HandlingEvent.Type type = HandlingEvent.Type.valueOf(handlingReport.getEventType()); - UnLocode unLocode = new UnLocode(handlingReport.getUnLocode()); + HandlingEvent.Type type = HandlingEvent.Type.valueOf(handlingReport.getEventType()); + UnLocode unLocode = new UnLocode(handlingReport.getUnLocode()); - TrackingId trackingId = new TrackingId(handlingReport.getTrackingId()); + TrackingId trackingId = new TrackingId(handlingReport.getTrackingId()); - Date registrationTime = new Date(); - HandlingEventRegistrationAttempt attempt = new HandlingEventRegistrationAttempt(registrationTime, - completionTime, trackingId, voyageNumber, type, unLocode); + Date registrationTime = new Date(); + HandlingEventRegistrationAttempt attempt = + new HandlingEventRegistrationAttempt( + registrationTime, completionTime, trackingId, voyageNumber, type, unLocode); - applicationEvents.receivedHandlingEventRegistrationAttempt(attempt); - } catch (ParseException ex) { - throw new RuntimeException("Error parsing completion time", ex); - } - } + applicationEvents.receivedHandlingEventRegistrationAttempt(attempt); + } catch (ParseException ex) { + throw new RuntimeException("Error parsing completion time", ex); + } + } } diff --git a/src/main/java/org/eclipse/cargotracker/interfaces/tracking/web/CargoTrackingViewAdapter.java b/src/main/java/org/eclipse/cargotracker/interfaces/tracking/web/CargoTrackingViewAdapter.java index 33ef8afdb..7547c112a 100644 --- a/src/main/java/org/eclipse/cargotracker/interfaces/tracking/web/CargoTrackingViewAdapter.java +++ b/src/main/java/org/eclipse/cargotracker/interfaces/tracking/web/CargoTrackingViewAdapter.java @@ -11,173 +11,176 @@ import org.eclipse.cargotracker.domain.model.cargo.HandlingActivity; import org.eclipse.cargotracker.domain.model.handling.HandlingEvent; -/** - * View adapter for displaying a cargo in a tracking context. - */ +/** View adapter for displaying a cargo in a tracking context. */ public class CargoTrackingViewAdapter { - private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("MM/dd/yyyy hh:mm a z"); - - private final Cargo cargo; - private final List events; - - public CargoTrackingViewAdapter(Cargo cargo, List handlingEvents) { - this.cargo = cargo; - this.events = new ArrayList<>(handlingEvents.size()); - - for (HandlingEvent handlingEvent : handlingEvents) { - events.add(new HandlingEventViewAdapter(handlingEvent)); - } - } - - public String getTrackingId() { - return cargo.getTrackingId().getIdString(); - } - - public String getOriginName() { - return cargo.getRouteSpecification().getOrigin().getName(); - } - - public String getOriginCode() { - return cargo.getRouteSpecification().getOrigin().getUnLocode().getIdString(); - } - - public String getDestinationName() { - return cargo.getRouteSpecification().getDestination().getName(); - } - - public String getDestinationCode() { - return cargo.getRouteSpecification().getDestination().getUnLocode().getIdString(); - } - - public String getLastKnownLocationName() { - return cargo.getDelivery().getLastKnownLocation().getUnLocode().getIdString().equals("XXXXX") ? "Unknown" - : cargo.getDelivery().getLastKnownLocation().getName(); - } - - public String getLastKnownLocationCode() { - return cargo.getDelivery().getLastKnownLocation().getUnLocode().getIdString(); - } - - public String getStatusCode() { - if (cargo.getItinerary().getLegs().isEmpty()) { - return "NOT_ROUTED"; - } - - if (cargo.getDelivery().isUnloadedAtDestination()) { - return "AT_DESTINATION"; - } - - if (cargo.getDelivery().isMisdirected()) { - return "MISDIRECTED"; - } - - return cargo.getDelivery().getTransportStatus().name(); - } - - /** - * @return A readable string describing the cargo status. - */ - public String getStatusText() { - Delivery delivery = cargo.getDelivery(); - - switch (delivery.getTransportStatus()) { - case IN_PORT: - return "In port " + cargo.getRouteSpecification().getDestination().getName(); - case ONBOARD_CARRIER: - return "Onboard voyage " + delivery.getCurrentVoyage().getVoyageNumber().getIdString(); - case CLAIMED: - return "Claimed"; - case NOT_RECEIVED: - return "Not received"; - case UNKNOWN: - return "Unknown"; - default: - return "[Unknown status]"; // Should never happen. - } - } - - public boolean isMisdirected() { - return cargo.getDelivery().isMisdirected(); - } - - public String getEta() { - Date eta = cargo.getDelivery().getEstimatedTimeOfArrival(); - - if (eta == null) { - return "?"; - } else { - return DATE_FORMAT.format(eta); - } - } - - public String getNextExpectedActivity() { - HandlingActivity activity = cargo.getDelivery().getNextExpectedActivity(); - - if ((activity == null) || (activity.isEmpty())) { - return ""; - } - - String text = "Next expected activity is to "; - HandlingEvent.Type type = activity.getType(); - - if (type.sameValueAs(HandlingEvent.Type.LOAD)) { - return text + type.name().toLowerCase() + " cargo onto voyage " + activity.getVoyage().getVoyageNumber() - + " in " + activity.getLocation().getName(); - } else if (type.sameValueAs(HandlingEvent.Type.UNLOAD)) { - return text + type.name().toLowerCase() + " cargo off of " + activity.getVoyage().getVoyageNumber() + " in " - + activity.getLocation().getName(); - } else { - return text + type.name().toLowerCase() + " cargo in " + activity.getLocation().getName(); - } - } - - /** - * @return An unmodifiable list of handling event view adapters. - */ - public List getEvents() { - return Collections.unmodifiableList(events); - } - - /** - * Handling event view adapter component. - */ - public class HandlingEventViewAdapter { - - private final HandlingEvent handlingEvent; - - public HandlingEventViewAdapter(HandlingEvent handlingEvent) { - this.handlingEvent = handlingEvent; - } - - /** - * @return the date in the format MM/dd/yyyy hh:mm a z - */ - public String getTime() { - return DATE_FORMAT.format(handlingEvent.getCompletionTime()); - } - - public boolean isExpected() { - return cargo.getItinerary().isExpected(handlingEvent); - } - - public String getDescription() { - switch (handlingEvent.getType()) { - case LOAD: - return "Loaded onto voyage " + handlingEvent.getVoyage().getVoyageNumber().getIdString() + " in " - + handlingEvent.getLocation().getName(); - case UNLOAD: - return "Unloaded off voyage " + handlingEvent.getVoyage().getVoyageNumber().getIdString() + " in " - + handlingEvent.getLocation().getName(); - case RECEIVE: - return "Received in " + handlingEvent.getLocation().getName(); - case CLAIM: - return "Claimed in " + handlingEvent.getLocation().getName(); - case CUSTOMS: - return "Cleared customs in " + handlingEvent.getLocation().getName(); - default: - return "[Unknown]"; - } - } - } + private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("MM/dd/yyyy hh:mm a z"); + + private final Cargo cargo; + private final List events; + + public CargoTrackingViewAdapter(Cargo cargo, List handlingEvents) { + this.cargo = cargo; + this.events = new ArrayList<>(handlingEvents.size()); + + for (HandlingEvent handlingEvent : handlingEvents) { + events.add(new HandlingEventViewAdapter(handlingEvent)); + } + } + + public String getTrackingId() { + return cargo.getTrackingId().getIdString(); + } + + public String getOriginName() { + return cargo.getRouteSpecification().getOrigin().getName(); + } + + public String getOriginCode() { + return cargo.getRouteSpecification().getOrigin().getUnLocode().getIdString(); + } + + public String getDestinationName() { + return cargo.getRouteSpecification().getDestination().getName(); + } + + public String getDestinationCode() { + return cargo.getRouteSpecification().getDestination().getUnLocode().getIdString(); + } + + public String getLastKnownLocationName() { + return cargo.getDelivery().getLastKnownLocation().getUnLocode().getIdString().equals("XXXXX") + ? "Unknown" + : cargo.getDelivery().getLastKnownLocation().getName(); + } + + public String getLastKnownLocationCode() { + return cargo.getDelivery().getLastKnownLocation().getUnLocode().getIdString(); + } + + public String getStatusCode() { + if (cargo.getItinerary().getLegs().isEmpty()) { + return "NOT_ROUTED"; + } + + if (cargo.getDelivery().isUnloadedAtDestination()) { + return "AT_DESTINATION"; + } + + if (cargo.getDelivery().isMisdirected()) { + return "MISDIRECTED"; + } + + return cargo.getDelivery().getTransportStatus().name(); + } + + /** @return A readable string describing the cargo status. */ + public String getStatusText() { + Delivery delivery = cargo.getDelivery(); + + switch (delivery.getTransportStatus()) { + case IN_PORT: + return "In port " + cargo.getRouteSpecification().getDestination().getName(); + case ONBOARD_CARRIER: + return "Onboard voyage " + delivery.getCurrentVoyage().getVoyageNumber().getIdString(); + case CLAIMED: + return "Claimed"; + case NOT_RECEIVED: + return "Not received"; + case UNKNOWN: + return "Unknown"; + default: + return "[Unknown status]"; // Should never happen. + } + } + + public boolean isMisdirected() { + return cargo.getDelivery().isMisdirected(); + } + + public String getEta() { + Date eta = cargo.getDelivery().getEstimatedTimeOfArrival(); + + if (eta == null) { + return "?"; + } else { + return DATE_FORMAT.format(eta); + } + } + + public String getNextExpectedActivity() { + HandlingActivity activity = cargo.getDelivery().getNextExpectedActivity(); + + if ((activity == null) || (activity.isEmpty())) { + return ""; + } + + String text = "Next expected activity is to "; + HandlingEvent.Type type = activity.getType(); + + if (type.sameValueAs(HandlingEvent.Type.LOAD)) { + return text + + type.name().toLowerCase() + + " cargo onto voyage " + + activity.getVoyage().getVoyageNumber() + + " in " + + activity.getLocation().getName(); + } else if (type.sameValueAs(HandlingEvent.Type.UNLOAD)) { + return text + + type.name().toLowerCase() + + " cargo off of " + + activity.getVoyage().getVoyageNumber() + + " in " + + activity.getLocation().getName(); + } else { + return text + type.name().toLowerCase() + " cargo in " + activity.getLocation().getName(); + } + } + + /** @return An unmodifiable list of handling event view adapters. */ + public List getEvents() { + return Collections.unmodifiableList(events); + } + + /** Handling event view adapter component. */ + public class HandlingEventViewAdapter { + + private final HandlingEvent handlingEvent; + + public HandlingEventViewAdapter(HandlingEvent handlingEvent) { + this.handlingEvent = handlingEvent; + } + + /** @return the date in the format MM/dd/yyyy hh:mm a z */ + public String getTime() { + return DATE_FORMAT.format(handlingEvent.getCompletionTime()); + } + + public boolean isExpected() { + return cargo.getItinerary().isExpected(handlingEvent); + } + + public String getDescription() { + switch (handlingEvent.getType()) { + case LOAD: + return "Loaded onto voyage " + + handlingEvent.getVoyage().getVoyageNumber().getIdString() + + " in " + + handlingEvent.getLocation().getName(); + case UNLOAD: + return "Unloaded off voyage " + + handlingEvent.getVoyage().getVoyageNumber().getIdString() + + " in " + + handlingEvent.getLocation().getName(); + case RECEIVE: + return "Received in " + handlingEvent.getLocation().getName(); + case CLAIM: + return "Claimed in " + handlingEvent.getLocation().getName(); + case CUSTOMS: + return "Cleared customs in " + handlingEvent.getLocation().getName(); + default: + return "[Unknown]"; + } + } + } } diff --git a/src/main/java/org/eclipse/cargotracker/interfaces/tracking/web/Track.java b/src/main/java/org/eclipse/cargotracker/interfaces/tracking/web/Track.java index 304bbe58a..b4511deeb 100644 --- a/src/main/java/org/eclipse/cargotracker/interfaces/tracking/web/Track.java +++ b/src/main/java/org/eclipse/cargotracker/interfaces/tracking/web/Track.java @@ -16,65 +16,64 @@ import org.eclipse.cargotracker.domain.model.handling.HandlingEventRepository; /** - * Backing bean for tracking cargo. This interface sits immediately on top of - * the domain layer, unlike the booking interface which has a facade and - * supporting DTOs in between. - *

- * An adapter class, designed for the tracking use case, is used to wrap the - * domain model to make it easier to work with in a web page rendering context. - * We do not want to apply view rendering constraints to the design of our - * domain model and the adapter helps us shield the domain model classes where - * needed. - *

- * In some very simplistic cases, it is fine to not use even an adapter. + * Backing bean for tracking cargo. This interface sits immediately on top of the domain layer, + * unlike the booking interface which has a facade and supporting DTOs in between. + * + *

An adapter class, designed for the tracking use case, is used to wrap the domain model to make + * it easier to work with in a web page rendering context. We do not want to apply view rendering + * constraints to the design of our domain model and the adapter helps us shield the domain model + * classes where needed. + * + *

In some very simplistic cases, it is fine to not use even an adapter. */ @Named("public.track") @ViewScoped public class Track implements Serializable { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - @Inject - private CargoRepository cargoRepository; - @Inject - private HandlingEventRepository handlingEventRepository; + @Inject private CargoRepository cargoRepository; + @Inject private HandlingEventRepository handlingEventRepository; - private String trackingId; - private CargoTrackingViewAdapter cargo; + private String trackingId; + private CargoTrackingViewAdapter cargo; - public String getTrackingId() { - return trackingId; - } + public String getTrackingId() { + return trackingId; + } - public void setTrackingId(String trackingId) { - if (trackingId != null) { - trackingId = trackingId.trim(); - } + public void setTrackingId(String trackingId) { + if (trackingId != null) { + trackingId = trackingId.trim(); + } - this.trackingId = trackingId; - } + this.trackingId = trackingId; + } - public CargoTrackingViewAdapter getCargo() { - return cargo; - } + public CargoTrackingViewAdapter getCargo() { + return cargo; + } - public void setCargo(CargoTrackingViewAdapter cargo) { - this.cargo = cargo; - } + public void setCargo(CargoTrackingViewAdapter cargo) { + this.cargo = cargo; + } - public void onTrackById() { - Cargo cargo = cargoRepository.find(new TrackingId(trackingId)); + public void onTrackById() { + Cargo cargo = cargoRepository.find(new TrackingId(trackingId)); - if (cargo != null) { - List handlingEvents = handlingEventRepository - .lookupHandlingHistoryOfCargo(new TrackingId(trackingId)).getDistinctEventsByCompletionTime(); - this.cargo = new CargoTrackingViewAdapter(cargo, handlingEvents); - } else { - FacesContext context = FacesContext.getCurrentInstance(); - FacesMessage message = new FacesMessage("Cargo with tracking ID: " + trackingId + " not found."); - message.setSeverity(FacesMessage.SEVERITY_ERROR); - context.addMessage(null, message); - this.cargo = null; - } - } + if (cargo != null) { + List handlingEvents = + handlingEventRepository + .lookupHandlingHistoryOfCargo(new TrackingId(trackingId)) + .getDistinctEventsByCompletionTime(); + this.cargo = new CargoTrackingViewAdapter(cargo, handlingEvents); + } else { + FacesContext context = FacesContext.getCurrentInstance(); + FacesMessage message = + new FacesMessage("Cargo with tracking ID: " + trackingId + " not found."); + message.setSeverity(FacesMessage.SEVERITY_ERROR); + context.addMessage(null, message); + this.cargo = null; + } + } } diff --git a/src/main/java/org/eclipse/pathfinder/api/GraphTraversalService.java b/src/main/java/org/eclipse/pathfinder/api/GraphTraversalService.java index bf610a88a..cceeedc98 100644 --- a/src/main/java/org/eclipse/pathfinder/api/GraphTraversalService.java +++ b/src/main/java/org/eclipse/pathfinder/api/GraphTraversalService.java @@ -21,74 +21,84 @@ @Path("/graph-traversal") public class GraphTraversalService { - private static final long ONE_MIN_MS = 1000 * 60; - private static final long ONE_DAY_MS = ONE_MIN_MS * 60 * 24; - - @Inject - private GraphDao dao; - private final Random random = new Random(); - - @GET - @Path("/shortest-path") - @Produces({ "application/json", "application/xml; qs=.75" }) - public List findShortestPath( - @NotNull @Size(min = 5, max = 5) @QueryParam("origin") String originUnLocode, - @NotNull @Size(min = 5, max = 5) @QueryParam("destination") String destinationUnLocode, - @QueryParam("deadline") String deadline) { - Date date = nextDate(new Date()); - - List allVertices = dao.listLocations(); - allVertices.remove(originUnLocode); - allVertices.remove(destinationUnLocode); - - int candidateCount = getRandomNumberOfCandidates(); - List candidates = new ArrayList<>(candidateCount); - - for (int i = 0; i < candidateCount; i++) { - allVertices = getRandomChunkOfLocations(allVertices); - List transitEdges = new ArrayList<>(allVertices.size() - 1); - String firstLegTo = allVertices.get(0); - - Date fromDate = nextDate(date); - Date toDate = nextDate(fromDate); - date = nextDate(toDate); - - transitEdges.add(new TransitEdge(dao.getVoyageNumber(originUnLocode, firstLegTo), originUnLocode, - firstLegTo, fromDate, toDate)); - - for (int j = 0; j < allVertices.size() - 1; j++) { - String current = allVertices.get(j); - String next = allVertices.get(j + 1); - fromDate = nextDate(date); - toDate = nextDate(fromDate); - date = nextDate(toDate); - transitEdges.add(new TransitEdge(dao.getVoyageNumber(current, next), current, next, fromDate, toDate)); - } - - String lastLegFrom = allVertices.get(allVertices.size() - 1); - fromDate = nextDate(date); - toDate = nextDate(fromDate); - transitEdges.add(new TransitEdge(dao.getVoyageNumber(lastLegFrom, destinationUnLocode), lastLegFrom, - destinationUnLocode, fromDate, toDate)); - - candidates.add(new TransitPath(transitEdges)); - } - - return candidates; - } - - private Date nextDate(Date date) { - return new Date(date.getTime() + ONE_DAY_MS + (random.nextInt(1000) - 500) * ONE_MIN_MS); - } - - private int getRandomNumberOfCandidates() { - return 3 + random.nextInt(3); - } - - private List getRandomChunkOfLocations(List allLocations) { - Collections.shuffle(allLocations); - int total = allLocations.size(); - int chunk = total > 4 ? 1 + new Random().nextInt(5) : total; - return allLocations.subList(0, chunk); - } + private static final long ONE_MIN_MS = 1000 * 60; + private static final long ONE_DAY_MS = ONE_MIN_MS * 60 * 24; + + @Inject private GraphDao dao; + private final Random random = new Random(); + + @GET + @Path("/shortest-path") + @Produces({"application/json", "application/xml; qs=.75"}) + public List findShortestPath( + @NotNull @Size(min = 5, max = 5) @QueryParam("origin") String originUnLocode, + @NotNull @Size(min = 5, max = 5) @QueryParam("destination") String destinationUnLocode, + @QueryParam("deadline") String deadline) { + Date date = nextDate(new Date()); + + List allVertices = dao.listLocations(); + allVertices.remove(originUnLocode); + allVertices.remove(destinationUnLocode); + + int candidateCount = getRandomNumberOfCandidates(); + List candidates = new ArrayList<>(candidateCount); + + for (int i = 0; i < candidateCount; i++) { + allVertices = getRandomChunkOfLocations(allVertices); + List transitEdges = new ArrayList<>(allVertices.size() - 1); + String firstLegTo = allVertices.get(0); + + Date fromDate = nextDate(date); + Date toDate = nextDate(fromDate); + date = nextDate(toDate); + + transitEdges.add( + new TransitEdge( + dao.getVoyageNumber(originUnLocode, firstLegTo), + originUnLocode, + firstLegTo, + fromDate, + toDate)); + + for (int j = 0; j < allVertices.size() - 1; j++) { + String current = allVertices.get(j); + String next = allVertices.get(j + 1); + fromDate = nextDate(date); + toDate = nextDate(fromDate); + date = nextDate(toDate); + transitEdges.add( + new TransitEdge(dao.getVoyageNumber(current, next), current, next, fromDate, toDate)); + } + + String lastLegFrom = allVertices.get(allVertices.size() - 1); + fromDate = nextDate(date); + toDate = nextDate(fromDate); + transitEdges.add( + new TransitEdge( + dao.getVoyageNumber(lastLegFrom, destinationUnLocode), + lastLegFrom, + destinationUnLocode, + fromDate, + toDate)); + + candidates.add(new TransitPath(transitEdges)); + } + + return candidates; + } + + private Date nextDate(Date date) { + return new Date(date.getTime() + ONE_DAY_MS + (random.nextInt(1000) - 500) * ONE_MIN_MS); + } + + private int getRandomNumberOfCandidates() { + return 3 + random.nextInt(3); + } + + private List getRandomChunkOfLocations(List allLocations) { + Collections.shuffle(allLocations); + int total = allLocations.size(); + int chunk = total > 4 ? 1 + new Random().nextInt(5) : total; + return allLocations.subList(0, chunk); + } } diff --git a/src/main/java/org/eclipse/pathfinder/api/TransitEdge.java b/src/main/java/org/eclipse/pathfinder/api/TransitEdge.java index ca17e2820..6a48bda20 100644 --- a/src/main/java/org/eclipse/pathfinder/api/TransitEdge.java +++ b/src/main/java/org/eclipse/pathfinder/api/TransitEdge.java @@ -3,75 +3,83 @@ import java.io.Serializable; import java.util.Date; -/** - * Represents an edge in a path through a graph, describing the route of a - * cargo. - */ +/** Represents an edge in a path through a graph, describing the route of a cargo. */ public class TransitEdge implements Serializable { - private static final long serialVersionUID = 1L; - - private String voyageNumber; - private String fromUnLocode; - private String toUnLocode; - private Date fromDate; - private Date toDate; - - public TransitEdge() { - // Nothing to do. - } - - public TransitEdge(String voyageNumber, String fromUnLocode, String toUnLocode, Date fromDate, Date toDate) { - this.voyageNumber = voyageNumber; - this.fromUnLocode = fromUnLocode; - this.toUnLocode = toUnLocode; - this.fromDate = fromDate; - this.toDate = toDate; - } - - public String getVoyageNumber() { - return voyageNumber; - } - - public void setVoyageNumber(String voyageNumber) { - this.voyageNumber = voyageNumber; - } - - public String getFromUnLocode() { - return fromUnLocode; - } - - public void setFromUnLocode(String fromUnLocode) { - this.fromUnLocode = fromUnLocode; - } - - public String getToUnLocode() { - return toUnLocode; - } - - public void setToUnLocode(String toUnLocode) { - this.toUnLocode = toUnLocode; - } - - public Date getFromDate() { - return fromDate; - } - - public void setFromDate(Date fromDate) { - this.fromDate = fromDate; - } - - public Date getToDate() { - return toDate; - } - - public void setToDate(Date toDate) { - this.toDate = toDate; - } - - @Override - public String toString() { - return "TransitEdge{" + "voyageNumber=" + voyageNumber + ", fromUnLocode=" + fromUnLocode + ", toUnLocode=" - + toUnLocode + ", fromDate=" + fromDate + ", toDate=" + toDate + '}'; - } + private static final long serialVersionUID = 1L; + + private String voyageNumber; + private String fromUnLocode; + private String toUnLocode; + private Date fromDate; + private Date toDate; + + public TransitEdge() { + // Nothing to do. + } + + public TransitEdge( + String voyageNumber, String fromUnLocode, String toUnLocode, Date fromDate, Date toDate) { + this.voyageNumber = voyageNumber; + this.fromUnLocode = fromUnLocode; + this.toUnLocode = toUnLocode; + this.fromDate = fromDate; + this.toDate = toDate; + } + + public String getVoyageNumber() { + return voyageNumber; + } + + public void setVoyageNumber(String voyageNumber) { + this.voyageNumber = voyageNumber; + } + + public String getFromUnLocode() { + return fromUnLocode; + } + + public void setFromUnLocode(String fromUnLocode) { + this.fromUnLocode = fromUnLocode; + } + + public String getToUnLocode() { + return toUnLocode; + } + + public void setToUnLocode(String toUnLocode) { + this.toUnLocode = toUnLocode; + } + + public Date getFromDate() { + return fromDate; + } + + public void setFromDate(Date fromDate) { + this.fromDate = fromDate; + } + + public Date getToDate() { + return toDate; + } + + public void setToDate(Date toDate) { + this.toDate = toDate; + } + + @Override + public String toString() { + return "TransitEdge{" + + "voyageNumber=" + + voyageNumber + + ", fromUnLocode=" + + fromUnLocode + + ", toUnLocode=" + + toUnLocode + + ", fromDate=" + + fromDate + + ", toDate=" + + toDate + + '}'; + } } diff --git a/src/main/java/org/eclipse/pathfinder/api/TransitPath.java b/src/main/java/org/eclipse/pathfinder/api/TransitPath.java index d6e332bfe..e2489d7bc 100644 --- a/src/main/java/org/eclipse/pathfinder/api/TransitPath.java +++ b/src/main/java/org/eclipse/pathfinder/api/TransitPath.java @@ -9,28 +9,28 @@ @XmlRootElement public class TransitPath implements Serializable { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - private List transitEdges; + private List transitEdges; - public TransitPath() { - this.transitEdges = new ArrayList<>(); - } + public TransitPath() { + this.transitEdges = new ArrayList<>(); + } - public TransitPath(List transitEdges) { - this.transitEdges = transitEdges; - } + public TransitPath(List transitEdges) { + this.transitEdges = transitEdges; + } - public List getTransitEdges() { - return transitEdges; - } + public List getTransitEdges() { + return transitEdges; + } - public void setTransitEdges(List transitEdges) { - this.transitEdges = transitEdges; - } + public void setTransitEdges(List transitEdges) { + this.transitEdges = transitEdges; + } - @Override - public String toString() { - return "TransitPath{" + "transitEdges=" + transitEdges + '}'; - } + @Override + public String toString() { + return "TransitPath{" + "transitEdges=" + transitEdges + '}'; + } } diff --git a/src/main/java/org/eclipse/pathfinder/internal/GraphDao.java b/src/main/java/org/eclipse/pathfinder/internal/GraphDao.java index f480f0c45..f7726bd2d 100644 --- a/src/main/java/org/eclipse/pathfinder/internal/GraphDao.java +++ b/src/main/java/org/eclipse/pathfinder/internal/GraphDao.java @@ -11,29 +11,31 @@ @ApplicationScoped public class GraphDao implements Serializable { - private static final long serialVersionUID = 1L; - - private final Random random = new Random(); - - public List listLocations() { - return new ArrayList<>(Arrays.asList("CNHKG", "AUMEL", "SESTO", "FIHEL", "USCHI", "JNTKO", "DEHAM", "CNSHA", - "NLRTM", "SEGOT", "CNHGH", "USNYC", "USDAL")); - } - - public String getVoyageNumber(String from, String to) { - int i = random.nextInt(5); - - switch (i) { - case 0: - return "0100S"; - case 1: - return "0200T"; - case 2: - return "0300A"; - case 3: - return "0301S"; - default: - return "0400S"; - } - } + private static final long serialVersionUID = 1L; + + private final Random random = new Random(); + + public List listLocations() { + return new ArrayList<>( + Arrays.asList( + "CNHKG", "AUMEL", "SESTO", "FIHEL", "USCHI", "JNTKO", "DEHAM", "CNSHA", "NLRTM", + "SEGOT", "CNHGH", "USNYC", "USDAL")); + } + + public String getVoyageNumber(String from, String to) { + int i = random.nextInt(5); + + switch (i) { + case 0: + return "0100S"; + case 1: + return "0200T"; + case 2: + return "0300A"; + case 3: + return "0301S"; + default: + return "0400S"; + } + } } From d6caefbecbae412c8d45445ae0a0533e099ceceb Mon Sep 17 00:00:00 2001 From: Reza Rahman Date: Sun, 17 Jan 2021 10:17:19 -0500 Subject: [PATCH 09/22] Apply Google Java Style Guide --- .../application/BookingServiceTest.java | 383 ++++---- .../BookingServiceTestDataGenerator.java | 119 ++- .../BookingServiceTestRestConfiguration.java | 24 +- .../application/HandlingEventServiceTest.java | 85 +- .../domain/model/cargo/CargoTest.java | 832 +++++++++++------- .../domain/model/cargo/ItineraryTest.java | 238 +++-- .../model/cargo/RouteSpecificationTest.java | 114 ++- .../model/handling/HandlingEventTest.java | 176 ++-- .../model/handling/HandlingHistoryTest.java | 67 +- .../routing/ExternalRoutingServiceTest.java | 98 ++- .../scenario/CargoLifecycleScenarioTest.java | 657 ++++++++------ 11 files changed, 1645 insertions(+), 1148 deletions(-) diff --git a/src/test/java/org/eclipse/cargotracker/application/BookingServiceTest.java b/src/test/java/org/eclipse/cargotracker/application/BookingServiceTest.java index e7b384d82..00064708c 100644 --- a/src/test/java/org/eclipse/cargotracker/application/BookingServiceTest.java +++ b/src/test/java/org/eclipse/cargotracker/application/BookingServiceTest.java @@ -74,176 +74,223 @@ import org.junit.runner.RunWith; /** - * Application layer integration test covering a number of otherwise fairly - * trivial components that largely do not warrant their own tests. - * - * Ensure a Payara instance is running locally before this test is executed, - * with the default user name and password. + * Application layer integration test covering a number of otherwise fairly trivial components that + * largely do not warrant their own tests. + * + *

Ensure a Payara instance is running locally before this test is executed, with the default + * user name and password. */ -//TODO [Jakarta EE 8] Move to the Java Date-Time API for date manipulation. Also avoid hard-coded dates. +// TODO [Jakarta EE 8] Move to the Java Date-Time API for date manipulation. Also avoid hard-coded +// dates. @RunWith(Arquillian.class) public class BookingServiceTest { - @Inject - private BookingService bookingService; - @PersistenceContext - private EntityManager entityManager; - - private static TrackingId trackingId; - private static List candidates; - private static Date deadline; - private static Itinerary assigned; - - @Deployment - public static WebArchive createDeployment() { - WebArchive war = ShrinkWrap.create(WebArchive.class, "cargo-tracker-test.war") - // Application layer component directly under test. - .addClass(BookingService.class) - // Domain layer components. - .addClass(TrackingId.class).addClass(UnLocode.class).addClass(Itinerary.class).addClass(Leg.class) - .addClass(Voyage.class).addClass(VoyageNumber.class).addClass(Schedule.class) - .addClass(CarrierMovement.class).addClass(Location.class).addClass(HandlingEvent.class) - .addClass(Cargo.class).addClass(RouteSpecification.class).addClass(AbstractSpecification.class) - .addClass(Specification.class).addClass(AndSpecification.class).addClass(OrSpecification.class) - .addClass(NotSpecification.class).addClass(Delivery.class).addClass(TransportStatus.class) - .addClass(HandlingActivity.class).addClass(RoutingStatus.class).addClass(HandlingHistory.class) - .addClass(DomainObjectUtils.class).addClass(CargoRepository.class).addClass(LocationRepository.class) - .addClass(VoyageRepository.class).addClass(HandlingEventRepository.class) - .addClass(HandlingEventFactory.class).addClass(CannotCreateHandlingEventException.class) - .addClass(UnknownCargoException.class).addClass(UnknownVoyageException.class) - .addClass(UnknownLocationException.class).addClass(RoutingService.class) - // Application layer components - .addClass(DefaultBookingService.class) - // Infrastructure layer components. - .addClass(JpaCargoRepository.class).addClass(JpaVoyageRepository.class) - .addClass(JpaHandlingEventRepository.class).addClass(JpaLocationRepository.class) - .addClass(ExternalRoutingService.class).addClass(LoggerProducer.class) - .addClass(JsonMoxyConfigurationContextResolver.class) - // Interface components - .addClass(TransitPath.class).addClass(TransitEdge.class) - // Third-party system simulator - .addClass(GraphTraversalService.class).addClass(GraphDao.class) - // Sample data. - .addClass(BookingServiceTestDataGenerator.class).addClass(SampleLocations.class) - .addClass(SampleVoyages.class).addClass(DateUtil.class) - .addClass(BookingServiceTestRestConfiguration.class) - .addAsResource("META-INF/persistence.xml", "META-INF/persistence.xml"); - - war.addAsWebInfResource("test-web.xml", "web.xml"); - - war.addAsLibraries(Maven.resolver().loadPomFromFile("pom.xml").resolve("org.apache.commons:commons-lang3") - .withTransitivity().asFile()); - - return war; - } - - @Test - @InSequence(1) - public void testRegisterNew() { - UnLocode fromUnlocode = new UnLocode("USCHI"); - UnLocode toUnlocode = new UnLocode("SESTO"); - - deadline = new Date(); - GregorianCalendar calendar = new GregorianCalendar(); - calendar.setTime(deadline); - calendar.add(Calendar.MONTH, 6); // Six months ahead. - deadline.setTime(calendar.getTime().getTime()); - - trackingId = bookingService.bookNewCargo(fromUnlocode, toUnlocode, deadline); - - Cargo cargo = entityManager.createNamedQuery("Cargo.findByTrackingId", Cargo.class) - .setParameter("trackingId", trackingId).getSingleResult(); - - assertEquals(SampleLocations.CHICAGO, cargo.getOrigin()); - assertEquals(SampleLocations.STOCKHOLM, cargo.getRouteSpecification().getDestination()); - assertTrue(DateUtils.isSameDay(deadline, cargo.getRouteSpecification().getArrivalDeadline())); - assertEquals(TransportStatus.NOT_RECEIVED, cargo.getDelivery().getTransportStatus()); - assertEquals(Location.UNKNOWN, cargo.getDelivery().getLastKnownLocation()); - assertEquals(Voyage.NONE, cargo.getDelivery().getCurrentVoyage()); - assertFalse(cargo.getDelivery().isMisdirected()); - assertEquals(Delivery.ETA_UNKOWN, cargo.getDelivery().getEstimatedTimeOfArrival()); - assertEquals(Delivery.NO_ACTIVITY, cargo.getDelivery().getNextExpectedActivity()); - assertFalse(cargo.getDelivery().isUnloadedAtDestination()); - assertEquals(RoutingStatus.NOT_ROUTED, cargo.getDelivery().getRoutingStatus()); - assertEquals(Itinerary.EMPTY_ITINERARY, cargo.getItinerary()); - } - - @Test - @InSequence(2) - public void testRouteCandidates() { - candidates = bookingService.requestPossibleRoutesForCargo(trackingId); - - assertFalse(candidates.isEmpty()); - } - - @Test - @InSequence(3) - public void testAssignRoute() { - assigned = candidates.get(new Random().nextInt(candidates.size())); - - bookingService.assignCargoToRoute(assigned, trackingId); - - Cargo cargo = entityManager.createNamedQuery("Cargo.findByTrackingId", Cargo.class) - .setParameter("trackingId", trackingId).getSingleResult(); - - assertEquals(assigned, cargo.getItinerary()); - assertEquals(TransportStatus.NOT_RECEIVED, cargo.getDelivery().getTransportStatus()); - assertEquals(Location.UNKNOWN, cargo.getDelivery().getLastKnownLocation()); - assertEquals(Voyage.NONE, cargo.getDelivery().getCurrentVoyage()); - assertFalse(cargo.getDelivery().isMisdirected()); - assertTrue(cargo.getDelivery().getEstimatedTimeOfArrival().before(deadline)); - Assert.assertEquals(HandlingEvent.Type.RECEIVE, cargo.getDelivery().getNextExpectedActivity().getType()); - Assert.assertEquals(SampleLocations.CHICAGO, cargo.getDelivery().getNextExpectedActivity().getLocation()); - Assert.assertEquals(null, cargo.getDelivery().getNextExpectedActivity().getVoyage()); - assertFalse(cargo.getDelivery().isUnloadedAtDestination()); - assertEquals(RoutingStatus.ROUTED, cargo.getDelivery().getRoutingStatus()); - } - - @Test - @InSequence(4) - public void testChangeDestination() { - bookingService.changeDestination(trackingId, new UnLocode("FIHEL")); - - Cargo cargo = entityManager.createNamedQuery("Cargo.findByTrackingId", Cargo.class) - .setParameter("trackingId", trackingId).getSingleResult(); - - assertEquals(SampleLocations.CHICAGO, cargo.getOrigin()); - assertEquals(SampleLocations.HELSINKI, cargo.getRouteSpecification().getDestination()); - assertTrue(DateUtils.isSameDay(deadline, cargo.getRouteSpecification().getArrivalDeadline())); - assertEquals(assigned, cargo.getItinerary()); - assertEquals(TransportStatus.NOT_RECEIVED, cargo.getDelivery().getTransportStatus()); - assertEquals(Location.UNKNOWN, cargo.getDelivery().getLastKnownLocation()); - assertEquals(Voyage.NONE, cargo.getDelivery().getCurrentVoyage()); - assertFalse(cargo.getDelivery().isMisdirected()); - assertEquals(Delivery.ETA_UNKOWN, cargo.getDelivery().getEstimatedTimeOfArrival()); - assertEquals(Delivery.NO_ACTIVITY, cargo.getDelivery().getNextExpectedActivity()); - assertFalse(cargo.getDelivery().isUnloadedAtDestination()); - assertEquals(RoutingStatus.MISROUTED, cargo.getDelivery().getRoutingStatus()); - } - - @Test - @InSequence(5) - public void testChangeDeadline() { - Calendar cal = Calendar.getInstance(); - cal.setTime(deadline); - cal.add(Calendar.MONTH, 1); // Change the deadline one month ahead of the original - Date newDeadline = cal.getTime(); - bookingService.changeDeadline(trackingId, newDeadline); - - Cargo cargo = entityManager.createNamedQuery("Cargo.findByTrackingId", Cargo.class) - .setParameter("trackingId", trackingId).getSingleResult(); - - assertEquals(SampleLocations.CHICAGO, cargo.getOrigin()); - assertEquals(SampleLocations.HELSINKI, cargo.getRouteSpecification().getDestination()); - assertTrue(DateUtils.isSameDay(newDeadline, cargo.getRouteSpecification().getArrivalDeadline())); - assertEquals(assigned, cargo.getItinerary()); - assertEquals(TransportStatus.NOT_RECEIVED, cargo.getDelivery().getTransportStatus()); - assertEquals(Location.UNKNOWN, cargo.getDelivery().getLastKnownLocation()); - assertEquals(Voyage.NONE, cargo.getDelivery().getCurrentVoyage()); - assertFalse(cargo.getDelivery().isMisdirected()); - assertEquals(Delivery.ETA_UNKOWN, cargo.getDelivery().getEstimatedTimeOfArrival()); - assertEquals(Delivery.NO_ACTIVITY, cargo.getDelivery().getNextExpectedActivity()); - assertFalse(cargo.getDelivery().isUnloadedAtDestination()); - assertEquals(RoutingStatus.MISROUTED, cargo.getDelivery().getRoutingStatus()); - } + @Inject private BookingService bookingService; + @PersistenceContext private EntityManager entityManager; + + private static TrackingId trackingId; + private static List candidates; + private static Date deadline; + private static Itinerary assigned; + + @Deployment + public static WebArchive createDeployment() { + WebArchive war = + ShrinkWrap.create(WebArchive.class, "cargo-tracker-test.war") + // Application layer component directly under test. + .addClass(BookingService.class) + // Domain layer components. + .addClass(TrackingId.class) + .addClass(UnLocode.class) + .addClass(Itinerary.class) + .addClass(Leg.class) + .addClass(Voyage.class) + .addClass(VoyageNumber.class) + .addClass(Schedule.class) + .addClass(CarrierMovement.class) + .addClass(Location.class) + .addClass(HandlingEvent.class) + .addClass(Cargo.class) + .addClass(RouteSpecification.class) + .addClass(AbstractSpecification.class) + .addClass(Specification.class) + .addClass(AndSpecification.class) + .addClass(OrSpecification.class) + .addClass(NotSpecification.class) + .addClass(Delivery.class) + .addClass(TransportStatus.class) + .addClass(HandlingActivity.class) + .addClass(RoutingStatus.class) + .addClass(HandlingHistory.class) + .addClass(DomainObjectUtils.class) + .addClass(CargoRepository.class) + .addClass(LocationRepository.class) + .addClass(VoyageRepository.class) + .addClass(HandlingEventRepository.class) + .addClass(HandlingEventFactory.class) + .addClass(CannotCreateHandlingEventException.class) + .addClass(UnknownCargoException.class) + .addClass(UnknownVoyageException.class) + .addClass(UnknownLocationException.class) + .addClass(RoutingService.class) + // Application layer components + .addClass(DefaultBookingService.class) + // Infrastructure layer components. + .addClass(JpaCargoRepository.class) + .addClass(JpaVoyageRepository.class) + .addClass(JpaHandlingEventRepository.class) + .addClass(JpaLocationRepository.class) + .addClass(ExternalRoutingService.class) + .addClass(LoggerProducer.class) + .addClass(JsonMoxyConfigurationContextResolver.class) + // Interface components + .addClass(TransitPath.class) + .addClass(TransitEdge.class) + // Third-party system simulator + .addClass(GraphTraversalService.class) + .addClass(GraphDao.class) + // Sample data. + .addClass(BookingServiceTestDataGenerator.class) + .addClass(SampleLocations.class) + .addClass(SampleVoyages.class) + .addClass(DateUtil.class) + .addClass(BookingServiceTestRestConfiguration.class) + .addAsResource("META-INF/persistence.xml", "META-INF/persistence.xml"); + + war.addAsWebInfResource("test-web.xml", "web.xml"); + + war.addAsLibraries( + Maven.resolver() + .loadPomFromFile("pom.xml") + .resolve("org.apache.commons:commons-lang3") + .withTransitivity() + .asFile()); + + return war; + } + + @Test + @InSequence(1) + public void testRegisterNew() { + UnLocode fromUnlocode = new UnLocode("USCHI"); + UnLocode toUnlocode = new UnLocode("SESTO"); + + deadline = new Date(); + GregorianCalendar calendar = new GregorianCalendar(); + calendar.setTime(deadline); + calendar.add(Calendar.MONTH, 6); // Six months ahead. + deadline.setTime(calendar.getTime().getTime()); + + trackingId = bookingService.bookNewCargo(fromUnlocode, toUnlocode, deadline); + + Cargo cargo = + entityManager + .createNamedQuery("Cargo.findByTrackingId", Cargo.class) + .setParameter("trackingId", trackingId) + .getSingleResult(); + + assertEquals(SampleLocations.CHICAGO, cargo.getOrigin()); + assertEquals(SampleLocations.STOCKHOLM, cargo.getRouteSpecification().getDestination()); + assertTrue(DateUtils.isSameDay(deadline, cargo.getRouteSpecification().getArrivalDeadline())); + assertEquals(TransportStatus.NOT_RECEIVED, cargo.getDelivery().getTransportStatus()); + assertEquals(Location.UNKNOWN, cargo.getDelivery().getLastKnownLocation()); + assertEquals(Voyage.NONE, cargo.getDelivery().getCurrentVoyage()); + assertFalse(cargo.getDelivery().isMisdirected()); + assertEquals(Delivery.ETA_UNKOWN, cargo.getDelivery().getEstimatedTimeOfArrival()); + assertEquals(Delivery.NO_ACTIVITY, cargo.getDelivery().getNextExpectedActivity()); + assertFalse(cargo.getDelivery().isUnloadedAtDestination()); + assertEquals(RoutingStatus.NOT_ROUTED, cargo.getDelivery().getRoutingStatus()); + assertEquals(Itinerary.EMPTY_ITINERARY, cargo.getItinerary()); + } + + @Test + @InSequence(2) + public void testRouteCandidates() { + candidates = bookingService.requestPossibleRoutesForCargo(trackingId); + + assertFalse(candidates.isEmpty()); + } + + @Test + @InSequence(3) + public void testAssignRoute() { + assigned = candidates.get(new Random().nextInt(candidates.size())); + + bookingService.assignCargoToRoute(assigned, trackingId); + + Cargo cargo = + entityManager + .createNamedQuery("Cargo.findByTrackingId", Cargo.class) + .setParameter("trackingId", trackingId) + .getSingleResult(); + + assertEquals(assigned, cargo.getItinerary()); + assertEquals(TransportStatus.NOT_RECEIVED, cargo.getDelivery().getTransportStatus()); + assertEquals(Location.UNKNOWN, cargo.getDelivery().getLastKnownLocation()); + assertEquals(Voyage.NONE, cargo.getDelivery().getCurrentVoyage()); + assertFalse(cargo.getDelivery().isMisdirected()); + assertTrue(cargo.getDelivery().getEstimatedTimeOfArrival().before(deadline)); + Assert.assertEquals( + HandlingEvent.Type.RECEIVE, cargo.getDelivery().getNextExpectedActivity().getType()); + Assert.assertEquals( + SampleLocations.CHICAGO, cargo.getDelivery().getNextExpectedActivity().getLocation()); + Assert.assertEquals(null, cargo.getDelivery().getNextExpectedActivity().getVoyage()); + assertFalse(cargo.getDelivery().isUnloadedAtDestination()); + assertEquals(RoutingStatus.ROUTED, cargo.getDelivery().getRoutingStatus()); + } + + @Test + @InSequence(4) + public void testChangeDestination() { + bookingService.changeDestination(trackingId, new UnLocode("FIHEL")); + + Cargo cargo = + entityManager + .createNamedQuery("Cargo.findByTrackingId", Cargo.class) + .setParameter("trackingId", trackingId) + .getSingleResult(); + + assertEquals(SampleLocations.CHICAGO, cargo.getOrigin()); + assertEquals(SampleLocations.HELSINKI, cargo.getRouteSpecification().getDestination()); + assertTrue(DateUtils.isSameDay(deadline, cargo.getRouteSpecification().getArrivalDeadline())); + assertEquals(assigned, cargo.getItinerary()); + assertEquals(TransportStatus.NOT_RECEIVED, cargo.getDelivery().getTransportStatus()); + assertEquals(Location.UNKNOWN, cargo.getDelivery().getLastKnownLocation()); + assertEquals(Voyage.NONE, cargo.getDelivery().getCurrentVoyage()); + assertFalse(cargo.getDelivery().isMisdirected()); + assertEquals(Delivery.ETA_UNKOWN, cargo.getDelivery().getEstimatedTimeOfArrival()); + assertEquals(Delivery.NO_ACTIVITY, cargo.getDelivery().getNextExpectedActivity()); + assertFalse(cargo.getDelivery().isUnloadedAtDestination()); + assertEquals(RoutingStatus.MISROUTED, cargo.getDelivery().getRoutingStatus()); + } + + @Test + @InSequence(5) + public void testChangeDeadline() { + Calendar cal = Calendar.getInstance(); + cal.setTime(deadline); + cal.add(Calendar.MONTH, 1); // Change the deadline one month ahead of the original + Date newDeadline = cal.getTime(); + bookingService.changeDeadline(trackingId, newDeadline); + + Cargo cargo = + entityManager + .createNamedQuery("Cargo.findByTrackingId", Cargo.class) + .setParameter("trackingId", trackingId) + .getSingleResult(); + + assertEquals(SampleLocations.CHICAGO, cargo.getOrigin()); + assertEquals(SampleLocations.HELSINKI, cargo.getRouteSpecification().getDestination()); + assertTrue( + DateUtils.isSameDay(newDeadline, cargo.getRouteSpecification().getArrivalDeadline())); + assertEquals(assigned, cargo.getItinerary()); + assertEquals(TransportStatus.NOT_RECEIVED, cargo.getDelivery().getTransportStatus()); + assertEquals(Location.UNKNOWN, cargo.getDelivery().getLastKnownLocation()); + assertEquals(Voyage.NONE, cargo.getDelivery().getCurrentVoyage()); + assertFalse(cargo.getDelivery().isMisdirected()); + assertEquals(Delivery.ETA_UNKOWN, cargo.getDelivery().getEstimatedTimeOfArrival()); + assertEquals(Delivery.NO_ACTIVITY, cargo.getDelivery().getNextExpectedActivity()); + assertFalse(cargo.getDelivery().isUnloadedAtDestination()); + assertEquals(RoutingStatus.MISROUTED, cargo.getDelivery().getRoutingStatus()); + } } diff --git a/src/test/java/org/eclipse/cargotracker/application/BookingServiceTestDataGenerator.java b/src/test/java/org/eclipse/cargotracker/application/BookingServiceTestDataGenerator.java index bb0382cfc..70e8b8dc2 100644 --- a/src/test/java/org/eclipse/cargotracker/application/BookingServiceTestDataGenerator.java +++ b/src/test/java/org/eclipse/cargotracker/application/BookingServiceTestDataGenerator.java @@ -16,76 +16,73 @@ import org.eclipse.cargotracker.domain.model.location.SampleLocations; import org.eclipse.cargotracker.domain.model.voyage.SampleVoyages; -/** - * Loads sample data for demo. - */ +/** Loads sample data for demo. */ @Singleton @Startup public class BookingServiceTestDataGenerator { - @Inject - private Logger logger; - @PersistenceContext - private EntityManager entityManager; + @Inject private Logger logger; + @PersistenceContext private EntityManager entityManager; - @PostConstruct - @TransactionAttribute(TransactionAttributeType.REQUIRED) - public void loadSampleData() { - logger.info("Loading sample data."); - unLoadAll(); // Fail-safe in case of application restart that does not - // trigger a JPA schema drop. - loadSampleLocations(); - loadSampleVoyages(); - // loadSampleCargos(); - } + @PostConstruct + @TransactionAttribute(TransactionAttributeType.REQUIRED) + public void loadSampleData() { + logger.info("Loading sample data."); + unLoadAll(); // Fail-safe in case of application restart that does not + // trigger a JPA schema drop. + loadSampleLocations(); + loadSampleVoyages(); + // loadSampleCargos(); + } - private void unLoadAll() { - logger.info("Unloading all existing data."); - // In order to remove handling events, must remove references in cargo. - // Dropping cargo first won't work since handling events have references - // to it. - // TODO [Clean Code] See if there is a better way to do this. - List cargos = entityManager.createQuery("Select c from Cargo c", Cargo.class).getResultList(); - for (Cargo cargo : cargos) { - cargo.getDelivery().setLastEvent(null); - entityManager.merge(cargo); - } + private void unLoadAll() { + logger.info("Unloading all existing data."); + // In order to remove handling events, must remove references in cargo. + // Dropping cargo first won't work since handling events have references + // to it. + // TODO [Clean Code] See if there is a better way to do this. + List cargos = + entityManager.createQuery("Select c from Cargo c", Cargo.class).getResultList(); + for (Cargo cargo : cargos) { + cargo.getDelivery().setLastEvent(null); + entityManager.merge(cargo); + } - // Delete all entities - // TODO [Clean Code] See why cascade delete is not working. - entityManager.createQuery("Delete from HandlingEvent").executeUpdate(); - entityManager.createQuery("Delete from Leg").executeUpdate(); - entityManager.createQuery("Delete from Cargo").executeUpdate(); - entityManager.createQuery("Delete from CarrierMovement").executeUpdate(); - entityManager.createQuery("Delete from Voyage").executeUpdate(); - entityManager.createQuery("Delete from Location").executeUpdate(); - } + // Delete all entities + // TODO [Clean Code] See why cascade delete is not working. + entityManager.createQuery("Delete from HandlingEvent").executeUpdate(); + entityManager.createQuery("Delete from Leg").executeUpdate(); + entityManager.createQuery("Delete from Cargo").executeUpdate(); + entityManager.createQuery("Delete from CarrierMovement").executeUpdate(); + entityManager.createQuery("Delete from Voyage").executeUpdate(); + entityManager.createQuery("Delete from Location").executeUpdate(); + } - private void loadSampleLocations() { - logger.info("Loading sample locations."); + private void loadSampleLocations() { + logger.info("Loading sample locations."); - entityManager.persist(SampleLocations.HONGKONG); - entityManager.persist(SampleLocations.MELBOURNE); - entityManager.persist(SampleLocations.STOCKHOLM); - entityManager.persist(SampleLocations.HELSINKI); - entityManager.persist(SampleLocations.CHICAGO); - entityManager.persist(SampleLocations.TOKYO); - entityManager.persist(SampleLocations.HAMBURG); - entityManager.persist(SampleLocations.SHANGHAI); - entityManager.persist(SampleLocations.ROTTERDAM); - entityManager.persist(SampleLocations.GOTHENBURG); - entityManager.persist(SampleLocations.HANGZOU); - entityManager.persist(SampleLocations.NEWYORK); - entityManager.persist(SampleLocations.DALLAS); - } + entityManager.persist(SampleLocations.HONGKONG); + entityManager.persist(SampleLocations.MELBOURNE); + entityManager.persist(SampleLocations.STOCKHOLM); + entityManager.persist(SampleLocations.HELSINKI); + entityManager.persist(SampleLocations.CHICAGO); + entityManager.persist(SampleLocations.TOKYO); + entityManager.persist(SampleLocations.HAMBURG); + entityManager.persist(SampleLocations.SHANGHAI); + entityManager.persist(SampleLocations.ROTTERDAM); + entityManager.persist(SampleLocations.GOTHENBURG); + entityManager.persist(SampleLocations.HANGZOU); + entityManager.persist(SampleLocations.NEWYORK); + entityManager.persist(SampleLocations.DALLAS); + } - private void loadSampleVoyages() { - logger.info("Loading sample voyages."); + private void loadSampleVoyages() { + logger.info("Loading sample voyages."); - entityManager.persist(SampleVoyages.HONGKONG_TO_NEW_YORK); - entityManager.persist(SampleVoyages.NEW_YORK_TO_DALLAS); - entityManager.persist(SampleVoyages.DALLAS_TO_HELSINKI); - entityManager.persist(SampleVoyages.HELSINKI_TO_HONGKONG); - entityManager.persist(SampleVoyages.DALLAS_TO_HELSINKI_ALT); - } + entityManager.persist(SampleVoyages.HONGKONG_TO_NEW_YORK); + entityManager.persist(SampleVoyages.NEW_YORK_TO_DALLAS); + entityManager.persist(SampleVoyages.DALLAS_TO_HELSINKI); + entityManager.persist(SampleVoyages.HELSINKI_TO_HONGKONG); + entityManager.persist(SampleVoyages.DALLAS_TO_HELSINKI_ALT); + } } diff --git a/src/test/java/org/eclipse/cargotracker/application/BookingServiceTestRestConfiguration.java b/src/test/java/org/eclipse/cargotracker/application/BookingServiceTestRestConfiguration.java index e5f732e66..576f2f42f 100644 --- a/src/test/java/org/eclipse/cargotracker/application/BookingServiceTestRestConfiguration.java +++ b/src/test/java/org/eclipse/cargotracker/application/BookingServiceTestRestConfiguration.java @@ -1,23 +1,23 @@ package org.eclipse.cargotracker.application; +import javax.ws.rs.ApplicationPath; + import org.eclipse.cargotracker.application.util.JsonMoxyConfigurationContextResolver; import org.eclipse.pathfinder.api.GraphTraversalService; import org.glassfish.jersey.moxy.json.MoxyJsonFeature; import org.glassfish.jersey.server.ResourceConfig; -import javax.ws.rs.ApplicationPath; - -/** - * JAX-RS configuration. - */ +/** JAX-RS configuration. */ @ApplicationPath("rest") public class BookingServiceTestRestConfiguration extends ResourceConfig { - public BookingServiceTestRestConfiguration() { - // Resources - packages(new String[]{GraphTraversalService.class.getPackage().getName()}); - // Providers - JSON. - register(new MoxyJsonFeature()); - register(new JsonMoxyConfigurationContextResolver()); // TODO [Jakarta EE 8] See if this can be removed. - } + public BookingServiceTestRestConfiguration() { + // Resources + packages(new String[] {GraphTraversalService.class.getPackage().getName()}); + // Providers - JSON. + register(new MoxyJsonFeature()); + register( + new JsonMoxyConfigurationContextResolver()); // TODO [Jakarta EE 8] See if this can be + // removed. + } } diff --git a/src/test/java/org/eclipse/cargotracker/application/HandlingEventServiceTest.java b/src/test/java/org/eclipse/cargotracker/application/HandlingEventServiceTest.java index 8229f0b86..4818c70bf 100644 --- a/src/test/java/org/eclipse/cargotracker/application/HandlingEventServiceTest.java +++ b/src/test/java/org/eclipse/cargotracker/application/HandlingEventServiceTest.java @@ -12,43 +12,50 @@ public class HandlingEventServiceTest { - private DefaultHandlingEventService service; -// private ApplicationEvents applicationEvents; -// private CargoRepository cargoRepository; -// private VoyageRepository voyageRepository; -// private HandlingEventRepository handlingEventRepository; -// private LocationRepository locationRepository; - private Cargo cargo = new Cargo(new TrackingId("ABC"), - new RouteSpecification(SampleLocations.HAMBURG, SampleLocations.TOKYO, new Date())); - - protected void setUp() throws Exception { -// cargoRepository = createMock(CargoRepository.class); -// voyageRepository = createMock(VoyageRepository.class); -// handlingEventRepository = createMock(HandlingEventRepository.class); -// locationRepository = createMock(LocationRepository.class); -// applicationEvents = createMock(ApplicationEvents.class); -// HandlingEventFactory handlingEventFactory = new HandlingEventFactory( -// cargoRepository, voyageRepository, locationRepository); -// service = new DefaultHandlingEventService(handlingEventRepository, applicationEvents, handlingEventFactory); - } - - protected void tearDown() throws Exception { -// verify(cargoRepository, voyageRepository, handlingEventRepository, applicationEvents); - } - - public void testRegisterEvent() throws Exception { -// expect(cargoRepository.find(cargo.getTrackingId())).andReturn(cargo); -// expect(voyageRepository.find(SampleVoyages.CM001.getVoyageNumber())) -// .andReturn(SampleVoyages.CM001); -// expect(locationRepository.find(SampleLocations.STOCKHOLM.getUnLocode())) -// .andReturn(SampleLocations.STOCKHOLM); -// handlingEventRepository.store(isA(HandlingEvent.class)); -// applicationEvents.cargoWasHandled(isA(HandlingEvent.class)); - -// replay(cargoRepository, voyageRepository, handlingEventRepository, -// locationRepository, applicationEvents); - - service.registerHandlingEvent(new Date(), cargo.getTrackingId(), SampleVoyages.CM001.getVoyageNumber(), - SampleLocations.STOCKHOLM.getUnLocode(), HandlingEvent.Type.LOAD); - } + private DefaultHandlingEventService service; + // private ApplicationEvents applicationEvents; + // private CargoRepository cargoRepository; + // private VoyageRepository voyageRepository; + // private HandlingEventRepository handlingEventRepository; + // private LocationRepository locationRepository; + private Cargo cargo = + new Cargo( + new TrackingId("ABC"), + new RouteSpecification(SampleLocations.HAMBURG, SampleLocations.TOKYO, new Date())); + + protected void setUp() throws Exception { + // cargoRepository = createMock(CargoRepository.class); + // voyageRepository = createMock(VoyageRepository.class); + // handlingEventRepository = createMock(HandlingEventRepository.class); + // locationRepository = createMock(LocationRepository.class); + // applicationEvents = createMock(ApplicationEvents.class); + // HandlingEventFactory handlingEventFactory = new HandlingEventFactory( + // cargoRepository, voyageRepository, locationRepository); + // service = new DefaultHandlingEventService(handlingEventRepository, applicationEvents, + // handlingEventFactory); + } + + protected void tearDown() throws Exception { + // verify(cargoRepository, voyageRepository, handlingEventRepository, applicationEvents); + } + + public void testRegisterEvent() throws Exception { + // expect(cargoRepository.find(cargo.getTrackingId())).andReturn(cargo); + // expect(voyageRepository.find(SampleVoyages.CM001.getVoyageNumber())) + // .andReturn(SampleVoyages.CM001); + // expect(locationRepository.find(SampleLocations.STOCKHOLM.getUnLocode())) + // .andReturn(SampleLocations.STOCKHOLM); + // handlingEventRepository.store(isA(HandlingEvent.class)); + // applicationEvents.cargoWasHandled(isA(HandlingEvent.class)); + + // replay(cargoRepository, voyageRepository, handlingEventRepository, + // locationRepository, applicationEvents); + + service.registerHandlingEvent( + new Date(), + cargo.getTrackingId(), + SampleVoyages.CM001.getVoyageNumber(), + SampleLocations.STOCKHOLM.getUnLocode(), + HandlingEvent.Type.LOAD); + } } diff --git a/src/test/java/org/eclipse/cargotracker/domain/model/cargo/CargoTest.java b/src/test/java/org/eclipse/cargotracker/domain/model/cargo/CargoTest.java index 8ac10f0a4..38a3ca336 100644 --- a/src/test/java/org/eclipse/cargotracker/domain/model/cargo/CargoTest.java +++ b/src/test/java/org/eclipse/cargotracker/domain/model/cargo/CargoTest.java @@ -23,311 +23,533 @@ import org.junit.Assert; import org.junit.Test; -// TODO [Jakarta EE 8] Move to the Java Date-Time API for date manipulation. Also avoid hard-coded dates. +// TODO [Jakarta EE 8] Move to the Java Date-Time API for date manipulation. Also avoid hard-coded +// dates. public class CargoTest { - private final List events = new ArrayList<>(); - private final Voyage voyage = new Voyage.Builder(new VoyageNumber("0123"), SampleLocations.STOCKHOLM) - .addMovement(SampleLocations.HAMBURG, new Date(), new Date()) - .addMovement(SampleLocations.HONGKONG, new Date(), new Date()) - .addMovement(SampleLocations.MELBOURNE, new Date(), new Date()).build(); - - @Test - public void testConstruction() { - TrackingId trackingId = new TrackingId("XYZ"); - Date arrivalDeadline = DateUtil.toDate("2009-03-13"); - RouteSpecification routeSpecification = new RouteSpecification(SampleLocations.STOCKHOLM, - SampleLocations.MELBOURNE, arrivalDeadline); - - Cargo cargo = new Cargo(trackingId, routeSpecification); - - assertEquals(RoutingStatus.NOT_ROUTED, cargo.getDelivery().getRoutingStatus()); - assertEquals(TransportStatus.NOT_RECEIVED, cargo.getDelivery().getTransportStatus()); - Assert.assertEquals(Location.UNKNOWN, cargo.getDelivery().getLastKnownLocation()); - Assert.assertEquals(Voyage.NONE, cargo.getDelivery().getCurrentVoyage()); - } - - @Test - public void testRoutingStatus() { - Cargo cargo = new Cargo(new TrackingId("XYZ"), - new RouteSpecification(SampleLocations.STOCKHOLM, SampleLocations.MELBOURNE, new Date())); - final Itinerary good = new Itinerary(); - Itinerary bad = new Itinerary(); - @SuppressWarnings("serial") - RouteSpecification acceptOnlyGood = new RouteSpecification(cargo.getOrigin(), - cargo.getRouteSpecification().getDestination(), new Date()) { - - @Override - public boolean isSatisfiedBy(Itinerary itinerary) { - return itinerary == good; - } - }; - - cargo.specifyNewRoute(acceptOnlyGood); - - assertEquals(RoutingStatus.NOT_ROUTED, cargo.getDelivery().getRoutingStatus()); - - cargo.assignToRoute(bad); - assertEquals(RoutingStatus.MISROUTED, cargo.getDelivery().getRoutingStatus()); - - cargo.assignToRoute(good); - assertEquals(RoutingStatus.ROUTED, cargo.getDelivery().getRoutingStatus()); - } - - @Test - public void testLastKnownLocationUnknownWhenNoEvents() { - Cargo cargo = new Cargo(new TrackingId("XYZ"), - new RouteSpecification(SampleLocations.STOCKHOLM, SampleLocations.MELBOURNE, new Date())); - - Assert.assertEquals(Location.UNKNOWN, cargo.getDelivery().getLastKnownLocation()); - } - - @Test - public void testLastKnownLocationReceived() throws Exception { - Cargo cargo = populateCargoReceivedStockholm(); - - Assert.assertEquals(SampleLocations.STOCKHOLM, cargo.getDelivery().getLastKnownLocation()); - } - - @Test - public void testLastKnownLocationClaimed() throws Exception { - Cargo cargo = populateCargoClaimedMelbourne(); - - Assert.assertEquals(SampleLocations.MELBOURNE, cargo.getDelivery().getLastKnownLocation()); - } - - @Test - public void testLastKnownLocationUnloaded() throws Exception { - Cargo cargo = populateCargoOffHongKong(); - - Assert.assertEquals(SampleLocations.HONGKONG, cargo.getDelivery().getLastKnownLocation()); - } - - @Test - public void testLastKnownLocationloaded() throws Exception { - Cargo cargo = populateCargoOnHamburg(); - - Assert.assertEquals(SampleLocations.HAMBURG, cargo.getDelivery().getLastKnownLocation()); - } - - @Test - public void testIsUnloadedAtFinalDestination() { - Cargo cargo = setUpCargoWithItinerary(SampleLocations.HANGZOU, SampleLocations.TOKYO, SampleLocations.NEWYORK); - assertFalse(cargo.getDelivery().isUnloadedAtDestination()); - - // Adding an event unrelated to unloading at final destination - events.add(new HandlingEvent(cargo, new Date(10), new Date(), HandlingEvent.Type.RECEIVE, - SampleLocations.HANGZOU)); - cargo.deriveDeliveryProgress(new HandlingHistory(events)); - assertFalse(cargo.getDelivery().isUnloadedAtDestination()); - - Voyage voyage = new Voyage.Builder(new VoyageNumber("0123"), SampleLocations.HANGZOU) - .addMovement(SampleLocations.NEWYORK, new Date(), new Date()).build(); - - // Adding an unload event, but not at the final destination - events.add(new HandlingEvent(cargo, new Date(20), new Date(), HandlingEvent.Type.UNLOAD, SampleLocations.TOKYO, - voyage)); - cargo.deriveDeliveryProgress(new HandlingHistory(events)); - assertFalse(cargo.getDelivery().isUnloadedAtDestination()); - - // Adding an event in the final destination, but not unload - events.add(new HandlingEvent(cargo, new Date(30), new Date(), HandlingEvent.Type.CUSTOMS, - SampleLocations.NEWYORK)); - cargo.deriveDeliveryProgress(new HandlingHistory(events)); - assertFalse(cargo.getDelivery().isUnloadedAtDestination()); - - // Finally, cargo is unloaded at final destination - events.add(new HandlingEvent(cargo, new Date(40), new Date(), HandlingEvent.Type.UNLOAD, - SampleLocations.NEWYORK, voyage)); - cargo.deriveDeliveryProgress(new HandlingHistory(events)); - assertTrue(cargo.getDelivery().isUnloadedAtDestination()); - } - - // TODO [TDD] Generate test data some better way - private Cargo populateCargoReceivedStockholm() throws Exception { - Cargo cargo = new Cargo(new TrackingId("XYZ"), - new RouteSpecification(SampleLocations.STOCKHOLM, SampleLocations.MELBOURNE, new Date())); - - HandlingEvent event = new HandlingEvent(cargo, getDate("2007-12-01"), new Date(), HandlingEvent.Type.RECEIVE, - SampleLocations.STOCKHOLM); - events.add(event); - cargo.deriveDeliveryProgress(new HandlingHistory(events)); - - return cargo; - } - - private Cargo populateCargoClaimedMelbourne() throws Exception { - Cargo cargo = populateCargoOffMelbourne(); - - events.add(new HandlingEvent(cargo, getDate("2007-12-09"), new Date(), HandlingEvent.Type.CLAIM, - SampleLocations.MELBOURNE)); - cargo.deriveDeliveryProgress(new HandlingHistory(events)); - - return cargo; - } - - private Cargo populateCargoOffHongKong() throws Exception { - Cargo cargo = new Cargo(new TrackingId("XYZ"), - new RouteSpecification(SampleLocations.STOCKHOLM, SampleLocations.MELBOURNE, new Date())); - - events.add(new HandlingEvent(cargo, getDate("2007-12-01"), new Date(), HandlingEvent.Type.LOAD, - SampleLocations.STOCKHOLM, voyage)); - events.add(new HandlingEvent(cargo, getDate("2007-12-02"), new Date(), HandlingEvent.Type.UNLOAD, - SampleLocations.HAMBURG, voyage)); - - events.add(new HandlingEvent(cargo, getDate("2007-12-03"), new Date(), HandlingEvent.Type.LOAD, - SampleLocations.HAMBURG, voyage)); - events.add(new HandlingEvent(cargo, getDate("2007-12-04"), new Date(), HandlingEvent.Type.UNLOAD, - SampleLocations.HONGKONG, voyage)); - - cargo.deriveDeliveryProgress(new HandlingHistory(events)); - - return cargo; - } - - private Cargo populateCargoOnHamburg() throws Exception { - Cargo cargo = new Cargo(new TrackingId("XYZ"), - new RouteSpecification(SampleLocations.STOCKHOLM, SampleLocations.MELBOURNE, new Date())); - - events.add(new HandlingEvent(cargo, getDate("2007-12-01"), new Date(), HandlingEvent.Type.LOAD, - SampleLocations.STOCKHOLM, voyage)); - events.add(new HandlingEvent(cargo, getDate("2007-12-02"), new Date(), HandlingEvent.Type.UNLOAD, - SampleLocations.HAMBURG, voyage)); - events.add(new HandlingEvent(cargo, getDate("2007-12-03"), new Date(), HandlingEvent.Type.LOAD, - SampleLocations.HAMBURG, voyage)); - - cargo.deriveDeliveryProgress(new HandlingHistory(events)); - - return cargo; - } - - private Cargo populateCargoOffMelbourne() throws Exception { - Cargo cargo = new Cargo(new TrackingId("XYZ"), - new RouteSpecification(SampleLocations.STOCKHOLM, SampleLocations.MELBOURNE, new Date())); - - events.add(new HandlingEvent(cargo, getDate("2007-12-01"), new Date(), HandlingEvent.Type.LOAD, - SampleLocations.STOCKHOLM, voyage)); - events.add(new HandlingEvent(cargo, getDate("2007-12-02"), new Date(), HandlingEvent.Type.UNLOAD, - SampleLocations.HAMBURG, voyage)); - - events.add(new HandlingEvent(cargo, getDate("2007-12-03"), new Date(), HandlingEvent.Type.LOAD, - SampleLocations.HAMBURG, voyage)); - events.add(new HandlingEvent(cargo, getDate("2007-12-04"), new Date(), HandlingEvent.Type.UNLOAD, - SampleLocations.HONGKONG, voyage)); - - events.add(new HandlingEvent(cargo, getDate("2007-12-05"), new Date(), HandlingEvent.Type.LOAD, - SampleLocations.HONGKONG, voyage)); - events.add(new HandlingEvent(cargo, getDate("2007-12-07"), new Date(), HandlingEvent.Type.UNLOAD, - SampleLocations.MELBOURNE, voyage)); - - cargo.deriveDeliveryProgress(new HandlingHistory(events)); - - return cargo; - } - - @Test - public void testIsMisdirected() throws Exception { - // A cargo with no itinerary is not misdirected - Cargo cargo = new Cargo(new TrackingId("TRKID"), - new RouteSpecification(SampleLocations.SHANGHAI, SampleLocations.GOTHENBURG, new Date())); - assertFalse(cargo.getDelivery().isMisdirected()); - - cargo = setUpCargoWithItinerary(SampleLocations.SHANGHAI, SampleLocations.ROTTERDAM, - SampleLocations.GOTHENBURG); - - // A cargo with no handling events is not misdirected - assertFalse(cargo.getDelivery().isMisdirected()); - - Collection handlingEvents = new ArrayList<>(); - - // Happy path - handlingEvents.add(new HandlingEvent(cargo, new Date(10), new Date(20), HandlingEvent.Type.RECEIVE, - SampleLocations.SHANGHAI)); - handlingEvents.add(new HandlingEvent(cargo, new Date(30), new Date(40), HandlingEvent.Type.LOAD, - SampleLocations.SHANGHAI, voyage)); - handlingEvents.add(new HandlingEvent(cargo, new Date(50), new Date(60), HandlingEvent.Type.UNLOAD, - SampleLocations.ROTTERDAM, voyage)); - handlingEvents.add(new HandlingEvent(cargo, new Date(70), new Date(80), HandlingEvent.Type.LOAD, - SampleLocations.ROTTERDAM, voyage)); - handlingEvents.add(new HandlingEvent(cargo, new Date(90), new Date(100), HandlingEvent.Type.UNLOAD, - SampleLocations.GOTHENBURG, voyage)); - handlingEvents.add(new HandlingEvent(cargo, new Date(110), new Date(120), HandlingEvent.Type.CLAIM, - SampleLocations.GOTHENBURG)); - handlingEvents.add(new HandlingEvent(cargo, new Date(130), new Date(140), HandlingEvent.Type.CUSTOMS, - SampleLocations.GOTHENBURG)); - - events.addAll(handlingEvents); - cargo.deriveDeliveryProgress(new HandlingHistory(events)); - assertFalse(cargo.getDelivery().isMisdirected()); - - // Try a couple of failing ones - cargo = setUpCargoWithItinerary(SampleLocations.SHANGHAI, SampleLocations.ROTTERDAM, - SampleLocations.GOTHENBURG); - handlingEvents = new ArrayList<>(); - - handlingEvents.add( - new HandlingEvent(cargo, new Date(), new Date(), HandlingEvent.Type.RECEIVE, SampleLocations.HANGZOU)); - events.addAll(handlingEvents); - cargo.deriveDeliveryProgress(new HandlingHistory(events)); - - assertTrue(cargo.getDelivery().isMisdirected()); - - cargo = setUpCargoWithItinerary(SampleLocations.SHANGHAI, SampleLocations.ROTTERDAM, - SampleLocations.GOTHENBURG); - handlingEvents = new ArrayList<>(); - - handlingEvents.add(new HandlingEvent(cargo, new Date(10), new Date(20), HandlingEvent.Type.RECEIVE, - SampleLocations.SHANGHAI)); - handlingEvents.add(new HandlingEvent(cargo, new Date(30), new Date(40), HandlingEvent.Type.LOAD, - SampleLocations.SHANGHAI, voyage)); - handlingEvents.add(new HandlingEvent(cargo, new Date(50), new Date(60), HandlingEvent.Type.UNLOAD, - SampleLocations.ROTTERDAM, voyage)); - handlingEvents.add(new HandlingEvent(cargo, new Date(70), new Date(80), HandlingEvent.Type.LOAD, - SampleLocations.ROTTERDAM, voyage)); - - events.addAll(handlingEvents); - cargo.deriveDeliveryProgress(new HandlingHistory(events)); - - assertTrue(cargo.getDelivery().isMisdirected()); - - cargo = setUpCargoWithItinerary(SampleLocations.SHANGHAI, SampleLocations.ROTTERDAM, - SampleLocations.GOTHENBURG); - handlingEvents = new ArrayList<>(); - - handlingEvents.add(new HandlingEvent(cargo, new Date(10), new Date(20), HandlingEvent.Type.RECEIVE, - SampleLocations.SHANGHAI)); - handlingEvents.add(new HandlingEvent(cargo, new Date(30), new Date(40), HandlingEvent.Type.LOAD, - SampleLocations.SHANGHAI, voyage)); - handlingEvents.add(new HandlingEvent(cargo, new Date(50), new Date(60), HandlingEvent.Type.UNLOAD, - SampleLocations.ROTTERDAM, voyage)); - handlingEvents.add( - new HandlingEvent(cargo, new Date(), new Date(), HandlingEvent.Type.CLAIM, SampleLocations.ROTTERDAM)); - - events.addAll(handlingEvents); - cargo.deriveDeliveryProgress(new HandlingHistory(events)); - - assertTrue(cargo.getDelivery().isMisdirected()); - } - - private Cargo setUpCargoWithItinerary(Location origin, Location midpoint, Location destination) { - Cargo cargo = new Cargo(new TrackingId("CARGO1"), new RouteSpecification(origin, destination, new Date())); - - Itinerary itinerary = new Itinerary(Arrays.asList(new Leg(voyage, origin, midpoint, new Date(), new Date()), - new Leg(voyage, midpoint, destination, new Date(), new Date()))); - - cargo.assignToRoute(itinerary); - return cargo; - } - - /** - * Parse an ISO 8601 (YYYY-MM-DD) String to Date - * - * @param isoFormat String to parse. - * @return Created date instance. - * @throws ParseException Thrown if parsing fails. - */ - private Date getDate(String isoFormat) throws ParseException { - DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); - return dateFormat.parse(isoFormat); - } + private final List events = new ArrayList<>(); + private final Voyage voyage = + new Voyage.Builder(new VoyageNumber("0123"), SampleLocations.STOCKHOLM) + .addMovement(SampleLocations.HAMBURG, new Date(), new Date()) + .addMovement(SampleLocations.HONGKONG, new Date(), new Date()) + .addMovement(SampleLocations.MELBOURNE, new Date(), new Date()) + .build(); + + @Test + public void testConstruction() { + TrackingId trackingId = new TrackingId("XYZ"); + Date arrivalDeadline = DateUtil.toDate("2009-03-13"); + RouteSpecification routeSpecification = + new RouteSpecification( + SampleLocations.STOCKHOLM, SampleLocations.MELBOURNE, arrivalDeadline); + + Cargo cargo = new Cargo(trackingId, routeSpecification); + + assertEquals(RoutingStatus.NOT_ROUTED, cargo.getDelivery().getRoutingStatus()); + assertEquals(TransportStatus.NOT_RECEIVED, cargo.getDelivery().getTransportStatus()); + Assert.assertEquals(Location.UNKNOWN, cargo.getDelivery().getLastKnownLocation()); + Assert.assertEquals(Voyage.NONE, cargo.getDelivery().getCurrentVoyage()); + } + + @Test + public void testRoutingStatus() { + Cargo cargo = + new Cargo( + new TrackingId("XYZ"), + new RouteSpecification( + SampleLocations.STOCKHOLM, SampleLocations.MELBOURNE, new Date())); + final Itinerary good = new Itinerary(); + Itinerary bad = new Itinerary(); + @SuppressWarnings("serial") + RouteSpecification acceptOnlyGood = + new RouteSpecification( + cargo.getOrigin(), cargo.getRouteSpecification().getDestination(), new Date()) { + + @Override + public boolean isSatisfiedBy(Itinerary itinerary) { + return itinerary == good; + } + }; + + cargo.specifyNewRoute(acceptOnlyGood); + + assertEquals(RoutingStatus.NOT_ROUTED, cargo.getDelivery().getRoutingStatus()); + + cargo.assignToRoute(bad); + assertEquals(RoutingStatus.MISROUTED, cargo.getDelivery().getRoutingStatus()); + + cargo.assignToRoute(good); + assertEquals(RoutingStatus.ROUTED, cargo.getDelivery().getRoutingStatus()); + } + + @Test + public void testLastKnownLocationUnknownWhenNoEvents() { + Cargo cargo = + new Cargo( + new TrackingId("XYZ"), + new RouteSpecification( + SampleLocations.STOCKHOLM, SampleLocations.MELBOURNE, new Date())); + + Assert.assertEquals(Location.UNKNOWN, cargo.getDelivery().getLastKnownLocation()); + } + + @Test + public void testLastKnownLocationReceived() throws Exception { + Cargo cargo = populateCargoReceivedStockholm(); + + Assert.assertEquals(SampleLocations.STOCKHOLM, cargo.getDelivery().getLastKnownLocation()); + } + + @Test + public void testLastKnownLocationClaimed() throws Exception { + Cargo cargo = populateCargoClaimedMelbourne(); + + Assert.assertEquals(SampleLocations.MELBOURNE, cargo.getDelivery().getLastKnownLocation()); + } + + @Test + public void testLastKnownLocationUnloaded() throws Exception { + Cargo cargo = populateCargoOffHongKong(); + + Assert.assertEquals(SampleLocations.HONGKONG, cargo.getDelivery().getLastKnownLocation()); + } + + @Test + public void testLastKnownLocationloaded() throws Exception { + Cargo cargo = populateCargoOnHamburg(); + + Assert.assertEquals(SampleLocations.HAMBURG, cargo.getDelivery().getLastKnownLocation()); + } + + @Test + public void testIsUnloadedAtFinalDestination() { + Cargo cargo = + setUpCargoWithItinerary( + SampleLocations.HANGZOU, SampleLocations.TOKYO, SampleLocations.NEWYORK); + assertFalse(cargo.getDelivery().isUnloadedAtDestination()); + + // Adding an event unrelated to unloading at final destination + events.add( + new HandlingEvent( + cargo, new Date(10), new Date(), HandlingEvent.Type.RECEIVE, SampleLocations.HANGZOU)); + cargo.deriveDeliveryProgress(new HandlingHistory(events)); + assertFalse(cargo.getDelivery().isUnloadedAtDestination()); + + Voyage voyage = + new Voyage.Builder(new VoyageNumber("0123"), SampleLocations.HANGZOU) + .addMovement(SampleLocations.NEWYORK, new Date(), new Date()) + .build(); + + // Adding an unload event, but not at the final destination + events.add( + new HandlingEvent( + cargo, + new Date(20), + new Date(), + HandlingEvent.Type.UNLOAD, + SampleLocations.TOKYO, + voyage)); + cargo.deriveDeliveryProgress(new HandlingHistory(events)); + assertFalse(cargo.getDelivery().isUnloadedAtDestination()); + + // Adding an event in the final destination, but not unload + events.add( + new HandlingEvent( + cargo, new Date(30), new Date(), HandlingEvent.Type.CUSTOMS, SampleLocations.NEWYORK)); + cargo.deriveDeliveryProgress(new HandlingHistory(events)); + assertFalse(cargo.getDelivery().isUnloadedAtDestination()); + + // Finally, cargo is unloaded at final destination + events.add( + new HandlingEvent( + cargo, + new Date(40), + new Date(), + HandlingEvent.Type.UNLOAD, + SampleLocations.NEWYORK, + voyage)); + cargo.deriveDeliveryProgress(new HandlingHistory(events)); + assertTrue(cargo.getDelivery().isUnloadedAtDestination()); + } + + // TODO [TDD] Generate test data some better way + private Cargo populateCargoReceivedStockholm() throws Exception { + Cargo cargo = + new Cargo( + new TrackingId("XYZ"), + new RouteSpecification( + SampleLocations.STOCKHOLM, SampleLocations.MELBOURNE, new Date())); + + HandlingEvent event = + new HandlingEvent( + cargo, + getDate("2007-12-01"), + new Date(), + HandlingEvent.Type.RECEIVE, + SampleLocations.STOCKHOLM); + events.add(event); + cargo.deriveDeliveryProgress(new HandlingHistory(events)); + + return cargo; + } + + private Cargo populateCargoClaimedMelbourne() throws Exception { + Cargo cargo = populateCargoOffMelbourne(); + + events.add( + new HandlingEvent( + cargo, + getDate("2007-12-09"), + new Date(), + HandlingEvent.Type.CLAIM, + SampleLocations.MELBOURNE)); + cargo.deriveDeliveryProgress(new HandlingHistory(events)); + + return cargo; + } + + private Cargo populateCargoOffHongKong() throws Exception { + Cargo cargo = + new Cargo( + new TrackingId("XYZ"), + new RouteSpecification( + SampleLocations.STOCKHOLM, SampleLocations.MELBOURNE, new Date())); + + events.add( + new HandlingEvent( + cargo, + getDate("2007-12-01"), + new Date(), + HandlingEvent.Type.LOAD, + SampleLocations.STOCKHOLM, + voyage)); + events.add( + new HandlingEvent( + cargo, + getDate("2007-12-02"), + new Date(), + HandlingEvent.Type.UNLOAD, + SampleLocations.HAMBURG, + voyage)); + + events.add( + new HandlingEvent( + cargo, + getDate("2007-12-03"), + new Date(), + HandlingEvent.Type.LOAD, + SampleLocations.HAMBURG, + voyage)); + events.add( + new HandlingEvent( + cargo, + getDate("2007-12-04"), + new Date(), + HandlingEvent.Type.UNLOAD, + SampleLocations.HONGKONG, + voyage)); + + cargo.deriveDeliveryProgress(new HandlingHistory(events)); + + return cargo; + } + + private Cargo populateCargoOnHamburg() throws Exception { + Cargo cargo = + new Cargo( + new TrackingId("XYZ"), + new RouteSpecification( + SampleLocations.STOCKHOLM, SampleLocations.MELBOURNE, new Date())); + + events.add( + new HandlingEvent( + cargo, + getDate("2007-12-01"), + new Date(), + HandlingEvent.Type.LOAD, + SampleLocations.STOCKHOLM, + voyage)); + events.add( + new HandlingEvent( + cargo, + getDate("2007-12-02"), + new Date(), + HandlingEvent.Type.UNLOAD, + SampleLocations.HAMBURG, + voyage)); + events.add( + new HandlingEvent( + cargo, + getDate("2007-12-03"), + new Date(), + HandlingEvent.Type.LOAD, + SampleLocations.HAMBURG, + voyage)); + + cargo.deriveDeliveryProgress(new HandlingHistory(events)); + + return cargo; + } + + private Cargo populateCargoOffMelbourne() throws Exception { + Cargo cargo = + new Cargo( + new TrackingId("XYZ"), + new RouteSpecification( + SampleLocations.STOCKHOLM, SampleLocations.MELBOURNE, new Date())); + + events.add( + new HandlingEvent( + cargo, + getDate("2007-12-01"), + new Date(), + HandlingEvent.Type.LOAD, + SampleLocations.STOCKHOLM, + voyage)); + events.add( + new HandlingEvent( + cargo, + getDate("2007-12-02"), + new Date(), + HandlingEvent.Type.UNLOAD, + SampleLocations.HAMBURG, + voyage)); + + events.add( + new HandlingEvent( + cargo, + getDate("2007-12-03"), + new Date(), + HandlingEvent.Type.LOAD, + SampleLocations.HAMBURG, + voyage)); + events.add( + new HandlingEvent( + cargo, + getDate("2007-12-04"), + new Date(), + HandlingEvent.Type.UNLOAD, + SampleLocations.HONGKONG, + voyage)); + + events.add( + new HandlingEvent( + cargo, + getDate("2007-12-05"), + new Date(), + HandlingEvent.Type.LOAD, + SampleLocations.HONGKONG, + voyage)); + events.add( + new HandlingEvent( + cargo, + getDate("2007-12-07"), + new Date(), + HandlingEvent.Type.UNLOAD, + SampleLocations.MELBOURNE, + voyage)); + + cargo.deriveDeliveryProgress(new HandlingHistory(events)); + + return cargo; + } + + @Test + public void testIsMisdirected() throws Exception { + // A cargo with no itinerary is not misdirected + Cargo cargo = + new Cargo( + new TrackingId("TRKID"), + new RouteSpecification( + SampleLocations.SHANGHAI, SampleLocations.GOTHENBURG, new Date())); + assertFalse(cargo.getDelivery().isMisdirected()); + + cargo = + setUpCargoWithItinerary( + SampleLocations.SHANGHAI, SampleLocations.ROTTERDAM, SampleLocations.GOTHENBURG); + + // A cargo with no handling events is not misdirected + assertFalse(cargo.getDelivery().isMisdirected()); + + Collection handlingEvents = new ArrayList<>(); + + // Happy path + handlingEvents.add( + new HandlingEvent( + cargo, + new Date(10), + new Date(20), + HandlingEvent.Type.RECEIVE, + SampleLocations.SHANGHAI)); + handlingEvents.add( + new HandlingEvent( + cargo, + new Date(30), + new Date(40), + HandlingEvent.Type.LOAD, + SampleLocations.SHANGHAI, + voyage)); + handlingEvents.add( + new HandlingEvent( + cargo, + new Date(50), + new Date(60), + HandlingEvent.Type.UNLOAD, + SampleLocations.ROTTERDAM, + voyage)); + handlingEvents.add( + new HandlingEvent( + cargo, + new Date(70), + new Date(80), + HandlingEvent.Type.LOAD, + SampleLocations.ROTTERDAM, + voyage)); + handlingEvents.add( + new HandlingEvent( + cargo, + new Date(90), + new Date(100), + HandlingEvent.Type.UNLOAD, + SampleLocations.GOTHENBURG, + voyage)); + handlingEvents.add( + new HandlingEvent( + cargo, + new Date(110), + new Date(120), + HandlingEvent.Type.CLAIM, + SampleLocations.GOTHENBURG)); + handlingEvents.add( + new HandlingEvent( + cargo, + new Date(130), + new Date(140), + HandlingEvent.Type.CUSTOMS, + SampleLocations.GOTHENBURG)); + + events.addAll(handlingEvents); + cargo.deriveDeliveryProgress(new HandlingHistory(events)); + assertFalse(cargo.getDelivery().isMisdirected()); + + // Try a couple of failing ones + cargo = + setUpCargoWithItinerary( + SampleLocations.SHANGHAI, SampleLocations.ROTTERDAM, SampleLocations.GOTHENBURG); + handlingEvents = new ArrayList<>(); + + handlingEvents.add( + new HandlingEvent( + cargo, new Date(), new Date(), HandlingEvent.Type.RECEIVE, SampleLocations.HANGZOU)); + events.addAll(handlingEvents); + cargo.deriveDeliveryProgress(new HandlingHistory(events)); + + assertTrue(cargo.getDelivery().isMisdirected()); + + cargo = + setUpCargoWithItinerary( + SampleLocations.SHANGHAI, SampleLocations.ROTTERDAM, SampleLocations.GOTHENBURG); + handlingEvents = new ArrayList<>(); + + handlingEvents.add( + new HandlingEvent( + cargo, + new Date(10), + new Date(20), + HandlingEvent.Type.RECEIVE, + SampleLocations.SHANGHAI)); + handlingEvents.add( + new HandlingEvent( + cargo, + new Date(30), + new Date(40), + HandlingEvent.Type.LOAD, + SampleLocations.SHANGHAI, + voyage)); + handlingEvents.add( + new HandlingEvent( + cargo, + new Date(50), + new Date(60), + HandlingEvent.Type.UNLOAD, + SampleLocations.ROTTERDAM, + voyage)); + handlingEvents.add( + new HandlingEvent( + cargo, + new Date(70), + new Date(80), + HandlingEvent.Type.LOAD, + SampleLocations.ROTTERDAM, + voyage)); + + events.addAll(handlingEvents); + cargo.deriveDeliveryProgress(new HandlingHistory(events)); + + assertTrue(cargo.getDelivery().isMisdirected()); + + cargo = + setUpCargoWithItinerary( + SampleLocations.SHANGHAI, SampleLocations.ROTTERDAM, SampleLocations.GOTHENBURG); + handlingEvents = new ArrayList<>(); + + handlingEvents.add( + new HandlingEvent( + cargo, + new Date(10), + new Date(20), + HandlingEvent.Type.RECEIVE, + SampleLocations.SHANGHAI)); + handlingEvents.add( + new HandlingEvent( + cargo, + new Date(30), + new Date(40), + HandlingEvent.Type.LOAD, + SampleLocations.SHANGHAI, + voyage)); + handlingEvents.add( + new HandlingEvent( + cargo, + new Date(50), + new Date(60), + HandlingEvent.Type.UNLOAD, + SampleLocations.ROTTERDAM, + voyage)); + handlingEvents.add( + new HandlingEvent( + cargo, new Date(), new Date(), HandlingEvent.Type.CLAIM, SampleLocations.ROTTERDAM)); + + events.addAll(handlingEvents); + cargo.deriveDeliveryProgress(new HandlingHistory(events)); + + assertTrue(cargo.getDelivery().isMisdirected()); + } + + private Cargo setUpCargoWithItinerary(Location origin, Location midpoint, Location destination) { + Cargo cargo = + new Cargo( + new TrackingId("CARGO1"), new RouteSpecification(origin, destination, new Date())); + + Itinerary itinerary = + new Itinerary( + Arrays.asList( + new Leg(voyage, origin, midpoint, new Date(), new Date()), + new Leg(voyage, midpoint, destination, new Date(), new Date()))); + + cargo.assignToRoute(itinerary); + return cargo; + } + + /** + * Parse an ISO 8601 (YYYY-MM-DD) String to Date + * + * @param isoFormat String to parse. + * @return Created date instance. + * @throws ParseException Thrown if parsing fails. + */ + private Date getDate(String isoFormat) throws ParseException { + DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); + return dateFormat.parse(isoFormat); + } } diff --git a/src/test/java/org/eclipse/cargotracker/domain/model/cargo/ItineraryTest.java b/src/test/java/org/eclipse/cargotracker/domain/model/cargo/ItineraryTest.java index db33017fe..69bda6154 100644 --- a/src/test/java/org/eclipse/cargotracker/domain/model/cargo/ItineraryTest.java +++ b/src/test/java/org/eclipse/cargotracker/domain/model/cargo/ItineraryTest.java @@ -17,93 +17,153 @@ public class ItineraryTest { - private Voyage voyage = new Voyage.Builder(new VoyageNumber("0123"), SampleLocations.SHANGHAI) - .addMovement(SampleLocations.ROTTERDAM, new Date(), new Date()) - .addMovement(SampleLocations.GOTHENBURG, new Date(), new Date()).build(); - private Voyage wrongVoyage = new Voyage.Builder(new VoyageNumber("666"), SampleLocations.NEWYORK) - .addMovement(SampleLocations.STOCKHOLM, new Date(), new Date()) - .addMovement(SampleLocations.HELSINKI, new Date(), new Date()).build(); - - @Test - public void testCargoOnTrack() { - TrackingId trackingId = new TrackingId("CARGO1"); - RouteSpecification routeSpecification = new RouteSpecification(SampleLocations.SHANGHAI, - SampleLocations.GOTHENBURG, new Date()); - Cargo cargo = new Cargo(trackingId, routeSpecification); - - Itinerary itinerary = new Itinerary(Arrays.asList( - new Leg(voyage, SampleLocations.SHANGHAI, SampleLocations.ROTTERDAM, new Date(), new Date()), - new Leg(voyage, SampleLocations.ROTTERDAM, SampleLocations.GOTHENBURG, new Date(), new Date()))); - - // Happy path - HandlingEvent event = new HandlingEvent(cargo, new Date(), new Date(), HandlingEvent.Type.RECEIVE, - SampleLocations.SHANGHAI); - assertTrue(itinerary.isExpected(event)); - - event = new HandlingEvent(cargo, new Date(), new Date(), HandlingEvent.Type.LOAD, SampleLocations.SHANGHAI, - voyage); - assertTrue(itinerary.isExpected(event)); - - event = new HandlingEvent(cargo, new Date(), new Date(), HandlingEvent.Type.UNLOAD, SampleLocations.ROTTERDAM, - voyage); - assertTrue(itinerary.isExpected(event)); - - event = new HandlingEvent(cargo, new Date(), new Date(), HandlingEvent.Type.LOAD, SampleLocations.ROTTERDAM, - voyage); - assertTrue(itinerary.isExpected(event)); - - event = new HandlingEvent(cargo, new Date(), new Date(), HandlingEvent.Type.UNLOAD, SampleLocations.GOTHENBURG, - voyage); - assertTrue(itinerary.isExpected(event)); - - event = new HandlingEvent(cargo, new Date(), new Date(), HandlingEvent.Type.CLAIM, SampleLocations.GOTHENBURG); - assertTrue(itinerary.isExpected(event)); - - // Customs event changes nothing - event = new HandlingEvent(cargo, new Date(), new Date(), HandlingEvent.Type.CUSTOMS, - SampleLocations.GOTHENBURG); - assertTrue(itinerary.isExpected(event)); - - // Received at the wrong location - event = new HandlingEvent(cargo, new Date(), new Date(), HandlingEvent.Type.RECEIVE, SampleLocations.HANGZOU); - assertFalse(itinerary.isExpected(event)); - - // Loaded to onto the wrong ship, correct location - event = new HandlingEvent(cargo, new Date(), new Date(), HandlingEvent.Type.LOAD, SampleLocations.ROTTERDAM, - wrongVoyage); - assertFalse(itinerary.isExpected(event)); - - // Unloaded from the wrong ship in the wrong location - event = new HandlingEvent(cargo, new Date(), new Date(), HandlingEvent.Type.UNLOAD, SampleLocations.HELSINKI, - wrongVoyage); - assertFalse(itinerary.isExpected(event)); - - event = new HandlingEvent(cargo, new Date(), new Date(), HandlingEvent.Type.CLAIM, SampleLocations.ROTTERDAM); - assertFalse(itinerary.isExpected(event)); - } - - @Test - public void testNextExpectedEvent() { - // TODO [TDD] Complete this test. - } - - @Test - public void testCreateItinerary() { - try { - @SuppressWarnings("unused") - Itinerary itinerary = new Itinerary(new ArrayList()); - fail("An empty itinerary is not OK"); - } catch (IllegalArgumentException iae) { - // Expected - } - - try { - List legs = null; - @SuppressWarnings("unused") - Itinerary itinerary = new Itinerary(legs); - fail("Null itinerary is not OK"); - } catch (NullPointerException npe) { - // Expected - } - } + private Voyage voyage = + new Voyage.Builder(new VoyageNumber("0123"), SampleLocations.SHANGHAI) + .addMovement(SampleLocations.ROTTERDAM, new Date(), new Date()) + .addMovement(SampleLocations.GOTHENBURG, new Date(), new Date()) + .build(); + private Voyage wrongVoyage = + new Voyage.Builder(new VoyageNumber("666"), SampleLocations.NEWYORK) + .addMovement(SampleLocations.STOCKHOLM, new Date(), new Date()) + .addMovement(SampleLocations.HELSINKI, new Date(), new Date()) + .build(); + + @Test + public void testCargoOnTrack() { + TrackingId trackingId = new TrackingId("CARGO1"); + RouteSpecification routeSpecification = + new RouteSpecification(SampleLocations.SHANGHAI, SampleLocations.GOTHENBURG, new Date()); + Cargo cargo = new Cargo(trackingId, routeSpecification); + + Itinerary itinerary = + new Itinerary( + Arrays.asList( + new Leg( + voyage, + SampleLocations.SHANGHAI, + SampleLocations.ROTTERDAM, + new Date(), + new Date()), + new Leg( + voyage, + SampleLocations.ROTTERDAM, + SampleLocations.GOTHENBURG, + new Date(), + new Date()))); + + // Happy path + HandlingEvent event = + new HandlingEvent( + cargo, new Date(), new Date(), HandlingEvent.Type.RECEIVE, SampleLocations.SHANGHAI); + assertTrue(itinerary.isExpected(event)); + + event = + new HandlingEvent( + cargo, + new Date(), + new Date(), + HandlingEvent.Type.LOAD, + SampleLocations.SHANGHAI, + voyage); + assertTrue(itinerary.isExpected(event)); + + event = + new HandlingEvent( + cargo, + new Date(), + new Date(), + HandlingEvent.Type.UNLOAD, + SampleLocations.ROTTERDAM, + voyage); + assertTrue(itinerary.isExpected(event)); + + event = + new HandlingEvent( + cargo, + new Date(), + new Date(), + HandlingEvent.Type.LOAD, + SampleLocations.ROTTERDAM, + voyage); + assertTrue(itinerary.isExpected(event)); + + event = + new HandlingEvent( + cargo, + new Date(), + new Date(), + HandlingEvent.Type.UNLOAD, + SampleLocations.GOTHENBURG, + voyage); + assertTrue(itinerary.isExpected(event)); + + event = + new HandlingEvent( + cargo, new Date(), new Date(), HandlingEvent.Type.CLAIM, SampleLocations.GOTHENBURG); + assertTrue(itinerary.isExpected(event)); + + // Customs event changes nothing + event = + new HandlingEvent( + cargo, new Date(), new Date(), HandlingEvent.Type.CUSTOMS, SampleLocations.GOTHENBURG); + assertTrue(itinerary.isExpected(event)); + + // Received at the wrong location + event = + new HandlingEvent( + cargo, new Date(), new Date(), HandlingEvent.Type.RECEIVE, SampleLocations.HANGZOU); + assertFalse(itinerary.isExpected(event)); + + // Loaded to onto the wrong ship, correct location + event = + new HandlingEvent( + cargo, + new Date(), + new Date(), + HandlingEvent.Type.LOAD, + SampleLocations.ROTTERDAM, + wrongVoyage); + assertFalse(itinerary.isExpected(event)); + + // Unloaded from the wrong ship in the wrong location + event = + new HandlingEvent( + cargo, + new Date(), + new Date(), + HandlingEvent.Type.UNLOAD, + SampleLocations.HELSINKI, + wrongVoyage); + assertFalse(itinerary.isExpected(event)); + + event = + new HandlingEvent( + cargo, new Date(), new Date(), HandlingEvent.Type.CLAIM, SampleLocations.ROTTERDAM); + assertFalse(itinerary.isExpected(event)); + } + + @Test + public void testNextExpectedEvent() { + // TODO [TDD] Complete this test. + } + + @Test + public void testCreateItinerary() { + try { + @SuppressWarnings("unused") + Itinerary itinerary = new Itinerary(new ArrayList()); + fail("An empty itinerary is not OK"); + } catch (IllegalArgumentException iae) { + // Expected + } + + try { + List legs = null; + @SuppressWarnings("unused") + Itinerary itinerary = new Itinerary(legs); + fail("Null itinerary is not OK"); + } catch (NullPointerException npe) { + // Expected + } + } } diff --git a/src/test/java/org/eclipse/cargotracker/domain/model/cargo/RouteSpecificationTest.java b/src/test/java/org/eclipse/cargotracker/domain/model/cargo/RouteSpecificationTest.java index 2be3d15fc..ff3e26394 100644 --- a/src/test/java/org/eclipse/cargotracker/domain/model/cargo/RouteSpecificationTest.java +++ b/src/test/java/org/eclipse/cargotracker/domain/model/cargo/RouteSpecificationTest.java @@ -14,49 +14,73 @@ // TODO [Jakarta EE 8] Move to the Java Date-Time API for date manipulation. Avoid hard-coded dates. public class RouteSpecificationTest { - Voyage hongKongTokyoNewYork = new Voyage.Builder(new VoyageNumber("V001"), SampleLocations.HONGKONG) - .addMovement(SampleLocations.TOKYO, DateUtil.toDate("2009-02-01"), DateUtil.toDate("2009-02-05")) - .addMovement(SampleLocations.NEWYORK, DateUtil.toDate("2009-02-06"), DateUtil.toDate("2009-02-10")) - .addMovement(SampleLocations.HONGKONG, DateUtil.toDate("2009-02-11"), DateUtil.toDate("2009-02-14")) - .build(); - Voyage dallasNewYorkChicago = new Voyage.Builder(new VoyageNumber("V002"), SampleLocations.DALLAS) - .addMovement(SampleLocations.NEWYORK, DateUtil.toDate("2009-02-06"), DateUtil.toDate("2009-02-07")) - .addMovement(SampleLocations.CHICAGO, DateUtil.toDate("2009-02-12"), DateUtil.toDate("2009-02-20")).build(); - Itinerary itinerary = new Itinerary(Arrays.asList( - new Leg(hongKongTokyoNewYork, SampleLocations.HONGKONG, SampleLocations.NEWYORK, - DateUtil.toDate("2009-02-01"), DateUtil.toDate("2009-02-10")), - new Leg(dallasNewYorkChicago, SampleLocations.NEWYORK, SampleLocations.CHICAGO, - DateUtil.toDate("2009-02-12"), DateUtil.toDate("2009-02-20")))); - - @Test - public void testIsSatisfiedBySuccess() { - RouteSpecification routeSpecification = new RouteSpecification(SampleLocations.HONGKONG, - SampleLocations.CHICAGO, DateUtil.toDate("2009-03-01")); - - assertTrue(routeSpecification.isSatisfiedBy(itinerary)); - } - - @Test - public void testIsNotSatisfiedByWrongOrigin() { - RouteSpecification routeSpecification = new RouteSpecification(SampleLocations.HANGZOU, SampleLocations.CHICAGO, - DateUtil.toDate("2009-03-01")); - - assertFalse(routeSpecification.isSatisfiedBy(itinerary)); - } - - @Test - public void testIsNotSatisfiedByWrongDestination() { - RouteSpecification routeSpecification = new RouteSpecification(SampleLocations.HONGKONG, SampleLocations.DALLAS, - DateUtil.toDate("2009-03-01")); - - assertFalse(routeSpecification.isSatisfiedBy(itinerary)); - } - - @Test - public void testIsNotSatisfiedByMissedDeadline() { - RouteSpecification routeSpecification = new RouteSpecification(SampleLocations.HONGKONG, - SampleLocations.CHICAGO, DateUtil.toDate("2009-02-15")); - - assertFalse(routeSpecification.isSatisfiedBy(itinerary)); - } + Voyage hongKongTokyoNewYork = + new Voyage.Builder(new VoyageNumber("V001"), SampleLocations.HONGKONG) + .addMovement( + SampleLocations.TOKYO, DateUtil.toDate("2009-02-01"), DateUtil.toDate("2009-02-05")) + .addMovement( + SampleLocations.NEWYORK, DateUtil.toDate("2009-02-06"), DateUtil.toDate("2009-02-10")) + .addMovement( + SampleLocations.HONGKONG, + DateUtil.toDate("2009-02-11"), + DateUtil.toDate("2009-02-14")) + .build(); + Voyage dallasNewYorkChicago = + new Voyage.Builder(new VoyageNumber("V002"), SampleLocations.DALLAS) + .addMovement( + SampleLocations.NEWYORK, DateUtil.toDate("2009-02-06"), DateUtil.toDate("2009-02-07")) + .addMovement( + SampleLocations.CHICAGO, DateUtil.toDate("2009-02-12"), DateUtil.toDate("2009-02-20")) + .build(); + Itinerary itinerary = + new Itinerary( + Arrays.asList( + new Leg( + hongKongTokyoNewYork, + SampleLocations.HONGKONG, + SampleLocations.NEWYORK, + DateUtil.toDate("2009-02-01"), + DateUtil.toDate("2009-02-10")), + new Leg( + dallasNewYorkChicago, + SampleLocations.NEWYORK, + SampleLocations.CHICAGO, + DateUtil.toDate("2009-02-12"), + DateUtil.toDate("2009-02-20")))); + + @Test + public void testIsSatisfiedBySuccess() { + RouteSpecification routeSpecification = + new RouteSpecification( + SampleLocations.HONGKONG, SampleLocations.CHICAGO, DateUtil.toDate("2009-03-01")); + + assertTrue(routeSpecification.isSatisfiedBy(itinerary)); + } + + @Test + public void testIsNotSatisfiedByWrongOrigin() { + RouteSpecification routeSpecification = + new RouteSpecification( + SampleLocations.HANGZOU, SampleLocations.CHICAGO, DateUtil.toDate("2009-03-01")); + + assertFalse(routeSpecification.isSatisfiedBy(itinerary)); + } + + @Test + public void testIsNotSatisfiedByWrongDestination() { + RouteSpecification routeSpecification = + new RouteSpecification( + SampleLocations.HONGKONG, SampleLocations.DALLAS, DateUtil.toDate("2009-03-01")); + + assertFalse(routeSpecification.isSatisfiedBy(itinerary)); + } + + @Test + public void testIsNotSatisfiedByMissedDeadline() { + RouteSpecification routeSpecification = + new RouteSpecification( + SampleLocations.HONGKONG, SampleLocations.CHICAGO, DateUtil.toDate("2009-02-15")); + + assertFalse(routeSpecification.isSatisfiedBy(itinerary)); + } } diff --git a/src/test/java/org/eclipse/cargotracker/domain/model/handling/HandlingEventTest.java b/src/test/java/org/eclipse/cargotracker/domain/model/handling/HandlingEventTest.java index aa8b1f6c6..b24e8d4b6 100644 --- a/src/test/java/org/eclipse/cargotracker/domain/model/handling/HandlingEventTest.java +++ b/src/test/java/org/eclipse/cargotracker/domain/model/handling/HandlingEventTest.java @@ -15,77 +15,107 @@ public class HandlingEventTest { - private final TrackingId trackingId = new TrackingId("XYZ"); - private final RouteSpecification routeSpecification = new RouteSpecification(SampleLocations.HONGKONG, - SampleLocations.NEWYORK, new Date()); - private final Cargo cargo = new Cargo(trackingId, routeSpecification); - - @Test - public void testNewWithCarrierMovement() { - HandlingEvent event1 = new HandlingEvent(cargo, new Date(), new Date(), HandlingEvent.Type.LOAD, - SampleLocations.HONGKONG, SampleVoyages.CM003); - assertEquals(SampleLocations.HONGKONG, event1.getLocation()); - - HandlingEvent event2 = new HandlingEvent(cargo, new Date(), new Date(), HandlingEvent.Type.UNLOAD, - SampleLocations.NEWYORK, SampleVoyages.CM003); - assertEquals(SampleLocations.NEWYORK, event2.getLocation()); - - // These event types prohibit a carrier movement association - for (HandlingEvent.Type type : Arrays.asList(HandlingEvent.Type.CLAIM, HandlingEvent.Type.RECEIVE, - HandlingEvent.Type.CUSTOMS)) { - try { - new HandlingEvent(cargo, new Date(), new Date(), type, SampleLocations.HONGKONG, SampleVoyages.CM003); - fail("Handling event type " + type + " prohibits carrier movement"); - } catch (IllegalArgumentException expected) { - } - } - - // These event types requires a carrier movement association - for (HandlingEvent.Type type : Arrays.asList(HandlingEvent.Type.LOAD, HandlingEvent.Type.UNLOAD)) { - try { - new HandlingEvent(cargo, new Date(), new Date(), type, SampleLocations.HONGKONG, null); - fail("Handling event type " + type + " requires carrier movement"); - } catch (NullPointerException expected) { - } - } - } - - @Test - public void testNewWithLocation() { - HandlingEvent event1 = new HandlingEvent(cargo, new Date(), new Date(), HandlingEvent.Type.CLAIM, - SampleLocations.HELSINKI); - assertEquals(SampleLocations.HELSINKI, event1.getLocation()); - } - - @Test - public void testCurrentLocationLoadEvent() throws Exception { - HandlingEvent event = new HandlingEvent(cargo, new Date(), new Date(), HandlingEvent.Type.LOAD, - SampleLocations.CHICAGO, SampleVoyages.CM004); - - assertEquals(SampleLocations.CHICAGO, event.getLocation()); - } - - @Test - public void testCurrentLocationUnloadEvent() throws Exception { - HandlingEvent ev = new HandlingEvent(cargo, new Date(), new Date(), HandlingEvent.Type.UNLOAD, - SampleLocations.HAMBURG, SampleVoyages.CM004); - - assertEquals(SampleLocations.HAMBURG, ev.getLocation()); - } - - @Test - public void testCurrentLocationReceivedEvent() throws Exception { - HandlingEvent event = new HandlingEvent(cargo, new Date(), new Date(), HandlingEvent.Type.RECEIVE, - SampleLocations.CHICAGO); - - assertEquals(SampleLocations.CHICAGO, event.getLocation()); - } - - @Test - public void testCurrentLocationClaimedEvent() throws Exception { - HandlingEvent event = new HandlingEvent(cargo, new Date(), new Date(), HandlingEvent.Type.CLAIM, - SampleLocations.CHICAGO); - - assertEquals(SampleLocations.CHICAGO, event.getLocation()); - } + private final TrackingId trackingId = new TrackingId("XYZ"); + private final RouteSpecification routeSpecification = + new RouteSpecification(SampleLocations.HONGKONG, SampleLocations.NEWYORK, new Date()); + private final Cargo cargo = new Cargo(trackingId, routeSpecification); + + @Test + public void testNewWithCarrierMovement() { + HandlingEvent event1 = + new HandlingEvent( + cargo, + new Date(), + new Date(), + HandlingEvent.Type.LOAD, + SampleLocations.HONGKONG, + SampleVoyages.CM003); + assertEquals(SampleLocations.HONGKONG, event1.getLocation()); + + HandlingEvent event2 = + new HandlingEvent( + cargo, + new Date(), + new Date(), + HandlingEvent.Type.UNLOAD, + SampleLocations.NEWYORK, + SampleVoyages.CM003); + assertEquals(SampleLocations.NEWYORK, event2.getLocation()); + + // These event types prohibit a carrier movement association + for (HandlingEvent.Type type : + Arrays.asList( + HandlingEvent.Type.CLAIM, HandlingEvent.Type.RECEIVE, HandlingEvent.Type.CUSTOMS)) { + try { + new HandlingEvent( + cargo, new Date(), new Date(), type, SampleLocations.HONGKONG, SampleVoyages.CM003); + fail("Handling event type " + type + " prohibits carrier movement"); + } catch (IllegalArgumentException expected) { + } + } + + // These event types requires a carrier movement association + for (HandlingEvent.Type type : + Arrays.asList(HandlingEvent.Type.LOAD, HandlingEvent.Type.UNLOAD)) { + try { + new HandlingEvent(cargo, new Date(), new Date(), type, SampleLocations.HONGKONG, null); + fail("Handling event type " + type + " requires carrier movement"); + } catch (NullPointerException expected) { + } + } + } + + @Test + public void testNewWithLocation() { + HandlingEvent event1 = + new HandlingEvent( + cargo, new Date(), new Date(), HandlingEvent.Type.CLAIM, SampleLocations.HELSINKI); + assertEquals(SampleLocations.HELSINKI, event1.getLocation()); + } + + @Test + public void testCurrentLocationLoadEvent() throws Exception { + HandlingEvent event = + new HandlingEvent( + cargo, + new Date(), + new Date(), + HandlingEvent.Type.LOAD, + SampleLocations.CHICAGO, + SampleVoyages.CM004); + + assertEquals(SampleLocations.CHICAGO, event.getLocation()); + } + + @Test + public void testCurrentLocationUnloadEvent() throws Exception { + HandlingEvent ev = + new HandlingEvent( + cargo, + new Date(), + new Date(), + HandlingEvent.Type.UNLOAD, + SampleLocations.HAMBURG, + SampleVoyages.CM004); + + assertEquals(SampleLocations.HAMBURG, ev.getLocation()); + } + + @Test + public void testCurrentLocationReceivedEvent() throws Exception { + HandlingEvent event = + new HandlingEvent( + cargo, new Date(), new Date(), HandlingEvent.Type.RECEIVE, SampleLocations.CHICAGO); + + assertEquals(SampleLocations.CHICAGO, event.getLocation()); + } + + @Test + public void testCurrentLocationClaimedEvent() throws Exception { + HandlingEvent event = + new HandlingEvent( + cargo, new Date(), new Date(), HandlingEvent.Type.CLAIM, SampleLocations.CHICAGO); + + assertEquals(SampleLocations.CHICAGO, event.getLocation()); + } } diff --git a/src/test/java/org/eclipse/cargotracker/domain/model/handling/HandlingHistoryTest.java b/src/test/java/org/eclipse/cargotracker/domain/model/handling/HandlingHistoryTest.java index 697b8f4e1..ed5c464f5 100644 --- a/src/test/java/org/eclipse/cargotracker/domain/model/handling/HandlingHistoryTest.java +++ b/src/test/java/org/eclipse/cargotracker/domain/model/handling/HandlingHistoryTest.java @@ -14,29 +14,54 @@ import org.eclipse.cargotracker.domain.model.voyage.VoyageNumber; import org.junit.Test; -//TODO [Jakarta EE 8] Move to the Java Date-Time API for date manipulation. Avoid hard-coded dates. +// TODO [Jakarta EE 8] Move to the Java Date-Time API for date manipulation. Avoid hard-coded dates. public class HandlingHistoryTest { - Cargo cargo = new Cargo(new TrackingId("ABC"), - new RouteSpecification(SampleLocations.SHANGHAI, SampleLocations.DALLAS, DateUtil.toDate("2009-04-01"))); - Voyage voyage = new Voyage.Builder(new VoyageNumber("X25"), SampleLocations.HONGKONG) - .addMovement(SampleLocations.SHANGHAI, new Date(), new Date()) - .addMovement(SampleLocations.DALLAS, new Date(), new Date()).build(); - HandlingEvent event1 = new HandlingEvent(cargo, DateUtil.toDate("2009-03-05"), new Date(100), - HandlingEvent.Type.LOAD, SampleLocations.SHANGHAI, voyage); - HandlingEvent event1duplicate = new HandlingEvent(cargo, DateUtil.toDate("2009-03-05"), new Date(200), - HandlingEvent.Type.LOAD, SampleLocations.SHANGHAI, voyage); - HandlingEvent event2 = new HandlingEvent(cargo, DateUtil.toDate("2009-03-10"), new Date(150), - HandlingEvent.Type.UNLOAD, SampleLocations.DALLAS, voyage); - HandlingHistory handlingHistory = new HandlingHistory(Arrays.asList(event2, event1, event1duplicate)); + Cargo cargo = + new Cargo( + new TrackingId("ABC"), + new RouteSpecification( + SampleLocations.SHANGHAI, SampleLocations.DALLAS, DateUtil.toDate("2009-04-01"))); + Voyage voyage = + new Voyage.Builder(new VoyageNumber("X25"), SampleLocations.HONGKONG) + .addMovement(SampleLocations.SHANGHAI, new Date(), new Date()) + .addMovement(SampleLocations.DALLAS, new Date(), new Date()) + .build(); + HandlingEvent event1 = + new HandlingEvent( + cargo, + DateUtil.toDate("2009-03-05"), + new Date(100), + HandlingEvent.Type.LOAD, + SampleLocations.SHANGHAI, + voyage); + HandlingEvent event1duplicate = + new HandlingEvent( + cargo, + DateUtil.toDate("2009-03-05"), + new Date(200), + HandlingEvent.Type.LOAD, + SampleLocations.SHANGHAI, + voyage); + HandlingEvent event2 = + new HandlingEvent( + cargo, + DateUtil.toDate("2009-03-10"), + new Date(150), + HandlingEvent.Type.UNLOAD, + SampleLocations.DALLAS, + voyage); + HandlingHistory handlingHistory = + new HandlingHistory(Arrays.asList(event2, event1, event1duplicate)); - @Test - public void testDistinctEventsByCompletionTime() { - assertEquals(Arrays.asList(event1, event2), handlingHistory.getDistinctEventsByCompletionTime()); - } + @Test + public void testDistinctEventsByCompletionTime() { + assertEquals( + Arrays.asList(event1, event2), handlingHistory.getDistinctEventsByCompletionTime()); + } - @Test - public void testMostRecentlyCompletedEvent() { - assertEquals(event2, handlingHistory.getMostRecentlyCompletedEvent()); - } + @Test + public void testMostRecentlyCompletedEvent() { + assertEquals(event2, handlingHistory.getMostRecentlyCompletedEvent()); + } } diff --git a/src/test/java/org/eclipse/cargotracker/infrastructure/routing/ExternalRoutingServiceTest.java b/src/test/java/org/eclipse/cargotracker/infrastructure/routing/ExternalRoutingServiceTest.java index ff7028cfe..55be82374 100644 --- a/src/test/java/org/eclipse/cargotracker/infrastructure/routing/ExternalRoutingServiceTest.java +++ b/src/test/java/org/eclipse/cargotracker/infrastructure/routing/ExternalRoutingServiceTest.java @@ -18,58 +18,64 @@ public class ExternalRoutingServiceTest { - private ExternalRoutingService externalRoutingService; -// private VoyageRepository voyageRepository; + private ExternalRoutingService externalRoutingService; + // private VoyageRepository voyageRepository; - // protected void setUp() throws Exception { -// externalRoutingService = new ExternalRoutingService(); -// LocationRepository locationRepository = new LocationRepositoryInMem(); -// externalRoutingService.setLocationRepository(locationRepository); -// -// voyageRepository = createMock(VoyageRepository.class); -// externalRoutingService.setVoyageRepository(voyageRepository); -// -// GraphTraversalService graphTraversalService = new GraphTraversalServiceImpl(new GraphDAO() { -// public List listLocations() { -// return Arrays.asList(SampleLocations.TOKYO.getUnLocode().getIdString(), SampleLocations.STOCKHOLM.getUnLocode().getIdString(), SampleLocations.GOTHENBURG.getUnLocode().getIdString()); -// } -// -// public void storeCarrierMovementId(String cmId, String from, String to) { -// } -// }); -// externalRoutingService.setGraphTraversalService(graphTraversalService); -// } - // TODO [TDD] this test belongs in com.pathfinder - public void testCalculatePossibleRoutes() { - TrackingId trackingId = new TrackingId("ABC"); - RouteSpecification routeSpecification = new RouteSpecification(SampleLocations.HONGKONG, SampleLocations.HELSINKI, new Date()); - Cargo cargo = new Cargo(trackingId, routeSpecification); + // protected void setUp() throws Exception { + // externalRoutingService = new ExternalRoutingService(); + // LocationRepository locationRepository = new LocationRepositoryInMem(); + // externalRoutingService.setLocationRepository(locationRepository); + // + // voyageRepository = createMock(VoyageRepository.class); + // externalRoutingService.setVoyageRepository(voyageRepository); + // + // GraphTraversalService graphTraversalService = new GraphTraversalServiceImpl(new + // GraphDAO() { + // public List listLocations() { + // return Arrays.asList(SampleLocations.TOKYO.getUnLocode().getIdString(), + // SampleLocations.STOCKHOLM.getUnLocode().getIdString(), + // SampleLocations.GOTHENBURG.getUnLocode().getIdString()); + // } + // + // public void storeCarrierMovementId(String cmId, String from, String to) { + // } + // }); + // externalRoutingService.setGraphTraversalService(graphTraversalService); + // } + // TODO [TDD] this test belongs in com.pathfinder + public void testCalculatePossibleRoutes() { + TrackingId trackingId = new TrackingId("ABC"); + RouteSpecification routeSpecification = + new RouteSpecification(SampleLocations.HONGKONG, SampleLocations.HELSINKI, new Date()); + Cargo cargo = new Cargo(trackingId, routeSpecification); -// expect(voyageRepository.find(isA(VoyageNumber.class))).andStubReturn(SampleVoyages.CM002); -// -// replay(voyageRepository); + // + // expect(voyageRepository.find(isA(VoyageNumber.class))).andStubReturn(SampleVoyages.CM002); + // + // replay(voyageRepository); - List candidates = externalRoutingService.fetchRoutesForSpecification(routeSpecification); - assertNotNull(candidates); + List candidates = + externalRoutingService.fetchRoutesForSpecification(routeSpecification); + assertNotNull(candidates); - for (Itinerary itinerary : candidates) { - List legs = itinerary.getLegs(); - assertNotNull(legs); - assertFalse(legs.isEmpty()); + for (Itinerary itinerary : candidates) { + List legs = itinerary.getLegs(); + assertNotNull(legs); + assertFalse(legs.isEmpty()); - // Cargo origin and start of first leg should match - Assert.assertEquals(cargo.getOrigin(), legs.get(0).getLoadLocation()); + // Cargo origin and start of first leg should match + Assert.assertEquals(cargo.getOrigin(), legs.get(0).getLoadLocation()); - // Cargo final destination and last leg stop should match - Location lastLegStop = legs.get(legs.size() - 1).getUnloadLocation(); - assertEquals(cargo.getRouteSpecification().getDestination(), lastLegStop); + // Cargo final destination and last leg stop should match + Location lastLegStop = legs.get(legs.size() - 1).getUnloadLocation(); + assertEquals(cargo.getRouteSpecification().getDestination(), lastLegStop); - // Assert that all legs are connected - for (int i = 0; i < legs.size() - 1; i++) { - assertEquals(legs.get(i).getUnloadLocation(), legs.get(i + 1).getLoadLocation()); - } - } - -// verify(voyageRepository); + // Assert that all legs are connected + for (int i = 0; i < legs.size() - 1; i++) { + assertEquals(legs.get(i).getUnloadLocation(), legs.get(i + 1).getLoadLocation()); + } } + + // verify(voyageRepository); + } } diff --git a/src/test/java/org/eclipse/cargotracker/scenario/CargoLifecycleScenarioTest.java b/src/test/java/org/eclipse/cargotracker/scenario/CargoLifecycleScenarioTest.java index bb2e76f41..10434cdf6 100644 --- a/src/test/java/org/eclipse/cargotracker/scenario/CargoLifecycleScenarioTest.java +++ b/src/test/java/org/eclipse/cargotracker/scenario/CargoLifecycleScenarioTest.java @@ -39,293 +39,372 @@ public class CargoLifecycleScenarioTest { - /** - * Repository implementations are part of the infrastructure layer, which in - * this test is stubbed out by in-memory replacements. - */ - HandlingEventRepository handlingEventRepository; - CargoRepository cargoRepository; - LocationRepository locationRepository; - VoyageRepository voyageRepository; - /** - * This interface is part of the application layer, and defines a number of - * events that occur during aplication execution. It is used for message-driving - * and is implemented using JMS. - *

- * In this test it is stubbed with synchronous calls. - */ - ApplicationEvents applicationEvents; - /** - * These three components all belong to the application layer, and map against - * use cases of the application. The "real" implementations are used in this - * lifecycle test, but wired with stubbed infrastructure. - */ - BookingService bookingService; - HandlingEventService handlingEventService; - CargoInspectionService cargoInspectionService; - /** - * This factory is part of the handling aggregate and belongs to the domain - * layer. Similar to the application layer components, the "real" implementation - * is used here too, wired with stubbed infrastructure. - */ - HandlingEventFactory handlingEventFactory; - /** - * This is a domain service interface, whose implementation is part of the - * infrastructure layer (remote call to external system). - *

- * It is stubbed in this test. - */ - RoutingService routingService; - - public void testCargoFromHongkongToStockholm() throws Exception { - /* - * Test setup: A cargo should be shipped from Hongkong to - * SampleLocations.STOCKHOLM, and it should arrive in no more than two weeks. - */ - Location origin = SampleLocations.HONGKONG; - Location destination = SampleLocations.STOCKHOLM; - Date arrivalDeadline = DateUtil.toDate("2009-03-18"); - - /* - * Use case 1: booking - * - * A new cargo is booked, and the unique tracking id is assigned to the cargo. - */ - TrackingId trackingId = bookingService.bookNewCargo(origin.getUnLocode(), destination.getUnLocode(), - arrivalDeadline); - - /* - * The tracking id can be used to lookup the cargo in the repository. - * - * Important: The cargo, and thus the domain model, is responsible for - * determining the status of the cargo, whether it is on the right track or not - * and so on. This is core domain logic. - * - * Tracking the cargo basically amounts to presenting information extracted from - * the cargo aggregate in a suitable way. - */ - Cargo cargo = cargoRepository.find(trackingId); - org.junit.Assert.assertNotNull(cargo); - Assert.assertEquals(TransportStatus.NOT_RECEIVED, cargo.getDelivery().getTransportStatus()); - Assert.assertEquals(RoutingStatus.NOT_ROUTED, cargo.getDelivery().getRoutingStatus()); - assertFalse(cargo.getDelivery().isMisdirected()); - assertNull(cargo.getDelivery().getEstimatedTimeOfArrival()); - assertNull(cargo.getDelivery().getNextExpectedActivity()); - - /* - * Use case 2: routing - * - * A number of possible routes for this cargo is requested and may be presented - * to the customer in some way for him/her to choose from. Selection could be - * affected by things like price and time of delivery, but this test simply uses - * an arbitrary selection to mimic that process. - * - * The cargo is then assigned to the selected route, described by an itinerary. - */ - List itineraries = bookingService.requestPossibleRoutesForCargo(trackingId); - Itinerary itinerary = selectPreferedItinerary(itineraries); - cargo.assignToRoute(itinerary); - - assertEquals(TransportStatus.NOT_RECEIVED, cargo.getDelivery().getTransportStatus()); - assertEquals(RoutingStatus.ROUTED, cargo.getDelivery().getRoutingStatus()); - org.junit.Assert.assertNotNull(cargo.getDelivery().getEstimatedTimeOfArrival()); - assertEquals(new HandlingActivity(HandlingEvent.Type.RECEIVE, SampleLocations.HONGKONG), - cargo.getDelivery().getNextExpectedActivity()); - - /* - * Use case 3: handling - * - * A handling event registration attempt will be formed from parsing the data - * coming in as a handling report either via the web service interface or as an - * uploaded CSV file. - * - * The handling event factory tries to create a HandlingEvent from the attempt, - * and if the factory decides that this is a plausible handling event, it is - * stored. If the attempt is invalid, for example if no cargo exists for the - * specfied tracking id, the attempt is rejected. - * - * Handling begins: cargo is received in Hongkong. - */ - handlingEventService.registerHandlingEvent(DateUtil.toDate("2009-03-01"), trackingId, null, - SampleLocations.HONGKONG.getUnLocode(), HandlingEvent.Type.RECEIVE); - - assertEquals(TransportStatus.IN_PORT, cargo.getDelivery().getTransportStatus()); - assertEquals(SampleLocations.HONGKONG, cargo.getDelivery().getLastKnownLocation()); - - // Next event: Load onto voyage SampleVoyages.CM003 in Hongkong - handlingEventService.registerHandlingEvent(DateUtil.toDate("2009-03-03"), trackingId, - SampleVoyages.v100.getVoyageNumber(), SampleLocations.HONGKONG.getUnLocode(), HandlingEvent.Type.LOAD); - - // Check current state - should be ok - assertEquals(SampleVoyages.v100, cargo.getDelivery().getCurrentVoyage()); - assertEquals(SampleLocations.HONGKONG, cargo.getDelivery().getLastKnownLocation()); - assertEquals(TransportStatus.ONBOARD_CARRIER, cargo.getDelivery().getTransportStatus()); - assertFalse(cargo.getDelivery().isMisdirected()); - assertEquals(new HandlingActivity(HandlingEvent.Type.UNLOAD, SampleLocations.NEWYORK, SampleVoyages.v100), - cargo.getDelivery().getNextExpectedActivity()); - - /* - * Here's an attempt to register a handling event that's not valid because there - * is no voyage with the specified voyage number, and there's no location with - * the specified UN Locode either. - * - * This attempt will be rejected and will not affect the cargo delivery in any - * way. - */ - VoyageNumber noSuchVoyageNumber = new VoyageNumber("XX000"); - UnLocode noSuchUnLocode = new UnLocode("ZZZZZ"); - try { - handlingEventService.registerHandlingEvent(DateUtil.toDate("2009-03-05"), trackingId, noSuchVoyageNumber, - noSuchUnLocode, HandlingEvent.Type.LOAD); - org.junit.Assert.fail("Should not be able to register a handling event with invalid location and voyage"); - } catch (CannotCreateHandlingEventException expected) { - } - - // Cargo is now (incorrectly) unloaded in Tokyo - handlingEventService.registerHandlingEvent(DateUtil.toDate("2009-03-05"), trackingId, - SampleVoyages.v100.getVoyageNumber(), SampleLocations.TOKYO.getUnLocode(), HandlingEvent.Type.UNLOAD); - - // Check current state - cargo is misdirected! - Assert.assertEquals(Voyage.NONE, cargo.getDelivery().getCurrentVoyage()); - assertEquals(SampleLocations.TOKYO, cargo.getDelivery().getLastKnownLocation()); - assertEquals(TransportStatus.IN_PORT, cargo.getDelivery().getTransportStatus()); - org.junit.Assert.assertTrue(cargo.getDelivery().isMisdirected()); - assertNull(cargo.getDelivery().getNextExpectedActivity()); - - // -- Cargo needs to be rerouted -- - // TODO [TDD] cleaner reroute from "earliest location from where the new route - // originates" - // Specify a new route, this time from Tokyo (where it was incorrectly unloaded) - // to SampleLocations.STOCKHOLM - RouteSpecification fromTokyo = new RouteSpecification(SampleLocations.TOKYO, SampleLocations.STOCKHOLM, - arrivalDeadline); - cargo.specifyNewRoute(fromTokyo); - - // The old itinerary does not satisfy the new specification - assertEquals(RoutingStatus.MISROUTED, cargo.getDelivery().getRoutingStatus()); - assertNull(cargo.getDelivery().getNextExpectedActivity()); - - // Repeat procedure of selecting one out of a number of possible routes - // satisfying the route spec - List newItineraries = bookingService.requestPossibleRoutesForCargo(cargo.getTrackingId()); - Itinerary newItinerary = selectPreferedItinerary(newItineraries); - cargo.assignToRoute(newItinerary); - - // New itinerary should satisfy new route - assertEquals(RoutingStatus.ROUTED, cargo.getDelivery().getRoutingStatus()); - - // TODO [TDD] we can't handle the face that after a reroute, the cargo isn't - // misdirected anymore - // org.junit.Assert.assertFalse(cargo.isMisdirected()); - // org.junit.Assert.assertEquals(new HandlingActivity(HandlingEvent.Type.LOAD, - // SampleLocations.TOKYO), cargo.getNextExpectedActivity()); - // -- Cargo has been rerouted, shipping continues -- - // Load in Tokyo - handlingEventService.registerHandlingEvent(DateUtil.toDate("2009-03-08"), trackingId, - SampleVoyages.v300.getVoyageNumber(), SampleLocations.TOKYO.getUnLocode(), HandlingEvent.Type.LOAD); - - // Check current state - should be ok - assertEquals(SampleVoyages.v300, cargo.getDelivery().getCurrentVoyage()); - assertEquals(SampleLocations.TOKYO, cargo.getDelivery().getLastKnownLocation()); - assertEquals(TransportStatus.ONBOARD_CARRIER, cargo.getDelivery().getTransportStatus()); - assertFalse(cargo.getDelivery().isMisdirected()); - assertEquals(new HandlingActivity(HandlingEvent.Type.UNLOAD, SampleLocations.HAMBURG, SampleVoyages.v300), - cargo.getDelivery().getNextExpectedActivity()); - - // Unload in Hamburg - handlingEventService.registerHandlingEvent(DateUtil.toDate("2009-03-12"), trackingId, - SampleVoyages.v300.getVoyageNumber(), SampleLocations.HAMBURG.getUnLocode(), HandlingEvent.Type.UNLOAD); - - // Check current state - should be ok - assertEquals(Voyage.NONE, cargo.getDelivery().getCurrentVoyage()); - assertEquals(SampleLocations.HAMBURG, cargo.getDelivery().getLastKnownLocation()); - assertEquals(TransportStatus.IN_PORT, cargo.getDelivery().getTransportStatus()); - assertFalse(cargo.getDelivery().isMisdirected()); - assertEquals(new HandlingActivity(HandlingEvent.Type.LOAD, SampleLocations.HAMBURG, SampleVoyages.v400), - cargo.getDelivery().getNextExpectedActivity()); - - // Load in Hamburg - handlingEventService.registerHandlingEvent(DateUtil.toDate("2009-03-14"), trackingId, - SampleVoyages.v400.getVoyageNumber(), SampleLocations.HAMBURG.getUnLocode(), HandlingEvent.Type.LOAD); - - // Check current state - should be ok - assertEquals(SampleVoyages.v400, cargo.getDelivery().getCurrentVoyage()); - assertEquals(SampleLocations.HAMBURG, cargo.getDelivery().getLastKnownLocation()); - assertEquals(TransportStatus.ONBOARD_CARRIER, cargo.getDelivery().getTransportStatus()); - assertFalse(cargo.getDelivery().isMisdirected()); - assertEquals(new HandlingActivity(HandlingEvent.Type.UNLOAD, SampleLocations.STOCKHOLM, SampleVoyages.v400), - cargo.getDelivery().getNextExpectedActivity()); - - // Unload in SampleLocations.STOCKHOLM - handlingEventService.registerHandlingEvent(DateUtil.toDate("2009-03-15"), trackingId, - SampleVoyages.v400.getVoyageNumber(), SampleLocations.STOCKHOLM.getUnLocode(), - HandlingEvent.Type.UNLOAD); - - // Check current state - should be ok - assertEquals(Voyage.NONE, cargo.getDelivery().getCurrentVoyage()); - assertEquals(SampleLocations.STOCKHOLM, cargo.getDelivery().getLastKnownLocation()); - assertEquals(TransportStatus.IN_PORT, cargo.getDelivery().getTransportStatus()); - assertFalse(cargo.getDelivery().isMisdirected()); - assertEquals(new HandlingActivity(HandlingEvent.Type.CLAIM, SampleLocations.STOCKHOLM), - cargo.getDelivery().getNextExpectedActivity()); - - // Finally, cargo is claimed in SampleLocations.STOCKHOLM. This ends the cargo - // lifecycle from our perspective. - handlingEventService.registerHandlingEvent(DateUtil.toDate("2009-03-16"), trackingId, null, - SampleLocations.STOCKHOLM.getUnLocode(), HandlingEvent.Type.CLAIM); - - // Check current state - should be ok - assertEquals(Voyage.NONE, cargo.getDelivery().getCurrentVoyage()); - assertEquals(SampleLocations.STOCKHOLM, cargo.getDelivery().getLastKnownLocation()); - assertEquals(TransportStatus.CLAIMED, cargo.getDelivery().getTransportStatus()); - assertFalse(cargo.getDelivery().isMisdirected()); - assertNull(cargo.getDelivery().getNextExpectedActivity()); - } - - /* - * Utility stubs below. - */ - private Itinerary selectPreferedItinerary(List itineraries) { - return itineraries.get(0); - } - - protected void setUp() throws Exception { - routingService = new RoutingService() { - public List fetchRoutesForSpecification(RouteSpecification routeSpecification) { - if (routeSpecification.getOrigin().equals(SampleLocations.HONGKONG)) { - // Hongkong - NYC - Chicago - SampleLocations.STOCKHOLM, initial routing - return Arrays.asList(new Itinerary(Arrays.asList( - new Leg(SampleVoyages.v100, SampleLocations.HONGKONG, SampleLocations.NEWYORK, - DateUtil.toDate("2009-03-03"), DateUtil.toDate("2009-03-09")), - new Leg(SampleVoyages.v200, SampleLocations.NEWYORK, SampleLocations.CHICAGO, - DateUtil.toDate("2009-03-10"), DateUtil.toDate("2009-03-14")), - new Leg(SampleVoyages.v200, SampleLocations.CHICAGO, SampleLocations.STOCKHOLM, - DateUtil.toDate("2009-03-07"), DateUtil.toDate("2009-03-11"))))); - } else { - // Tokyo - Hamburg - SampleLocations.STOCKHOLM, rerouting misdirected cargo from - // Tokyo - return Arrays.asList(new Itinerary(Arrays.asList( - new Leg(SampleVoyages.v300, SampleLocations.TOKYO, SampleLocations.HAMBURG, - DateUtil.toDate("2009-03-08"), DateUtil.toDate("2009-03-12")), - new Leg(SampleVoyages.v400, SampleLocations.HAMBURG, SampleLocations.STOCKHOLM, - DateUtil.toDate("2009-03-14"), DateUtil.toDate("2009-03-15"))))); - } - } - }; - -// applicationEvents = new SynchronousApplicationEventsStub(); - // In-memory implementations of the repositories -// handlingEventRepository = new HandlingEventRepositoryInMem(); -// cargoRepository = new CargoRepositoryInMem(); -// locationRepository = new LocationRepositoryInMem(); -// voyageRepository = new VoyageRepositoryInMem(); - // Actual factories and application services, wired with stubbed or in-memory - // infrastructure -// handlingEventFactory = new HandlingEventFactory(cargoRepository, voyageRepository, locationRepository); -// cargoInspectionService = new CargoInspectionServiceImpl(applicationEvents, cargoRepository, handlingEventRepository); -// handlingEventService = new DefaultHandlingEventService(handlingEventRepository, applicationEvents, handlingEventFactory); -// bookingService = new BookingServiceImpl(cargoRepository, locationRepository, routingService); - // Circular dependency when doing synchrounous calls -// ((SynchronousApplicationEventsStub) applicationEvents).setCargoInspectionService(cargoInspectionService); - } + /** + * Repository implementations are part of the infrastructure layer, which in this test is stubbed + * out by in-memory replacements. + */ + HandlingEventRepository handlingEventRepository; + + CargoRepository cargoRepository; + LocationRepository locationRepository; + VoyageRepository voyageRepository; + /** + * This interface is part of the application layer, and defines a number of events that occur + * during aplication execution. It is used for message-driving and is implemented using JMS. + * + *

In this test it is stubbed with synchronous calls. + */ + ApplicationEvents applicationEvents; + /** + * These three components all belong to the application layer, and map against use cases of the + * application. The "real" implementations are used in this lifecycle test, but wired with stubbed + * infrastructure. + */ + BookingService bookingService; + + HandlingEventService handlingEventService; + CargoInspectionService cargoInspectionService; + /** + * This factory is part of the handling aggregate and belongs to the domain layer. Similar to the + * application layer components, the "real" implementation is used here too, wired with stubbed + * infrastructure. + */ + HandlingEventFactory handlingEventFactory; + /** + * This is a domain service interface, whose implementation is part of the infrastructure layer + * (remote call to external system). + * + *

It is stubbed in this test. + */ + RoutingService routingService; + + public void testCargoFromHongkongToStockholm() throws Exception { + /* + * Test setup: A cargo should be shipped from Hongkong to + * SampleLocations.STOCKHOLM, and it should arrive in no more than two weeks. + */ + Location origin = SampleLocations.HONGKONG; + Location destination = SampleLocations.STOCKHOLM; + Date arrivalDeadline = DateUtil.toDate("2009-03-18"); + + /* + * Use case 1: booking + * + * A new cargo is booked, and the unique tracking id is assigned to the cargo. + */ + TrackingId trackingId = + bookingService.bookNewCargo( + origin.getUnLocode(), destination.getUnLocode(), arrivalDeadline); + + /* + * The tracking id can be used to lookup the cargo in the repository. + * + * Important: The cargo, and thus the domain model, is responsible for + * determining the status of the cargo, whether it is on the right track or not + * and so on. This is core domain logic. + * + * Tracking the cargo basically amounts to presenting information extracted from + * the cargo aggregate in a suitable way. + */ + Cargo cargo = cargoRepository.find(trackingId); + org.junit.Assert.assertNotNull(cargo); + Assert.assertEquals(TransportStatus.NOT_RECEIVED, cargo.getDelivery().getTransportStatus()); + Assert.assertEquals(RoutingStatus.NOT_ROUTED, cargo.getDelivery().getRoutingStatus()); + assertFalse(cargo.getDelivery().isMisdirected()); + assertNull(cargo.getDelivery().getEstimatedTimeOfArrival()); + assertNull(cargo.getDelivery().getNextExpectedActivity()); + + /* + * Use case 2: routing + * + * A number of possible routes for this cargo is requested and may be presented + * to the customer in some way for him/her to choose from. Selection could be + * affected by things like price and time of delivery, but this test simply uses + * an arbitrary selection to mimic that process. + * + * The cargo is then assigned to the selected route, described by an itinerary. + */ + List itineraries = bookingService.requestPossibleRoutesForCargo(trackingId); + Itinerary itinerary = selectPreferedItinerary(itineraries); + cargo.assignToRoute(itinerary); + + assertEquals(TransportStatus.NOT_RECEIVED, cargo.getDelivery().getTransportStatus()); + assertEquals(RoutingStatus.ROUTED, cargo.getDelivery().getRoutingStatus()); + org.junit.Assert.assertNotNull(cargo.getDelivery().getEstimatedTimeOfArrival()); + assertEquals( + new HandlingActivity(HandlingEvent.Type.RECEIVE, SampleLocations.HONGKONG), + cargo.getDelivery().getNextExpectedActivity()); + + /* + * Use case 3: handling + * + * A handling event registration attempt will be formed from parsing the data + * coming in as a handling report either via the web service interface or as an + * uploaded CSV file. + * + * The handling event factory tries to create a HandlingEvent from the attempt, + * and if the factory decides that this is a plausible handling event, it is + * stored. If the attempt is invalid, for example if no cargo exists for the + * specfied tracking id, the attempt is rejected. + * + * Handling begins: cargo is received in Hongkong. + */ + handlingEventService.registerHandlingEvent( + DateUtil.toDate("2009-03-01"), + trackingId, + null, + SampleLocations.HONGKONG.getUnLocode(), + HandlingEvent.Type.RECEIVE); + + assertEquals(TransportStatus.IN_PORT, cargo.getDelivery().getTransportStatus()); + assertEquals(SampleLocations.HONGKONG, cargo.getDelivery().getLastKnownLocation()); + + // Next event: Load onto voyage SampleVoyages.CM003 in Hongkong + handlingEventService.registerHandlingEvent( + DateUtil.toDate("2009-03-03"), + trackingId, + SampleVoyages.v100.getVoyageNumber(), + SampleLocations.HONGKONG.getUnLocode(), + HandlingEvent.Type.LOAD); + + // Check current state - should be ok + assertEquals(SampleVoyages.v100, cargo.getDelivery().getCurrentVoyage()); + assertEquals(SampleLocations.HONGKONG, cargo.getDelivery().getLastKnownLocation()); + assertEquals(TransportStatus.ONBOARD_CARRIER, cargo.getDelivery().getTransportStatus()); + assertFalse(cargo.getDelivery().isMisdirected()); + assertEquals( + new HandlingActivity( + HandlingEvent.Type.UNLOAD, SampleLocations.NEWYORK, SampleVoyages.v100), + cargo.getDelivery().getNextExpectedActivity()); + + /* + * Here's an attempt to register a handling event that's not valid because there + * is no voyage with the specified voyage number, and there's no location with + * the specified UN Locode either. + * + * This attempt will be rejected and will not affect the cargo delivery in any + * way. + */ + VoyageNumber noSuchVoyageNumber = new VoyageNumber("XX000"); + UnLocode noSuchUnLocode = new UnLocode("ZZZZZ"); + try { + handlingEventService.registerHandlingEvent( + DateUtil.toDate("2009-03-05"), + trackingId, + noSuchVoyageNumber, + noSuchUnLocode, + HandlingEvent.Type.LOAD); + org.junit.Assert.fail( + "Should not be able to register a handling event with invalid location and voyage"); + } catch (CannotCreateHandlingEventException expected) { + } + + // Cargo is now (incorrectly) unloaded in Tokyo + handlingEventService.registerHandlingEvent( + DateUtil.toDate("2009-03-05"), + trackingId, + SampleVoyages.v100.getVoyageNumber(), + SampleLocations.TOKYO.getUnLocode(), + HandlingEvent.Type.UNLOAD); + + // Check current state - cargo is misdirected! + Assert.assertEquals(Voyage.NONE, cargo.getDelivery().getCurrentVoyage()); + assertEquals(SampleLocations.TOKYO, cargo.getDelivery().getLastKnownLocation()); + assertEquals(TransportStatus.IN_PORT, cargo.getDelivery().getTransportStatus()); + org.junit.Assert.assertTrue(cargo.getDelivery().isMisdirected()); + assertNull(cargo.getDelivery().getNextExpectedActivity()); + + // -- Cargo needs to be rerouted -- + // TODO [TDD] cleaner reroute from "earliest location from where the new route + // originates" + // Specify a new route, this time from Tokyo (where it was incorrectly unloaded) + // to SampleLocations.STOCKHOLM + RouteSpecification fromTokyo = + new RouteSpecification(SampleLocations.TOKYO, SampleLocations.STOCKHOLM, arrivalDeadline); + cargo.specifyNewRoute(fromTokyo); + + // The old itinerary does not satisfy the new specification + assertEquals(RoutingStatus.MISROUTED, cargo.getDelivery().getRoutingStatus()); + assertNull(cargo.getDelivery().getNextExpectedActivity()); + + // Repeat procedure of selecting one out of a number of possible routes + // satisfying the route spec + List newItineraries = + bookingService.requestPossibleRoutesForCargo(cargo.getTrackingId()); + Itinerary newItinerary = selectPreferedItinerary(newItineraries); + cargo.assignToRoute(newItinerary); + + // New itinerary should satisfy new route + assertEquals(RoutingStatus.ROUTED, cargo.getDelivery().getRoutingStatus()); + + // TODO [TDD] we can't handle the face that after a reroute, the cargo isn't + // misdirected anymore + // org.junit.Assert.assertFalse(cargo.isMisdirected()); + // org.junit.Assert.assertEquals(new HandlingActivity(HandlingEvent.Type.LOAD, + // SampleLocations.TOKYO), cargo.getNextExpectedActivity()); + // -- Cargo has been rerouted, shipping continues -- + // Load in Tokyo + handlingEventService.registerHandlingEvent( + DateUtil.toDate("2009-03-08"), + trackingId, + SampleVoyages.v300.getVoyageNumber(), + SampleLocations.TOKYO.getUnLocode(), + HandlingEvent.Type.LOAD); + + // Check current state - should be ok + assertEquals(SampleVoyages.v300, cargo.getDelivery().getCurrentVoyage()); + assertEquals(SampleLocations.TOKYO, cargo.getDelivery().getLastKnownLocation()); + assertEquals(TransportStatus.ONBOARD_CARRIER, cargo.getDelivery().getTransportStatus()); + assertFalse(cargo.getDelivery().isMisdirected()); + assertEquals( + new HandlingActivity( + HandlingEvent.Type.UNLOAD, SampleLocations.HAMBURG, SampleVoyages.v300), + cargo.getDelivery().getNextExpectedActivity()); + + // Unload in Hamburg + handlingEventService.registerHandlingEvent( + DateUtil.toDate("2009-03-12"), + trackingId, + SampleVoyages.v300.getVoyageNumber(), + SampleLocations.HAMBURG.getUnLocode(), + HandlingEvent.Type.UNLOAD); + + // Check current state - should be ok + assertEquals(Voyage.NONE, cargo.getDelivery().getCurrentVoyage()); + assertEquals(SampleLocations.HAMBURG, cargo.getDelivery().getLastKnownLocation()); + assertEquals(TransportStatus.IN_PORT, cargo.getDelivery().getTransportStatus()); + assertFalse(cargo.getDelivery().isMisdirected()); + assertEquals( + new HandlingActivity(HandlingEvent.Type.LOAD, SampleLocations.HAMBURG, SampleVoyages.v400), + cargo.getDelivery().getNextExpectedActivity()); + + // Load in Hamburg + handlingEventService.registerHandlingEvent( + DateUtil.toDate("2009-03-14"), + trackingId, + SampleVoyages.v400.getVoyageNumber(), + SampleLocations.HAMBURG.getUnLocode(), + HandlingEvent.Type.LOAD); + + // Check current state - should be ok + assertEquals(SampleVoyages.v400, cargo.getDelivery().getCurrentVoyage()); + assertEquals(SampleLocations.HAMBURG, cargo.getDelivery().getLastKnownLocation()); + assertEquals(TransportStatus.ONBOARD_CARRIER, cargo.getDelivery().getTransportStatus()); + assertFalse(cargo.getDelivery().isMisdirected()); + assertEquals( + new HandlingActivity( + HandlingEvent.Type.UNLOAD, SampleLocations.STOCKHOLM, SampleVoyages.v400), + cargo.getDelivery().getNextExpectedActivity()); + + // Unload in SampleLocations.STOCKHOLM + handlingEventService.registerHandlingEvent( + DateUtil.toDate("2009-03-15"), + trackingId, + SampleVoyages.v400.getVoyageNumber(), + SampleLocations.STOCKHOLM.getUnLocode(), + HandlingEvent.Type.UNLOAD); + + // Check current state - should be ok + assertEquals(Voyage.NONE, cargo.getDelivery().getCurrentVoyage()); + assertEquals(SampleLocations.STOCKHOLM, cargo.getDelivery().getLastKnownLocation()); + assertEquals(TransportStatus.IN_PORT, cargo.getDelivery().getTransportStatus()); + assertFalse(cargo.getDelivery().isMisdirected()); + assertEquals( + new HandlingActivity(HandlingEvent.Type.CLAIM, SampleLocations.STOCKHOLM), + cargo.getDelivery().getNextExpectedActivity()); + + // Finally, cargo is claimed in SampleLocations.STOCKHOLM. This ends the cargo + // lifecycle from our perspective. + handlingEventService.registerHandlingEvent( + DateUtil.toDate("2009-03-16"), + trackingId, + null, + SampleLocations.STOCKHOLM.getUnLocode(), + HandlingEvent.Type.CLAIM); + + // Check current state - should be ok + assertEquals(Voyage.NONE, cargo.getDelivery().getCurrentVoyage()); + assertEquals(SampleLocations.STOCKHOLM, cargo.getDelivery().getLastKnownLocation()); + assertEquals(TransportStatus.CLAIMED, cargo.getDelivery().getTransportStatus()); + assertFalse(cargo.getDelivery().isMisdirected()); + assertNull(cargo.getDelivery().getNextExpectedActivity()); + } + + /* + * Utility stubs below. + */ + private Itinerary selectPreferedItinerary(List itineraries) { + return itineraries.get(0); + } + + protected void setUp() throws Exception { + routingService = + new RoutingService() { + public List fetchRoutesForSpecification( + RouteSpecification routeSpecification) { + if (routeSpecification.getOrigin().equals(SampleLocations.HONGKONG)) { + // Hongkong - NYC - Chicago - SampleLocations.STOCKHOLM, initial routing + return Arrays.asList( + new Itinerary( + Arrays.asList( + new Leg( + SampleVoyages.v100, + SampleLocations.HONGKONG, + SampleLocations.NEWYORK, + DateUtil.toDate("2009-03-03"), + DateUtil.toDate("2009-03-09")), + new Leg( + SampleVoyages.v200, + SampleLocations.NEWYORK, + SampleLocations.CHICAGO, + DateUtil.toDate("2009-03-10"), + DateUtil.toDate("2009-03-14")), + new Leg( + SampleVoyages.v200, + SampleLocations.CHICAGO, + SampleLocations.STOCKHOLM, + DateUtil.toDate("2009-03-07"), + DateUtil.toDate("2009-03-11"))))); + } else { + // Tokyo - Hamburg - SampleLocations.STOCKHOLM, rerouting misdirected cargo from + // Tokyo + return Arrays.asList( + new Itinerary( + Arrays.asList( + new Leg( + SampleVoyages.v300, + SampleLocations.TOKYO, + SampleLocations.HAMBURG, + DateUtil.toDate("2009-03-08"), + DateUtil.toDate("2009-03-12")), + new Leg( + SampleVoyages.v400, + SampleLocations.HAMBURG, + SampleLocations.STOCKHOLM, + DateUtil.toDate("2009-03-14"), + DateUtil.toDate("2009-03-15"))))); + } + } + }; + + // applicationEvents = new SynchronousApplicationEventsStub(); + // In-memory implementations of the repositories + // handlingEventRepository = new HandlingEventRepositoryInMem(); + // cargoRepository = new CargoRepositoryInMem(); + // locationRepository = new LocationRepositoryInMem(); + // voyageRepository = new VoyageRepositoryInMem(); + // Actual factories and application services, wired with stubbed or in-memory + // infrastructure + // handlingEventFactory = new HandlingEventFactory(cargoRepository, voyageRepository, + // locationRepository); + // cargoInspectionService = new CargoInspectionServiceImpl(applicationEvents, + // cargoRepository, handlingEventRepository); + // handlingEventService = new DefaultHandlingEventService(handlingEventRepository, + // applicationEvents, handlingEventFactory); + // bookingService = new BookingServiceImpl(cargoRepository, locationRepository, + // routingService); + // Circular dependency when doing synchrounous calls + // ((SynchronousApplicationEventsStub) + // applicationEvents).setCargoInspectionService(cargoInspectionService); + } } From 378ee733509182188607f466e59be55934af89f9 Mon Sep 17 00:00:00 2001 From: Reza Rahman Date: Sun, 17 Jan 2021 10:23:12 -0500 Subject: [PATCH 10/22] Apply Google Java Style Guide --- .../dialogs/changeArrivalDeadlineDate.xhtml | 53 ++-- .../admin/dialogs/changeDestination.xhtml | 62 ++-- src/main/webapp/admin/route.xhtml | 3 +- src/main/webapp/admin/selectItinerary.xhtml | 38 +-- src/main/webapp/admin/show.xhtml | 3 +- .../webapp/admin/tables/listNotRouted.xhtml | 13 +- src/main/webapp/admin/tracking/map.xhtml | 16 +- src/main/webapp/admin/tracking/mapFrame.xhtml | 53 ++-- src/main/webapp/admin/tracking/track.xhtml | 9 +- src/main/webapp/booking/booking-date.xhtml | 12 +- src/main/webapp/public/mapFrame.xhtml | 4 +- src/main/webapp/resources/css/app.css | 300 ++++++++---------- src/main/webapp/resources/css/dd.css | 149 ++++----- src/main/webapp/resources/css/title.css | 172 +++++----- 14 files changed, 433 insertions(+), 454 deletions(-) diff --git a/src/main/webapp/admin/dialogs/changeArrivalDeadlineDate.xhtml b/src/main/webapp/admin/dialogs/changeArrivalDeadlineDate.xhtml index 77b22613c..8f4591e91 100644 --- a/src/main/webapp/admin/dialogs/changeArrivalDeadlineDate.xhtml +++ b/src/main/webapp/admin/dialogs/changeArrivalDeadlineDate.xhtml @@ -1,36 +1,39 @@ + xmlns:h="http://xmlns.jcp.org/jsf/html" + xmlns:f="http://xmlns.jcp.org/jsf/core" + xmlns:p="http://primefaces.org/ui"> - Change Deadline + Change Deadline - - - - + + + + -

- - - - +
+ + + + - - + + - - + + - + - - - -
+ +
+
+
diff --git a/src/main/webapp/admin/dialogs/changeDestination.xhtml b/src/main/webapp/admin/dialogs/changeDestination.xhtml index 50e5a2715..1537a556d 100644 --- a/src/main/webapp/admin/dialogs/changeDestination.xhtml +++ b/src/main/webapp/admin/dialogs/changeDestination.xhtml @@ -1,43 +1,43 @@ + xmlns:h="http://xmlns.jcp.org/jsf/html" + xmlns:f="http://xmlns.jcp.org/jsf/core" + xmlns:p="http://primefaces.org/ui"> - Change Destination + Change Destination - - - - + + + + -
- - - - +
+ + + + - - + + - - - - + + + + - + - - - -
+ +
+
+
diff --git a/src/main/webapp/admin/route.xhtml b/src/main/webapp/admin/route.xhtml index 7f748b0d4..a1e099bad 100644 --- a/src/main/webapp/admin/route.xhtml +++ b/src/main/webapp/admin/route.xhtml @@ -66,7 +66,8 @@ var="itinerary" varStatus="itineraryStatus">
- Route option ##{itineraryStatus.index + 1} + Route option + ##{itineraryStatus.index + 1}
diff --git a/src/main/webapp/admin/selectItinerary.xhtml b/src/main/webapp/admin/selectItinerary.xhtml index c515d0cd4..356d008e2 100644 --- a/src/main/webapp/admin/selectItinerary.xhtml +++ b/src/main/webapp/admin/selectItinerary.xhtml @@ -1,25 +1,25 @@ + xmlns:h="http://xmlns.jcp.org/jsf/html" + xmlns:f="http://xmlns.jcp.org/jsf/core" + xmlns:ui="http://xmlns.jcp.org/jsf/facelets"> - Cargo Administration + Cargo Administration - - - - - + + + + + -
-
- -

No routes found that satisfy the route specification. Try - setting an arrival deadline further into the future (a few weeks at - least).

-
-
-
+
+
+ +

No routes found that satisfy the route specification. Try + setting an arrival deadline further into the future (a few weeks at + least).

+
+
+
diff --git a/src/main/webapp/admin/show.xhtml b/src/main/webapp/admin/show.xhtml index ec153112e..23a7813d5 100644 --- a/src/main/webapp/admin/show.xhtml +++ b/src/main/webapp/admin/show.xhtml @@ -66,7 +66,8 @@ - +

+ action="#{changeArrivalDeadlineDateDialog.showDialog(cargoNotRouted.trackingId)}" + style="text-decoration: none;" id="arrivalDeadlineToUpdate"> - + listener="#{changeArrivalDeadlineDateDialog.handleReturn}" + update="tableNotRouted" /> + diff --git a/src/main/webapp/admin/tracking/map.xhtml b/src/main/webapp/admin/tracking/map.xhtml index 5bd768de9..5d3881f14 100644 --- a/src/main/webapp/admin/tracking/map.xhtml +++ b/src/main/webapp/admin/tracking/map.xhtml @@ -1,12 +1,12 @@ + xmlns:ui="http://xmlns.jcp.org/jsf/facelets"> - Live Map - -
-