Przeglądaj źródła

Included Patrik's specification pattern implementation

peter_backlund 18 lat temu
rodzic
commit
d7892ed38a

+ 0
- 7
dddsample/src/main/java/se/citerus/dddsample/domain/model/Specification.java Wyświetl plik

@@ -1,7 +0,0 @@
1
-package se.citerus.dddsample.domain.model;
2
-
3
-public interface Specification<T> {
4
-
5
-  boolean isSatisfiedBy(T t);
6
-    
7
-}

+ 3
- 3
dddsample/src/main/java/se/citerus/dddsample/domain/model/cargo/RouteSpecification.java Wyświetl plik

@@ -3,9 +3,9 @@ package se.citerus.dddsample.domain.model.cargo;
3 3
 import org.apache.commons.lang.Validate;
4 4
 import org.apache.commons.lang.builder.EqualsBuilder;
5 5
 import org.apache.commons.lang.builder.HashCodeBuilder;
6
-import se.citerus.dddsample.domain.model.Specification;
7 6
 import se.citerus.dddsample.domain.model.ValueObject;
8 7
 import se.citerus.dddsample.domain.model.location.Location;
8
+import se.citerus.dddsample.domain.shared.AbstractSpecification;
9 9
 
10 10
 import java.util.Date;
11 11
 
@@ -13,7 +13,7 @@ import java.util.Date;
13 13
  * Route specification.
14 14
  * 
15 15
  */
16
-public class RouteSpecification implements ValueObject<RouteSpecification>, Specification<Itinerary> {
16
+public class RouteSpecification extends AbstractSpecification<Itinerary> implements ValueObject<RouteSpecification> {
17 17
   private Location origin;
18 18
   private Location destination;
19 19
   private Date arrivalDeadline;
@@ -95,5 +95,5 @@ public class RouteSpecification implements ValueObject<RouteSpecification>, Spec
95 95
       append(this.arrivalDeadline).
96 96
       toHashCode();
97 97
   }
98
-  
98
+
99 99
 }

+ 35
- 0
dddsample/src/main/java/se/citerus/dddsample/domain/shared/AbstractSpecification.java Wyświetl plik

@@ -0,0 +1,35 @@
1
+package se.citerus.dddsample.domain.shared;
2
+
3
+
4
+/**
5
+ * Abstract base implementation of composite {@link Specification} with default
6
+ * implementations for {@code and}, {@code or} and {@code not}.
7
+ */
8
+public abstract class AbstractSpecification<T> implements Specification<T> {
9
+
10
+  /**
11
+   * {@inheritDoc}
12
+   */
13
+  public abstract boolean isSatisfiedBy(T t);
14
+
15
+  /**
16
+   * {@inheritDoc}
17
+   */
18
+  public Specification<T> and(final Specification<T> specification) {
19
+    return new AndSpecification<T>(this, specification);
20
+  }
21
+
22
+  /**
23
+   * {@inheritDoc}
24
+   */
25
+  public Specification<T> or(final Specification<T> specification) {
26
+    return new OrSpecification<T>(this, specification);
27
+  }
28
+
29
+  /**
30
+   * {@inheritDoc}
31
+   */
32
+  public Specification<T> not(final Specification<T> specification) {
33
+    return new NotSpecification<T>(specification);
34
+  }
35
+}

+ 28
- 0
dddsample/src/main/java/se/citerus/dddsample/domain/shared/AndSpecification.java Wyświetl plik

@@ -0,0 +1,28 @@
1
+package se.citerus.dddsample.domain.shared;
2
+
3
+/**
4
+ * AND specification, used to create a new specifcation that is the AND of two other specifications.
5
+ */
6
+public class AndSpecification<T> extends AbstractSpecification<T> {
7
+
8
+  private Specification<T> spec1;
9
+  private Specification<T> spec2;
10
+
11
+  /**
12
+   * Create a new AND specification based on two other spec.
13
+   *
14
+   * @param spec1 Specification one.
15
+   * @param spec2 Specification two.
16
+   */
17
+  public AndSpecification(final Specification<T> spec1, final Specification<T> spec2) {
18
+    this.spec1 = spec1;
19
+    this.spec2 = spec2;
20
+  }
21
+
22
+  /**
23
+   * {@inheritDoc}
24
+   */
25
+  public boolean isSatisfiedBy(final T t) {
26
+    return spec1.isSatisfiedBy(t) && spec2.isSatisfiedBy(t);
27
+  }
28
+}

+ 25
- 0
dddsample/src/main/java/se/citerus/dddsample/domain/shared/NotSpecification.java Wyświetl plik

@@ -0,0 +1,25 @@
1
+package se.citerus.dddsample.domain.shared;
2
+
3
+/**
4
+ * NOT decorator, used to create a new specifcation that is the inverse (NOT) of the given spec.
5
+ */
6
+public class NotSpecification<T> extends AbstractSpecification<T> {
7
+
8
+  private Specification<T> spec1;
9
+
10
+  /**
11
+   * Create a new NOT specification based on another spec.
12
+   *
13
+   * @param spec1 Specification instance to not.
14
+   */
15
+  public NotSpecification(final Specification<T> spec1) {
16
+    this.spec1 = spec1;
17
+  }
18
+
19
+  /**
20
+   * {@inheritDoc}
21
+   */
22
+  public boolean isSatisfiedBy(final T t) {
23
+    return !spec1.isSatisfiedBy(t);
24
+  }
25
+}

+ 28
- 0
dddsample/src/main/java/se/citerus/dddsample/domain/shared/OrSpecification.java Wyświetl plik

@@ -0,0 +1,28 @@
1
+package se.citerus.dddsample.domain.shared;
2
+
3
+/**
4
+ * OR specification, used to create a new specifcation that is the OR of two other specifications.
5
+ */
6
+public class OrSpecification<T> extends AbstractSpecification<T> {
7
+
8
+  private Specification<T> spec1;
9
+  private Specification<T> spec2;
10
+
11
+  /**
12
+   * Create a new OR specification based on two other spec.
13
+   *
14
+   * @param spec1 Specification one.
15
+   * @param spec2 Specification two.
16
+   */
17
+  public OrSpecification(final Specification<T> spec1, final Specification<T> spec2) {
18
+    this.spec1 = spec1;
19
+    this.spec2 = spec2;
20
+  }
21
+
22
+  /**
23
+   * {@inheritDoc}
24
+   */
25
+  public boolean isSatisfiedBy(final T t) {
26
+    return spec1.isSatisfiedBy(t) || spec2.isSatisfiedBy(t);
27
+  }
28
+}

+ 39
- 0
dddsample/src/main/java/se/citerus/dddsample/domain/shared/Specification.java Wyświetl plik

@@ -0,0 +1,39 @@
1
+package se.citerus.dddsample.domain.shared;
2
+
3
+/**
4
+ * Specificaiton interface.
5
+ * <p/>
6
+ * Use {@link se.citerus.dddsample.domain.shared.AbstractSpecification} as base for creating specifications, and
7
+ * only the method {@link #isSatisfiedBy(Object)} must be implemented.
8
+ */
9
+public interface Specification<T> {
10
+
11
+  /**
12
+   * Check if {@code t} is satisfied by the specification.
13
+   *
14
+   * @param t Object to test.
15
+   * @return {@code true} if {@code t} satisfies the specification.
16
+   */
17
+  boolean isSatisfiedBy(T t);
18
+
19
+  /**
20
+   * Create a new specification that is the AND operation of {@code this} specification and another specification.
21
+   * @param specification Specification to AND.
22
+   * @return A new specification.
23
+   */
24
+  Specification<T> and(Specification<T> specification);
25
+
26
+  /**
27
+   * Create a new specification that is the OR operation of {@code this} specification and another specification.
28
+   * @param specification Specification to OR.
29
+   * @return A new specification.
30
+   */
31
+  Specification<T> or(Specification<T> specification);
32
+
33
+  /**
34
+   * Create a new specification that is the NOT operation of {@code this} specification.
35
+   * @param specification Specification to NOT.
36
+   * @return A new specification.
37
+   */
38
+  Specification<T> not(Specification<T> specification);
39
+}