1   package se.citerus.dddsample.domain.model.handling;
2   
3   import org.apache.commons.lang.Validate;
4   import org.apache.commons.lang.builder.EqualsBuilder;
5   import org.apache.commons.lang.builder.HashCodeBuilder;
6   import se.citerus.dddsample.domain.model.cargo.Cargo;
7   import se.citerus.dddsample.domain.model.location.Location;
8   import se.citerus.dddsample.domain.model.voyage.Voyage;
9   import se.citerus.dddsample.domain.shared.DomainEvent;
10  import se.citerus.dddsample.domain.shared.DomainObjectUtils;
11  import se.citerus.dddsample.domain.shared.ValueObject;
12  
13  import java.util.Date;
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  public final class HandlingEvent implements DomainEvent<HandlingEvent> {
32  
33    private Type type;
34    private Voyage voyage;
35    private Location location;
36    private Date completionTime;
37    private Date registrationTime;
38    private Cargo cargo;
39  
40    
41  
42  
43  
44    public enum Type implements ValueObject<Type> {
45      LOAD(true),
46      UNLOAD(true),
47      RECEIVE(false),
48      CLAIM(false),
49      CUSTOMS(false);
50  
51      private final boolean voyageRequired;
52  
53      
54  
55  
56  
57  
58      private Type(final boolean voyageRequired) {
59        this.voyageRequired = voyageRequired;
60      }
61  
62      
63  
64  
65      public boolean requiresVoyage() {
66        return voyageRequired;
67      }
68  
69      
70  
71  
72      public boolean prohibitsVoyage() {
73        return !requiresVoyage();
74      }
75  
76      @Override
77      public boolean sameValueAs(Type other) {
78        return other != null && this.equals(other);
79      }
80  
81    }
82  
83    
84  
85  
86  
87  
88  
89  
90  
91    public HandlingEvent(final Cargo cargo,
92                         final Date completionTime,
93                         final Date registrationTime,
94                         final Type type,
95                         final Location location,
96                         final Voyage voyage) {
97      Validate.notNull(cargo, "Cargo is required");
98      Validate.notNull(completionTime, "Completion time is required");
99      Validate.notNull(registrationTime, "Registration time is required");
100     Validate.notNull(type, "Handling event type is required");
101     Validate.notNull(location, "Location is required");
102     Validate.notNull(voyage, "Voyage is required");
103 
104     if (type.prohibitsVoyage()) {
105       throw new IllegalArgumentException("Voyage is not allowed with event type " + type);
106     }
107 
108     this.voyage = voyage;
109     this.completionTime = (Date) completionTime.clone();
110     this.registrationTime = (Date) registrationTime.clone();
111     this.type = type;
112     this.location = location;
113     this.cargo = cargo;
114   }
115 
116   
117 
118 
119 
120 
121 
122 
123   public HandlingEvent(final Cargo cargo,
124                        final Date completionTime,
125                        final Date registrationTime,
126                        final Type type,
127                        final Location location) {
128     Validate.notNull(cargo, "Cargo is required");
129     Validate.notNull(completionTime, "Completion time is required");
130     Validate.notNull(registrationTime, "Registration time is required");
131     Validate.notNull(type, "Handling event type is required");
132     Validate.notNull(location, "Location is required");
133 
134     if (type.requiresVoyage()) {
135       throw new IllegalArgumentException("Voyage is required for event type " + type);
136     }
137 
138     this.completionTime = (Date) completionTime.clone();
139     this.registrationTime = (Date) registrationTime.clone();
140     this.type = type;
141     this.location = location;
142     this.cargo = cargo;
143     this.voyage = null;
144   }
145 
146   public Type type() {
147     return this.type;
148   }
149 
150   public Voyage voyage() {
151     return DomainObjectUtils.nullSafe(this.voyage, Voyage.NONE);
152   }
153 
154   public Date completionTime() {
155     return new Date(this.completionTime.getTime());
156   }
157 
158   public Date registrationTime() {
159     return new Date(this.registrationTime.getTime());
160   }
161 
162   public Location location() {
163     return this.location;
164   }
165 
166   public Cargo cargo() {
167     return this.cargo;
168   }
169 
170   @Override
171   public boolean equals(final Object o) {
172     if (this == o) return true;
173     if (o == null || getClass() != o.getClass()) return false;
174 
175     final HandlingEvent event = (HandlingEvent) o;
176 
177     return sameEventAs(event);
178   }
179 
180   @Override
181   public boolean sameEventAs(final HandlingEvent other) {
182     return other != null && new EqualsBuilder().
183       append(this.cargo, other.cargo).
184       append(this.voyage, other.voyage).
185       append(this.completionTime, other.completionTime).
186       append(this.location, other.location).
187       append(this.type, other.type).
188       isEquals();
189   }
190 
191   @Override
192   public int hashCode() {
193     return new HashCodeBuilder().
194       append(cargo).
195       append(voyage).
196       append(completionTime).
197       append(location).
198       append(type).
199       toHashCode();
200   }
201 
202   @Override
203   public String toString() {
204     final StringBuilder builder = new StringBuilder("\n--- Handling event ---\n").
205       append("Cargo: ").append(cargo.trackingId()).append("\n").
206       append("Type: ").append(type).append("\n").
207       append("Location: ").append(location.name()).append("\n").
208       append("Completed on: ").append(completionTime).append("\n").
209       append("Registered on: ").append(registrationTime).append("\n");
210     
211     if (voyage != null) {
212       builder.append("Voyage: ").append(voyage.voyageNumber()).append("\n");
213     }
214 
215     return builder.toString();
216   }
217 
218   HandlingEvent() {
219     
220   }
221 
222 
223   
224   private Long id;
225 
226 }