-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
101 changed files
with
23,485 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
3 changes: 3 additions & 0 deletions
3
ddd/springboot-dddsample/src/main/java/org/hzz/ddd/Application.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
45 changes: 45 additions & 0 deletions
45
ddd/springboot-dddsample/src/main/java/org/hzz/ddd/application/BookingService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
package org.hzz.ddd.application; | ||
|
||
import org.hzz.ddd.domain.model.cargo.Itinerary; | ||
import org.hzz.ddd.domain.model.cargo.TrackingId; | ||
import org.hzz.ddd.domain.model.location.UnLocode; | ||
|
||
import java.time.Instant; | ||
import java.util.List; | ||
|
||
/** | ||
* Cargo booking service. | ||
*/ | ||
public interface BookingService { | ||
/** | ||
* Registers a new cargo in the tracking system, not yet routed. | ||
* | ||
* @param origin cargo origin | ||
* @param destination cargo destination | ||
* @param arrivalDeadline arrival deadline | ||
* @return Cargo tracking id | ||
*/ | ||
TrackingId bookNewCargo(UnLocode origin, UnLocode destination, Instant 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<Itinerary> requestPossibleRoutesForCargo(TrackingId trackingId); | ||
|
||
/** | ||
* @param itinerary itinerary describing the selected route | ||
* @param trackingId cargo tracking id | ||
*/ | ||
void assignCargoToRoute(Itinerary itinerary, TrackingId trackingId); | ||
|
||
/** | ||
* Changes the destination of a cargo. | ||
* | ||
* @param trackingId cargo tracking id | ||
* @param unLocode UN locode of new destination | ||
*/ | ||
void changeDestination(TrackingId trackingId, UnLocode unLocode); | ||
} |
55 changes: 55 additions & 0 deletions
55
ddd/springboot-dddsample/src/main/java/org/hzz/ddd/application/impl/BookingServiceImpl.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
package org.hzz.ddd.application.impl; | ||
|
||
import lombok.extern.slf4j.Slf4j; | ||
import org.hzz.ddd.application.BookingService; | ||
import org.hzz.ddd.domain.model.cargo.CargoFactory; | ||
import org.hzz.ddd.domain.model.cargo.CargoRepository; | ||
import org.hzz.ddd.domain.model.cargo.Itinerary; | ||
import org.hzz.ddd.domain.model.cargo.TrackingId; | ||
import org.hzz.ddd.domain.model.location.LocationRepository; | ||
import org.hzz.ddd.domain.model.location.UnLocode; | ||
import org.hzz.ddd.domain.service.RoutingService; | ||
import org.springframework.stereotype.Service; | ||
|
||
import java.time.Instant; | ||
import java.util.List; | ||
|
||
@Slf4j | ||
@Service | ||
public class BookingServiceImpl implements BookingService { | ||
|
||
private final CargoRepository cargoRepository; | ||
private final LocationRepository locationRepository; | ||
private final RoutingService routingService; | ||
private final CargoFactory cargoFactory; | ||
|
||
public BookingServiceImpl(final CargoRepository cargoRepository, | ||
final LocationRepository locationRepository, | ||
final RoutingService routingService, | ||
final CargoFactory cargoFactory) { | ||
this.cargoRepository = cargoRepository; | ||
this.locationRepository = locationRepository; | ||
this.routingService = routingService; | ||
this.cargoFactory = cargoFactory; | ||
} | ||
|
||
@Override | ||
public TrackingId bookNewCargo(UnLocode origin, UnLocode destination, Instant arrivalDeadline) { | ||
return null; | ||
} | ||
|
||
@Override | ||
public List<Itinerary> requestPossibleRoutesForCargo(TrackingId trackingId) { | ||
return null; | ||
} | ||
|
||
@Override | ||
public void assignCargoToRoute(Itinerary itinerary, TrackingId trackingId) { | ||
|
||
} | ||
|
||
@Override | ||
public void changeDestination(TrackingId trackingId, UnLocode unLocode) { | ||
|
||
} | ||
} |
38 changes: 38 additions & 0 deletions
38
ddd/springboot-dddsample/src/main/java/org/hzz/ddd/application/util/DateUtils.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
package org.hzz.ddd.application.util; | ||
|
||
import java.time.Instant; | ||
import java.time.format.DateTimeParseException; | ||
|
||
/** | ||
* A few utils for working with Date in tests. | ||
* | ||
*/ | ||
public final class DateUtils { | ||
|
||
/** | ||
* @param date date string as yyyy-MM-dd | ||
* @return Date representation | ||
*/ | ||
public static Instant toDate(final String date) { | ||
return toDate(date, "00:00"); | ||
} | ||
|
||
/** | ||
* @param date date string as yyyy-MM-dd | ||
* @param time time string as HH:mm | ||
* @return Date representation | ||
*/ | ||
public static Instant toDate(final String date, final String time) { | ||
try { | ||
return Instant.parse(date + "T" + time + ":00Z"); | ||
} catch (DateTimeParseException e) { | ||
throw new RuntimeException(e); | ||
} | ||
} | ||
|
||
/** | ||
* Prevent instantiation. | ||
*/ | ||
private DateUtils() { | ||
} | ||
} |
7 changes: 7 additions & 0 deletions
7
ddd/springboot-dddsample/src/main/java/org/hzz/ddd/config/DDDSampleApplicationContext.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package org.hzz.ddd.config; | ||
|
||
import org.springframework.context.annotation.Configuration; | ||
|
||
@Configuration | ||
public class DDDSampleApplicationContext { | ||
} |
189 changes: 189 additions & 0 deletions
189
ddd/springboot-dddsample/src/main/java/org/hzz/ddd/domain/model/cargo/Cargo.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,189 @@ | ||
package org.hzz.ddd.domain.model.cargo; | ||
|
||
|
||
import org.apache.commons.lang3.Validate; | ||
import org.hzz.ddd.domain.model.handling.HandlingHistory; | ||
import org.hzz.ddd.domain.model.location.Location; | ||
import org.hzz.ddd.domain.shared.Entity; | ||
|
||
import javax.persistence.*; | ||
import java.util.List; | ||
|
||
@javax.persistence.Entity(name="Cargo") | ||
@Table(name = "Cargo") | ||
public class Cargo implements Entity<Cargo> { | ||
@Id | ||
@GeneratedValue(strategy = GenerationType.AUTO) | ||
public long id; | ||
|
||
@Column(name = "tracking_id", unique = true) | ||
public String trackingId; | ||
|
||
@ManyToOne(fetch = FetchType.LAZY) | ||
@JoinColumn(name = "origin_id") | ||
public Location origin; | ||
|
||
@Embedded | ||
public RouteSpecification routeSpecification; | ||
|
||
@OneToMany(cascade = CascadeType.ALL) | ||
@JoinColumn(name = "cargo_id") | ||
public List<Leg> itinerary; // TODO figure out if we can map an Itinerary object instead | ||
|
||
@Embedded | ||
public Delivery delivery; | ||
|
||
public Cargo() { | ||
// Needed by Hibernate | ||
} | ||
|
||
public Cargo(final TrackingId trackingId, final RouteSpecification routeSpecification) { | ||
Validate.notNull(trackingId, "Tracking ID is required"); | ||
Validate.notNull(routeSpecification, "Route specification is required"); | ||
|
||
this.trackingId = trackingId.idString(); | ||
// 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.origin(); | ||
this.routeSpecification = routeSpecification; | ||
|
||
this.delivery = Delivery.derivedFrom( | ||
this.routeSpecification, null, HandlingHistory.EMPTY | ||
); | ||
} | ||
|
||
public Cargo(TrackingId trackingId, RouteSpecification routeSpecification, Itinerary itinerary) { | ||
Validate.notNull(trackingId, "Tracking ID is required"); | ||
Validate.notNull(routeSpecification, "Route specification is required"); | ||
this.trackingId = trackingId.idString(); | ||
this.origin = routeSpecification.origin(); | ||
this.routeSpecification = routeSpecification; | ||
this.itinerary = itinerary.legs(); | ||
|
||
this.delivery = Delivery.derivedFrom( | ||
this.routeSpecification, new Itinerary(this.itinerary), HandlingHistory.EMPTY | ||
); | ||
} | ||
|
||
/** | ||
* The tracking id is the identity of this entity, and is unique. | ||
* | ||
* @return Tracking id. | ||
*/ | ||
public TrackingId trackingId() { | ||
return new TrackingId(trackingId); | ||
} | ||
|
||
/** | ||
* @return Origin location. | ||
*/ | ||
public Location origin() { | ||
return origin; | ||
} | ||
|
||
/** | ||
* @return The delivery. Never null. | ||
*/ | ||
public Delivery delivery() { | ||
return delivery; | ||
} | ||
|
||
/** | ||
* @return The itinerary. Never null. | ||
*/ | ||
public Itinerary itinerary() { | ||
if (itinerary == null || itinerary.isEmpty()) { | ||
return Itinerary.EMPTY_ITINERARY; | ||
} | ||
return new Itinerary(itinerary); | ||
} | ||
|
||
/** | ||
* @return The route specification. | ||
*/ | ||
public RouteSpecification routeSpecification() { | ||
return routeSpecification; | ||
} | ||
|
||
/** | ||
* Specifies a new route for this cargo. | ||
* | ||
* @param routeSpecification route specification. | ||
*/ | ||
public void specifyNewRoute(final RouteSpecification routeSpecification) { | ||
Validate.notNull(routeSpecification, "Route specification is required"); | ||
|
||
this.routeSpecification = routeSpecification; | ||
Itinerary itineraryForRouting = this.itinerary != null && !this.itinerary.isEmpty() ? new Itinerary(this.itinerary) : null; | ||
// Handling consistency within the Cargo aggregate synchronously | ||
this.delivery = delivery.updateOnRouting(this.routeSpecification, itineraryForRouting); | ||
} | ||
|
||
/** | ||
* Attach a new itinerary to this cargo. | ||
* | ||
* @param itinerary an itinerary. May not be null. | ||
*/ | ||
public void assignToRoute(final Itinerary itinerary) { | ||
Validate.notNull(itinerary, "Itinerary is required for assignment"); | ||
|
||
this.itinerary = itinerary.legs(); | ||
// Handling consistency within the Cargo aggregate synchronously | ||
this.delivery = delivery.updateOnRouting(this.routeSpecification, itinerary); | ||
} | ||
|
||
/** | ||
* Updates all aspects of the cargo aggregate status | ||
* based on the current route specification, itinerary and handling of the cargo. | ||
* <p/> | ||
* 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. | ||
* <p/> | ||
* {@link RouteSpecification} and {@link Itinerary} are both inside the Cargo | ||
* aggregate, so changes to them cause the status to be updated <b>synchronously</b>, | ||
* but changes to the delivery history (when a cargo is handled) cause the status update | ||
* to happen <b>asynchronously</b> since {@link se.citerus.dddsample.domain.model.handling.HandlingEvent} is in a different aggregate. | ||
* | ||
* @param handlingHistory handling history | ||
*/ | ||
public void deriveDeliveryProgress(final HandlingHistory handlingHistory) { | ||
// Delivery is a value object, so we can simply discard the old one | ||
// and replace it with a new | ||
this.delivery = Delivery.derivedFrom(routeSpecification(), itinerary(), handlingHistory.filterOnCargo(new TrackingId(this.trackingId))); | ||
} | ||
|
||
@Override | ||
public boolean sameIdentityAs(final Cargo other) { | ||
return other != null && trackingId.equals(other.trackingId); | ||
} | ||
|
||
/** | ||
* @param object to compare | ||
* @return True if they have the same identity | ||
* @see #sameIdentityAs(Cargo) | ||
*/ | ||
@Override | ||
public boolean equals(final Object object) { | ||
if (this == object) return true; | ||
if (object == null || getClass() != object.getClass()) return false; | ||
|
||
final Cargo other = (Cargo) object; | ||
return sameIdentityAs(other); | ||
} | ||
|
||
/** | ||
* @return Hash code of tracking id. | ||
*/ | ||
@Override | ||
public int hashCode() { | ||
return trackingId.hashCode(); | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return trackingId; | ||
} | ||
|
||
|
||
} |
Oops, something went wrong.