Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public TrackingId bookNewCargo(final UnLocode originUnLocode,
Cargo cargo = cargoFactory.createCargo(originUnLocode, destinationUnLocode, arrivalDeadline);

cargoRepository.store(cargo);
logger.info("Booked new cargo with tracking id {}", cargo.trackingId().idString());
logger.info("Booked new cargo with tracking id {}", cargo.trackingId().id());

return cargo.trackingId();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public Cargo(final TrackingId trackingId, final RouteSpecification routeSpecific
Objects.requireNonNull(trackingId, "Tracking ID is required");
Objects.requireNonNull(routeSpecification, "Route specification is required");

this.trackingId = trackingId.idString();
this.trackingId = trackingId.id();
// 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();
Expand All @@ -87,7 +87,7 @@ public Cargo(final TrackingId trackingId, final RouteSpecification routeSpecific
public Cargo(TrackingId trackingId, RouteSpecification routeSpecification, Itinerary itinerary) {
Objects.requireNonNull(trackingId, "Tracking ID is required");
Objects.requireNonNull(routeSpecification, "Route specification is required");
this.trackingId = trackingId.idString();
this.trackingId = trackingId.id();
this.origin = routeSpecification.origin();
this.routeSpecification = routeSpecification;
this.itinerary = itinerary.legs();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ private RoutingStatus calculateRoutingStatus(Itinerary itinerary, RouteSpecifica

private boolean calculateUnloadedAtDestination(RouteSpecification routeSpecification) {
return lastEvent != null &&
HandlingEvent.Type.UNLOAD.sameValueAs(lastEvent.type()) &&
HandlingEvent.Type.UNLOAD == lastEvent.type() &&
routeSpecification.destination().sameIdentityAs(lastEvent.location());
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,8 @@
package se.citerus.dddsample.domain.model.cargo;

import se.citerus.dddsample.domain.shared.ValueObject;

/**
* Routing status.
*/
public enum RoutingStatus implements ValueObject<RoutingStatus> {
NOT_ROUTED, ROUTED, MISROUTED;

@Override
public boolean sameValueAs(final RoutingStatus other) {
return this.equals(other);
}

public enum RoutingStatus {
NOT_ROUTED, ROUTED, MISROUTED
}
Original file line number Diff line number Diff line change
@@ -1,62 +1,18 @@
package se.citerus.dddsample.domain.model.cargo;

import org.apache.commons.lang3.Validate;
import se.citerus.dddsample.domain.shared.ValueObject;

import java.util.Objects;

/**
* Uniquely identifies a particular cargo. Automatically generated by the application.
*
*/
public final class TrackingId implements ValueObject<TrackingId> {
public record TrackingId(String id) {

private String id;

/**
* Constructor.
*
* @param id Id string.
*/
public TrackingId(final String id) {
public TrackingId {
Objects.requireNonNull(id);
Validate.notEmpty(id);
this.id = id;
}

/**
* @return String representation of this tracking id.
*/
public String idString() {
return id;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

TrackingId other = (TrackingId) o;

return sameValueAs(other);
}

@Override
public int hashCode() {
return id.hashCode();
}

@Override
public boolean sameValueAs(TrackingId other) {
return other != null && this.id.equals(other.id);
}

@Override
public String toString() {
return id;
}

TrackingId() {
// Needed by Hibernate
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,8 @@
package se.citerus.dddsample.domain.model.cargo;

import se.citerus.dddsample.domain.shared.ValueObject;

/**
* Represents the different transport statuses for a cargo.
*/
public enum TransportStatus implements ValueObject<TransportStatus> {
NOT_RECEIVED, IN_PORT, ONBOARD_CARRIER, CLAIMED, UNKNOWN;

@Override
public boolean sameValueAs(final TransportStatus other) {
return this.equals(other);
}
public enum TransportStatus {
NOT_RECEIVED, IN_PORT, ONBOARD_CARRIER, CLAIMED, UNKNOWN
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import se.citerus.dddsample.domain.model.location.Location;
import se.citerus.dddsample.domain.model.voyage.Voyage;
import se.citerus.dddsample.domain.shared.DomainEvent;
import se.citerus.dddsample.domain.shared.ValueObject;

import java.time.Instant;
import java.util.Objects;
Expand Down Expand Up @@ -62,7 +61,7 @@ public final class HandlingEvent implements DomainEvent<HandlingEvent> {
* Handling event type. Either requires or prohibits a carrier movement
* association, it's never optional.
*/
public enum Type implements ValueObject<Type> {
public enum Type {
LOAD(true),
UNLOAD(true),
RECEIVE(false),
Expand Down Expand Up @@ -94,11 +93,6 @@ public boolean prohibitsVoyage() {
return !requiresVoyage();
}

@Override
public boolean sameValueAs(Type other) {
return this.equals(other);
}

}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,18 @@
package se.citerus.dddsample.domain.model.handling;

import se.citerus.dddsample.domain.model.cargo.TrackingId;
import se.citerus.dddsample.domain.shared.ValueObject;

import java.util.*;
import java.util.stream.Collectors;

/**
* The handling history of a cargo.
*/
public class HandlingHistory implements ValueObject<HandlingHistory> {

private final List<HandlingEvent> handlingEvents;
public record HandlingHistory(List<HandlingEvent> handlingEvents) {

public static final HandlingHistory EMPTY = new HandlingHistory(Collections.<HandlingEvent>emptyList());

public HandlingHistory(Collection<HandlingEvent> handlingEvents) {
public HandlingHistory(List<HandlingEvent> handlingEvents) {
Objects.requireNonNull(handlingEvents, "Handling events are required");

this.handlingEvents = new ArrayList<>(handlingEvents);
Expand Down Expand Up @@ -51,30 +48,11 @@ public HandlingEvent mostRecentlyCompletedEvent() {
*/
public HandlingHistory filterOnCargo(TrackingId trackingId) {
List<HandlingEvent> events = handlingEvents.stream()
.filter(he -> he.cargo().trackingId().sameValueAs(trackingId))
.filter(he -> he.cargo().trackingId().equals(trackingId))
.collect(Collectors.toList());
return new HandlingHistory(events);
}

@Override
public 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;

final HandlingHistory other = (HandlingHistory) o;
return sameValueAs(other);
}

@Override
public int hashCode() {
return handlingEvents.hashCode();
}

private static final Comparator<HandlingEvent> BY_COMPLETION_TIME_COMPARATOR =
Comparator.comparing(HandlingEvent::completionTime);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@ public UnknownCargoException(final TrackingId trackingId) {
*/
@Override
public String getMessage() {
return "No cargo with tracking id " + trackingId.idString() + " exists in the system";
return "No cargo with tracking id " + trackingId.id() + " exists in the system";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ public UnknownLocationException(final UnLocode unlocode) {

@Override
public String getMessage() {
return "No location with UN locode " + unlocode.idString() + " exists in the system";
return "No location with UN locode " + unlocode.unlocode() + " exists in the system";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@ public UnknownVoyageException(VoyageNumber voyageNumber) {

@Override
public String getMessage() {
return "No voyage with number " + voyageNumber.idString() + " exists in the system";
return "No voyage with number " + voyageNumber.number() + " exists in the system";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public Location(final UnLocode unLocode, final String name) {
Objects.requireNonNull(unLocode);
Objects.requireNonNull(name);

this.unlocode = unLocode.idString();
this.unlocode = unLocode.unlocode();
this.name = name;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,72 +1,26 @@
package se.citerus.dddsample.domain.model.location;

import org.apache.commons.lang3.Validate;
import se.citerus.dddsample.domain.shared.ValueObject;

import java.util.Objects;
import java.util.regex.Pattern;

/**
* United nations location code.
*
* http://www.unece.org/cefact/locode/
* http://www.unece.org/cefact/locode/DocColumnDescription.htm#LOCODE
*/
public final class UnLocode implements ValueObject<UnLocode> {

private String unlocode;

// Country code is exactly two letters.
// Location code is usually three letters, but may contain the numbers 2-9 as well
private static final Pattern VALID_PATTERN = Pattern.compile("[a-zA-Z]{2}[a-zA-Z2-9]{3}");

/**
* Constructor.
*
* @param countryAndLocation Location string.
*/
public UnLocode(final String countryAndLocation) {
Objects.requireNonNull(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 idString() {
return unlocode;
}

@Override
public boolean equals(final 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();
}

@Override
public boolean sameValueAs(UnLocode other) {
return other != null && this.unlocode.equals(other.unlocode);
}

@Override
public String toString() {
return idString();
}

UnLocode() {
// Needed by Hibernate
}

}
package se.citerus.dddsample.domain.model.location;

import org.apache.commons.lang3.Validate;

import java.util.Objects;
import java.util.regex.Pattern;

/**
* United nations location code.
*
* http://www.unece.org/cefact/locode/
* http://www.unece.org/cefact/locode/DocColumnDescription.htm#LOCODE
*/
public record UnLocode(String unlocode) {

private static final Pattern VALID_PATTERN = Pattern.compile("[a-zA-Z]{2}[a-zA-Z2-9]{3}");

public UnLocode(String unlocode) {
Objects.requireNonNull(unlocode, "Country and location may not be null");
Validate.isTrue(VALID_PATTERN.matcher(unlocode).matches(),
unlocode + " is not a valid UN/LOCODE (does not match pattern)");

this.unlocode = unlocode.toUpperCase();
}

}
Loading