Selaa lähdekoodia

Refactored identities.

Entities have the method sameValueAs(otherEntity)
Value Objects have the method sameIdentiyAs(otherValueObject)
Events have the method sameEventAs(otherEvent)
Patrik Fredriksson 18 vuotta sitten
vanhempi
commit
44288c0b30

+ 15
- 1
dddsample/src/main/java/se/citerus/dddsample/domain/Cargo.java Näytä tiedosto

@@ -121,6 +121,20 @@ public class Cargo {
121 121
   }
122 122
 
123 123
   /**
124
+   * Entities compare by identity, therefore the trackingId field is the only basis of comparison. For persistence we
125
+   * have an id field, but it is not used for identiy comparison.
126
+   *
127
+   * Compare this behavior to the value object {@link se.citerus.dddsample.domain.Leg#sameValueAs(Leg)}
128
+   *
129
+   * @param other The other cargo.
130
+   * @return <code>true</code> if the given cargo's and this cargos's trackingId is the same, regardles of other
131
+   * attributes.
132
+   */
133
+  private boolean sameIdentityAs(Cargo other) {
134
+    return trackingId.equals(other.trackingId);
135
+  }
136
+
137
+  /**
124 138
    * @param object to compare
125 139
    * @return True if tracking ids are equal.
126 140
    */
@@ -130,7 +144,7 @@ public class Cargo {
130 144
       return false;
131 145
     }
132 146
     Cargo other = (Cargo) object;
133
-    return trackingId.equals(other.trackingId);
147
+    return sameIdentityAs(other);
134 148
   }
135 149
 
136 150
   /**

+ 39
- 2
dddsample/src/main/java/se/citerus/dddsample/domain/CarrierMovement.java Näytä tiedosto

@@ -5,7 +5,6 @@ import javax.persistence.*;
5 5
 
6 6
 /**
7 7
  * A carrier movement is a vessel voyage from one location to another.
8
- *
9 8
  */
10 9
 @Entity
11 10
 public class CarrierMovement {
@@ -42,6 +41,44 @@ public class CarrierMovement {
42 41
   }
43 42
 
44 43
   // Needed by Hibernate
45
-  CarrierMovement() {}
44
+  CarrierMovement() {
45
+  }
46
+
47
+
48
+  /**
49
+   * Entities compare by identity, therefore the carrierMovementId field is the only basis of comparison. For
50
+   * persistence we have an id field, but it is not used for identiy comparison.
51
+   * <p/>
52
+   * Compare this behavior to the value object {@link se.citerus.dddsample.domain.Leg#sameValueAs(Leg)}
53
+   *
54
+   * @param other The other cargo.
55
+   * @return <code>true</code> if the given carrier movement's and this carrier movement's carrierId is the same,
56
+   *         regardles of other attributes.
57
+   */
58
+  public boolean sameIdentityAs(CarrierMovement other) {
59
+    if (carrierMovementId != null ? !carrierMovementId.equals(other.carrierMovementId) : other.carrierMovementId != null)
60
+      return false;
61
+
62
+    return true;
63
+  }
46 64
 
65
+  @Override
66
+  public boolean equals(Object o) {
67
+    if (this == o) return true;
68
+    if (o == null || getClass() != o.getClass()) return false;
69
+
70
+    CarrierMovement that = (CarrierMovement) o;
71
+
72
+    return sameIdentityAs(that);
73
+  }
74
+
75
+  @Override
76
+  public int hashCode() {
77
+    int result;
78
+    result = (id != null ? id.hashCode() : 0);
79
+    result = 31 * result + (carrierMovementId != null ? carrierMovementId.hashCode() : 0);
80
+    result = 31 * result + (from != null ? from.hashCode() : 0);
81
+    result = 31 * result + (to != null ? to.hashCode() : 0);
82
+    return result;
83
+  }
47 84
 }

+ 2
- 0
dddsample/src/main/java/se/citerus/dddsample/domain/DeliveryHistory.java Näytä tiedosto

@@ -7,6 +7,8 @@ import java.util.*;
7 7
 
8 8
 /**
9 9
  * The delivery history of a cargo.
10
+ *
11
+ * Is this an entiy or a value object?
10 12
  */
11 13
 public class DeliveryHistory {
12 14
 

+ 37
- 36
dddsample/src/main/java/se/citerus/dddsample/domain/HandlingEvent.java Näytä tiedosto

@@ -1,7 +1,5 @@
1 1
 package se.citerus.dddsample.domain;
2 2
 
3
-import org.apache.commons.lang.builder.HashCodeBuilder;
4
-
5 3
 import javax.persistence.*;
6 4
 import java.util.Comparator;
7 5
 import java.util.Date;
@@ -80,9 +78,9 @@ public class HandlingEvent {
80 78
    * Constructor for events that do not have a carrier movement associated.
81 79
    *
82 80
    * @param cargo            cargo
83
-   * @param completionTime   completion time
84
-   * @param registrationTime registration time
85
-   * @param type             type of event. Legal values are CLAIM, RECIEVE and CUSTOMS
81
+   * @param completionTime   completion time, the reported time that the event actually happened (e.g. the receive took place).
82
+   * @param registrationTime registration time, the time the message is received
83
+   * @param type             type of event. Legal values are CLAIM, RECEIVE and CUSTOMS
86 84
    * @param location         where the event took place
87 85
    */
88 86
   public HandlingEvent(Cargo cargo, Date completionTime, Date registrationTime, Type type, Location location) {
@@ -102,8 +100,8 @@ public class HandlingEvent {
102 100
    * is the end point.
103 101
    *
104 102
    * @param cargo            cargo
105
-   * @param completionTime   completion time
106
-   * @param registrationTime registration time
103
+   * @param completionTime   completion time, the reported time that the event actually happened (e.g. the receive took place).
104
+   * @param registrationTime registration time, the time the message is received
107 105
    * @param type             type of event. Legal values are LOAD and UNLOAD
108 106
    * @param location         where the event took place
109 107
    * @param carrierMovement  carrier movement.
@@ -116,7 +114,6 @@ public class HandlingEvent {
116 114
     this.location = location;
117 115
     this.carrierMovement = carrierMovement;
118 116
 
119
-
120 117
     validateType();
121 118
   }
122 119
 
@@ -149,42 +146,46 @@ public class HandlingEvent {
149 146
     return this.cargo;
150 147
   }
151 148
 
149
+  public boolean equals(Object o) {
150
+    if (this == o) return true;
151
+    if (o == null || getClass() != o.getClass()) return false;
152
+
153
+    HandlingEvent event = (HandlingEvent) o;
154
+
155
+    return sameEventAs(event);
156
+  }
157
+
152 158
   /**
153
-   * @param object to compare
154
-   * @return True if location, completion time and type are equal.
159
+   * Events compare by the attributes that identify the underlying event as opposed to the report of the event.
160
+   * Therefore the completion time is part of the comparison but not the registration time.
161
+   *
162
+   * Compare this behavior to the value object {@link se.citerus.dddsample.domain.Leg#sameValueAs(Leg)}
163
+   * Compare this behavior to the entity {@link se.citerus.dddsample.domain.Cargo#sameIdentityAs(Cargo)}
164
+   *
165
+   * @param other The other hanling event.
166
+   * @return <code>true</code> if the given handling event and this event are regarded as the same.
155 167
    */
156
-  @Override
157
-  public boolean equals(Object object) {
158
-    if (object == null) {
168
+  public boolean sameEventAs(HandlingEvent other) {
169
+    if (cargo != null ? !cargo.equals(other.cargo) : other.cargo != null) return false;
170
+    if (carrierMovement != null ? !carrierMovement.equals(other.carrierMovement) : other.carrierMovement != null)
159 171
       return false;
160
-    }
161
-    if (!(object instanceof HandlingEvent)) {
172
+    if (completionTime != null ? !completionTime.equals(other.completionTime) : other.completionTime != null)
162 173
       return false;
163
-    }
164
-    HandlingEvent other = (HandlingEvent) object;
165
-    return this.location.equals(other.location) &&
166
-            this.completionTime.equals(other.completionTime) &&
167
-            this.type.equals(other.type);
174
+    if (location != null ? !location.equals(other.location) : other.location != null) return false;
175
+    if (type != other.type) return false;
176
+
177
+    return true;
168 178
   }
169 179
 
170
-  /**
171
-   * @return Hash code calculated from the same properties as equals().
172
-   */
173 180
   @Override
174 181
   public int hashCode() {
175
-    return new HashCodeBuilder(7, 39).
176
-            append(this.location).
177
-            append(this.completionTime).
178
-            append(this.type).
179
-            toHashCode();
180
-  }
181
-
182
-  /**
183
-   * @param other to compare
184
-   * @return True if the ids are equal.
185
-   */
186
-  public boolean sameIdentityAs(HandlingEvent other) {
187
-    return other != null && id.equals(other.id);
182
+    int result;
183
+    result = (type != null ? type.hashCode() : 0);
184
+    result = 31 * result + (carrierMovement != null ? carrierMovement.hashCode() : 0);
185
+    result = 31 * result + (location != null ? location.hashCode() : 0);
186
+    result = 31 * result + (completionTime != null ? completionTime.hashCode() : 0);
187
+    result = 31 * result + (cargo != null ? cargo.hashCode() : 0);
188
+    return result;
188 189
   }
189 190
 
190 191
   /**

+ 21
- 1
dddsample/src/main/java/se/citerus/dddsample/domain/Itinerary.java Näytä tiedosto

@@ -75,8 +75,28 @@ public class Itinerary {
75 75
       return (leg.to().equals(event.location()));
76 76
     }
77 77
 
78
-
79 78
     //HandlingEvent.Type.CUSTOMS;
80 79
     return true;
81 80
   }
81
+
82
+  private boolean sameValueAs(Itinerary other) {
83
+    if (!legs.equals(other.legs)) return false;
84
+
85
+    return true;
86
+  }
87
+
88
+  @Override
89
+  public boolean equals(Object o) {
90
+    if (this == o) return true;
91
+    if (o == null || getClass() != o.getClass()) return false;
92
+
93
+    Itinerary itinerary = (Itinerary) o;
94
+
95
+    return sameValueAs(itinerary);
96
+  }
97
+
98
+  @Override
99
+  public int hashCode() {
100
+    return legs.hashCode();
101
+  }
82 102
 }

+ 38
- 0
dddsample/src/main/java/se/citerus/dddsample/domain/Leg.java Näytä tiedosto

@@ -22,4 +22,42 @@ public class Leg {
22 22
   public CarrierMovementId carrierMovementId() {
23 23
     return carrierMovementId;
24 24
   }
25
+
26
+  
27
+  /**
28
+   * Value objects compare by value, therefore the id field which must be part of the class in order to support
29
+   * persistence is ignored in the comparison.
30
+   * <p/>
31
+   * Compare this behavior to the entity {@link se.citerus.dddsample.domain.Cargo#sameIdentityAs(Cargo)}
32
+   *
33
+   * @param other The other leg.
34
+   * @return <code>true</code> if the given leg's and this leg's attributes are the same.
35
+   */
36
+  public boolean sameValueAs(Leg other) {
37
+    if (carrierMovementId != null ? !carrierMovementId.equals(other.carrierMovementId) : other.carrierMovementId != null)
38
+      return false;
39
+    if (from != null ? !from.equals(other.from) : other.from != null) return false;
40
+    if (to != null ? !to.equals(other.to) : other.to != null) return false;
41
+
42
+    return true;
43
+  }
44
+
45
+  @Override
46
+  public boolean equals(Object o) {
47
+    if (this == o) return true;
48
+    if (o == null || getClass() != o.getClass()) return false;
49
+
50
+    Leg leg = (Leg) o;
51
+
52
+    return sameValueAs(leg);
53
+  }
54
+
55
+  @Override
56
+  public int hashCode() {
57
+    int result;
58
+    result = (carrierMovementId != null ? carrierMovementId.hashCode() : 0);
59
+    result = 31 * result + (from != null ? from.hashCode() : 0);
60
+    result = 31 * result + (to != null ? to.hashCode() : 0);
61
+    return result;
62
+  }
25 63
 }

+ 19
- 4
dddsample/src/main/java/se/citerus/dddsample/domain/Location.java Näytä tiedosto

@@ -23,12 +23,12 @@ public class Location {
23 23
    * Special Location object that marks an unknown location.
24 24
    */
25 25
   public static final Location UNKNOWN = new Location(
26
-    new UnLocode("XX","XXX"), "Unknown location"
26
+     new UnLocode("XX", "XXX"), "Unknown location"
27 27
   );
28 28
 
29 29
   /**
30 30
    * @param unLocode UN Locode
31
-   * @param name location name
31
+   * @param name     location name
32 32
    * @throws IllegalArgumentException if the UN Locode or name is null
33 33
    */
34 34
   public Location(UnLocode unLocode, String name) {
@@ -57,7 +57,7 @@ public class Location {
57 57
 
58 58
   /**
59 59
    * @param object to compare
60
-   * @return True iff UN locodes are equal.
60
+   * @return Since this is an entiy this will be true iff UN locodes are equal.
61 61
    */
62 62
   @Override
63 63
   public boolean equals(Object object) {
@@ -71,6 +71,20 @@ public class Location {
71 71
       return false;
72 72
     }
73 73
     Location other = (Location) object;
74
+    return sameIdentityAs(other);
75
+  }
76
+
77
+  /**
78
+   * Entities compare by identity, therefore the unLocode field is the only basis of comparison. For persistence we
79
+   * have an id field, but it is not used for identiy comparison.
80
+   *
81
+   * Compare this behavior to the value object {@link se.citerus.dddsample.domain.Leg#sameValueAs(Leg)}
82
+   *
83
+   * @param other The other location.
84
+   * @return <code>true</code> if the given location's and this locations's unLocode is the same, regardles of other
85
+   * attributes.
86
+   */
87
+  public boolean sameIdentityAs(Location other) {
74 88
     return this.unLocode.equals(other.unLocode);
75 89
   }
76 90
 
@@ -91,6 +105,7 @@ public class Location {
91 105
   }
92 106
 
93 107
   // Needed by Hibernate
94
-  Location() {}
108
+  Location() {
109
+  }
95 110
 
96 111
 }

+ 2
- 1
dddsample/src/main/java/se/citerus/dddsample/domain/TrackingId.java Näytä tiedosto

@@ -9,7 +9,8 @@ import javax.persistence.Embeddable;
9 9
 
10 10
 /**
11 11
  * Identifies a particular cargo.
12
- *
12
+ * <p>
13
+ * Make sure to put a constraint in the database to make sure TrackingId is unique.
13 14
  */
14 15
 @Embeddable
15 16
 public class TrackingId {