package org.sculptor.dddsample.cargo.domain; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.sculptor.dddsample.cargo.domain.TrackingId.trackingId; import static org.sculptor.dddsample.location.domain.SampleLocations.HELSINKI; import static org.sculptor.dddsample.location.domain.SampleLocations.HONGKONG; import static org.sculptor.dddsample.location.domain.SampleLocations.MELBOURNE; import static org.sculptor.dddsample.location.domain.SampleLocations.STOCKHOLM; import java.sql.Timestamp; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.TimeZone; import javax.persistence.Query; import org.joda.time.DateTime; import org.junit.Test; import org.sculptor.dddsample.cargo.exception.CargoNotFoundException; import org.sculptor.dddsample.carrier.domain.CarrierMovement; import org.sculptor.dddsample.carrier.domain.CarrierMovementId; import org.sculptor.dddsample.carrier.domain.CarrierMovementRepository; import org.sculptor.dddsample.location.domain.Location; import org.sculptor.dddsample.location.domain.LocationRepository; import org.sculptor.dddsample.location.domain.UnLocode; import org.sculptor.dddsample.location.exception.LocationNotFoundException; import org.sculptor.framework.test.AbstractDbUnitJpaTests; import org.springframework.beans.factory.annotation.Autowired; public class CargoRepositoryTest extends AbstractDbUnitJpaTests { private CargoRepository cargoRepository; private LocationRepository locationRepository; private CarrierMovementRepository carrierMovementRepository; @Autowired public void setCargoRepository(CargoRepository cargoRepository) { this.cargoRepository = cargoRepository; } @Autowired public void setLocationRepository(LocationRepository locationRepository) { this.locationRepository = locationRepository; } @Autowired public void setCarrierMovementRepository(CarrierMovementRepository carrierMovementRepository) { this.carrierMovementRepository = carrierMovementRepository; } private static final Timestamp base; static { try { SimpleDateFormat utcSimpleDateFormat = new SimpleDateFormat("yyyy-MM-dd") { { // set the calendar to use UTC calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC")); calendar.setLenient(false); } }; Date date = utcSimpleDateFormat.parse("2008-01-01"); base = new Timestamp(date.getTime()); } catch (ParseException e) { throw new RuntimeException(e); } } private static Timestamp ts(int hours) { return new Timestamp(base.getTime() + 1000L * 60 * 60 * hours); } public static DateTime offset(int hours) { return new DateTime(new Date(ts(hours).getTime())); } @Override protected String[] getCompositeDataSetFiles() { return new String[] {"dbunit/TestData.xml","dbunit/ExtraCargo.xml" }; } @Test public void testFindByCargoIdExtra() throws Exception { Cargo cargo = cargoRepository.find(trackingId("JJJ"), true); assertEquals(Long.valueOf(6), cargo.getOrigin().getId()); assertEquals(Long.valueOf(2), cargo.getDestination().getId()); } @Test public void testFindByCargoId() throws Exception { Cargo cargo = cargoRepository.find(trackingId("FGH"), true); assertEquals(HONGKONG, cargo.getOrigin()); assertEquals(HELSINKI, cargo.getDestination()); DeliveryHistory dh = cargo.deliveryHistory(); assertNotNull(dh); List<HandlingEvent> events = dh.eventsOrderedByCompletionTime(); assertEquals(2, events.size()); HandlingEvent firstEvent = events.get(0); assertHandlingEvent(cargo, firstEvent, Type.RECEIVE, HONGKONG, 100, 160, null); HandlingEvent secondEvent = events.get(1); CarrierMovement expectedCm = new CarrierMovement(new CarrierMovementId("CAR_010"), HONGKONG, MELBOURNE); assertHandlingEvent(cargo, secondEvent, Type.LOAD, HONGKONG, 150, 110, expectedCm); List<Leg> legs = cargo.itinerary().getLegs(); assertEquals(3, legs.size()); Leg firstLeg = legs.get(0); assertLeg(firstLeg, "CAR_010", HONGKONG, MELBOURNE); Leg secondLeg = legs.get(1); assertLeg(secondLeg, "CAR_011", MELBOURNE, STOCKHOLM); Leg thirdLeg = legs.get(2); assertLeg(thirdLeg, "CAR_011", STOCKHOLM, HELSINKI); } private void assertHandlingEvent(Cargo cargo, HandlingEvent event, Type expectedEventType, Location expectedLocation, int completionTimeMs, int registrationTimeMs, CarrierMovement expectedCarrierMovement) { assertEquals(expectedEventType, event.getType()); assertEquals(expectedLocation, event.getLocation()); DateTime expectedCompletionTime = offset(completionTimeMs); assertEquals(expectedCompletionTime, event.getCompletionTime()); DateTime expectedRegistrationTime = offset(registrationTimeMs); assertEquals(expectedRegistrationTime, event.getRegistrationTime()); if (expectedCarrierMovement == null) { assertNull(event.getCarrierMovement()); } else { assertEquals(expectedCarrierMovement, event.getCarrierMovement()); } assertEquals(cargo, event.getCargo()); } @Test(expected=CargoNotFoundException.class) public void testFindByCargoIdUnknownId() throws CargoNotFoundException { cargoRepository.find(trackingId("UNKNOWN")); } private void assertLeg(Leg firstLeg, String cmId, Location expectedFrom, Location expectedTo) { assertEquals(new CarrierMovementId(cmId), firstLeg.getCarrierMovement().getCarrierMovementId()); assertEquals(expectedFrom, firstLeg.getFrom()); assertEquals(expectedTo, firstLeg.getTo()); } @Test public void testSave() throws LocationNotFoundException { TrackingId trackingId = trackingId("AAA"); Location origin = locationRepository.find(STOCKHOLM.getUnLocode()); Location destination = locationRepository.find(MELBOURNE.getUnLocode()); Cargo cargo = new Cargo(trackingId, origin, destination); cargoRepository.save(cargo); assertEquals(cargo, getCargoForTrackingIdByNativeQuery(trackingId)); } /** * need to lookup Cargo within the same transaction, hsqldb 2.x doesn't * support read uncommitted */ private Cargo getCargoForTrackingIdByNativeQuery(TrackingId trackingId) { flush(); getEntityManager().clear(); Query query = getEntityManager().createNativeQuery( "select * from Cargo where TRACKINGID = '" + trackingId.getIdentifier() + "'", Cargo.class); return (Cargo) query.getSingleResult(); } @Test public void testDeleteOrphanedItinerary() throws Exception { Cargo cargo = cargoRepository.find(trackingId("FGH")); int countBefore = countRowsInTable(Itinerary.class); // Repository is responsible for deleting orphaned, detached itineraries cargoRepository.detachItineray(cargo); int countAfter = countRowsInTable(Itinerary.class); assertEquals(countBefore - 1, countAfter); } @Test public void testReplaceItinerary() throws Exception { Cargo cargo = cargoRepository.find(trackingId("FGH")); Long oldItineraryId = cargo.itinerary().getId(); assertEquals(1, countRowsInTable(Itinerary.class, "where id = " + oldItineraryId)); CarrierMovement cm = carrierMovementRepository.find(new CarrierMovementId("CAR_006")); Location legFrom = locationRepository.find(new UnLocode("FIHEL")); Location legTo = locationRepository.find(new UnLocode("DEHAM")); Itinerary newItinerary = new Itinerary(Arrays.asList(new Leg(cm, legFrom, legTo))); cargoRepository.detachItineray(cargo); cargo.attachItinerary(newItinerary); cargo = cargoRepository.save(cargo); // Old itinerary should be deleted assertEquals(0, countRowsInTable(Itinerary.class, "where id = " + oldItineraryId)); // New itinerary should be cascade-saved Long newItineraryId = cargo.itinerary().getId(); assertEquals(1, countRowsInTable(Itinerary.class, "where id = " + newItineraryId)); } @Test public void testSaveShouldNotCascadeToHandlingEvents() throws Exception { Cargo cargo = cargoRepository.find(trackingId("FGH"), true); int eventCount = cargo.deliveryHistory().eventsOrderedByCompletionTime().size(); Location origin = locationRepository.find(STOCKHOLM.getUnLocode()); HandlingEvent event = new HandlingEvent(cargo, new DateTime(), new DateTime(), Type.RECEIVE, origin, null); assertFalse(cargo.deliveryHistory().eventsOrderedByCompletionTime().contains(event)); cargo.getEvents().addAll(Arrays.asList(event)); assertTrue(cargo.deliveryHistory().eventsOrderedByCompletionTime().contains(event)); // Save cargo, and then re-load it - should not pick // up the added event, // as it was never cascade-saved cargo = cargoRepository.save(cargo); getEntityManager().refresh(cargo); // cargo = cargoRepository.find(cargo.getTrackingId(), true); assertFalse(cargo.deliveryHistory().eventsOrderedByCompletionTime().contains(event)); assertEquals(eventCount, cargo.deliveryHistory().eventsOrderedByCompletionTime().size()); } @Test public void testFindAll() { List<Cargo> all = cargoRepository.findAll(); assertNotNull(all); assertEquals(7, all.size()); } @Test public void testNextTrackingId() { TrackingId trackingId = cargoRepository.nextTrackingId(); assertNotNull(trackingId); TrackingId trackingId2 = cargoRepository.nextTrackingId(); assertNotNull(trackingId2); assertFalse(trackingId.equals(trackingId2)); } }