1   /*
2    * Copyright 2006-2010 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package net.sourceforge.domian.specification.example;
17  
18  
19  import java.io.File;
20  import java.util.ArrayList;
21  import java.util.Calendar;
22  import java.util.List;
23  import java.util.StringTokenizer;
24  
25  import org.junit.Assert;
26  import org.junit.Test;
27  
28  import static org.apache.commons.lang.StringUtils.isNotBlank;
29  
30  import net.sourceforge.domian.specification.CompositeSpecification;
31  import net.sourceforge.domian.specification.Specification;
32  import static net.sourceforge.domian.specification.SpecificationFactory.all;
33  import static net.sourceforge.domian.specification.SpecificationFactory.both;
34  import static net.sourceforge.domian.specification.SpecificationFactory.createSpecificationFor;
35  import static net.sourceforge.domian.specification.SpecificationFactory.is;
36  import static net.sourceforge.domian.specification.SpecificationFactory.isAfter;
37  import static net.sourceforge.domian.specification.SpecificationFactory.isEitherOf;
38  import static net.sourceforge.domian.specification.SpecificationFactory.isGreaterThan;
39  import static net.sourceforge.domian.specification.SpecificationFactory.isGreaterThanOrEqualTo;
40  import static net.sourceforge.domian.specification.SpecificationFactory.isLessThan;
41  import static net.sourceforge.domian.specification.SpecificationFactory.isLessThanOrEqualTo;
42  import static net.sourceforge.domian.specification.SpecificationFactory.isTrue;
43  import static net.sourceforge.domian.specification.SpecificationFactory.like;
44  import static net.sourceforge.domian.specification.SpecificationFactory.matchesWildcardExpression;
45  import static net.sourceforge.domian.specification.SpecificationFactory.shouldBe;
46  import static net.sourceforge.domian.specification.SpecificationFactory.shouldBeBoth;
47  import static net.sourceforge.domian.util.DateUtils.getTime;
48  import static org.junit.Assert.assertEquals;
49  import static org.junit.Assert.assertFalse;
50  import static org.junit.Assert.assertNotNull;
51  import static org.junit.Assert.assertTrue;
52  
53  import junit.framework.TestCase;
54  
55  
56  public class ExternalExamplesTest {
57  
58      /* Example from the original Specifications pattern article */
59      @Test
60      public void testCargoExample() {
61          final ShippingContainer containerWithTempLowerThanMinus3AndIsSanitaryForFood = new ShippingContainer(-4, true);
62          final ShippingContainer containerWithTempLowerThanMinus3ButNotSanitaryForFood = new ShippingContainer(-4, false);
63          final ShippingContainer containerWithTempHigherThanMinus4AndIsSanitaryForFood = new ShippingContainer(-3, true);
64          final ShippingContainer containerWithTempHigherThanMinus4ButNotSanitaryForFood = new ShippingContainer(10, false);
65  
66          // Direct construction of composite specification
67          Specification<ShippingContainer> containerSpec =
68                  createSpecificationFor(ShippingContainer.class)
69                          .where("lowerBoundTemperatureCapacity", isLessThanOrEqualTo(-4))
70                          .and("sanitaryForFood", isTrue());
71  
72          assertTrue(containerSpec.isSatisfiedBy(containerWithTempLowerThanMinus3AndIsSanitaryForFood));
73          assertFalse(containerSpec.isSatisfiedBy(containerWithTempLowerThanMinus3ButNotSanitaryForFood));
74          assertFalse(containerSpec.isSatisfiedBy(containerWithTempHigherThanMinus4AndIsSanitaryForFood));
75          assertFalse(containerSpec.isSatisfiedBy(containerWithTempHigherThanMinus4ButNotSanitaryForFood));
76  
77          // Creating two leaf specification and then using them to construct a composite specification
78          final Specification<ShippingContainer> coldEnough = createSpecificationFor(ShippingContainer.class).where("lowerBoundTemperatureCapacity", isLessThanOrEqualTo(-4));
79          final Specification<ShippingContainer> cleanEnough = createSpecificationFor(ShippingContainer.class).where("sanitaryForFood", isTrue());
80          containerSpec = shouldBeBoth(coldEnough, cleanEnough);
81  
82          assertTrue(containerSpec.isSatisfiedBy(containerWithTempLowerThanMinus3AndIsSanitaryForFood));
83          assertFalse(containerSpec.isSatisfiedBy(containerWithTempLowerThanMinus3ButNotSanitaryForFood));
84          assertFalse(containerSpec.isSatisfiedBy(containerWithTempHigherThanMinus4AndIsSanitaryForFood));
85          assertFalse(containerSpec.isSatisfiedBy(containerWithTempHigherThanMinus4ButNotSanitaryForFood));
86  
87          // Maybe more readable than the one above
88          containerSpec = shouldBe(coldEnough).and(cleanEnough);
89  
90          assertTrue(containerSpec.isSatisfiedBy(containerWithTempLowerThanMinus3AndIsSanitaryForFood));
91          assertFalse(containerSpec.isSatisfiedBy(containerWithTempLowerThanMinus3ButNotSanitaryForFood));
92          assertFalse(containerSpec.isSatisfiedBy(containerWithTempHigherThanMinus4AndIsSanitaryForFood));
93          assertFalse(containerSpec.isSatisfiedBy(containerWithTempHigherThanMinus4ButNotSanitaryForFood));
94      }
95  
96  
97      /* Example from JoSQL (http://josql.sourceforge.net/manual/introduction.html)" target="alexandria_uri">http://josql.sourceforge.net/manual/introduction.html) */
98      @Test
99      public void testStateRetrievalViaMethods() {
100         /*
101         SELECT   *
102         FROM     java.io.File
103         WHERE    (name LIKE "%.html"
104                  OR
105                  name LIKE "%.txt"
106                  OR
107                  name LIKE "%.xml"
108                  )
109         AND      lastModified BETWEEN toDate('01-1-2004') AND toDate('31-1-2004')
110         AND      length >= 10000
111         ORDER BY lastModified DESC, name, length DESC
112         */
113 
114         //Specification<Date> jan2004 = is(afterOrAtTheSameTimeAs(getTime(2004, 1, 1))).and(before(getTime(2004, 2, 1)));
115         //Specification<Date> jan2004 = is(afterOrAtTheSameTimeAs("2004-01-01", "yyyy-MM-dd")).and(before("2004-02-01", "yyyy-MM-dd"));
116         //Specification<Date> jan2004 = is(afterOrAtTheSameTimeAs("2004-01-01")).and(before("2004-02-01"));
117 
118         // Hmm, doesn't look good, but hey, it's a Long type spec and not Date, so...
119         Specification<Long> jan2004 = both(isGreaterThanOrEqualTo(getTime(2004, 1, 1).getTime())).and(isLessThan(getTime(2004, 2, 1).getTime()));
120         CompositeSpecification<File> spec = all(File.class)
121                 /*
122                 .where("name", matchesWildcardExpression("*.html"))
123                 .or("name", matchesWildcardExpression("*.txt"))
124                 .or("name", matchesWildcardExpression("*.xml"))
125                 */
126                 //.where("name", either(matchesRegularExpression("^.*\\.html$"), matchesRegularExpression("^.*\\.txt$"), matchesRegularExpression("^.*\\.xml$")))
127                 .where("name", isEitherOf(like("*.html"), like("*.txt"), like("*.xml")))
128                 .and("lastModified", is(jan2004))
129                 .and("length", isGreaterThan(10000L));
130 
131         final long thisMinute = Calendar.getInstance().get(Calendar.MINUTE);
132 
133         // A specification for a newly compiled net.sourceforge.domian.specificationSpecification CLASS file
134         CompositeSpecification<File> newlyCompiledSpecificationClass = all(File.class)
135                 .where("name", matchesWildcardExpression("*SpecificationFactory.class"))
136                 .and("lastModified", isAfter(thisMinute))
137                 .and("length", isGreaterThan(15000L))
138                 .and("length", isLessThan(25000L));
139 
140         // The file candidate...
141         String userDir = System.getProperty("user.dir");
142         String fileSeparator = System.getProperty("file.separator");
143         StringTokenizer stringTokenizer = new StringTokenizer(userDir, fileSeparator);
144         List<String> pathElements = new ArrayList<String>();
145         while (stringTokenizer.hasMoreElements()) {
146             pathElements.add((String) stringTokenizer.nextElement());
147         }
148         String lastPathElement = pathElements.get(pathElements.size() - 1);
149         String specClassFile = null;
150         if (lastPathElement.equals("domian")) {
151             specClassFile = userDir + fileSeparator + "domian-core" + fileSeparator + "target" + fileSeparator + "classes" + fileSeparator + "net" + fileSeparator + "sourceforge" + fileSeparator + "domian" + fileSeparator + "specification" + fileSeparator + "SpecificationFactory.class";
152         } else if (lastPathElement.equals("domian-core")) {
153             specClassFile = userDir + fileSeparator + "target" + fileSeparator + "classes" + fileSeparator + "net" + fileSeparator + "sourceforge" + fileSeparator + "domian" + fileSeparator + "specification" + fileSeparator + "SpecificationFactory.class";
154         }
155 
156         // And some asserts...
157         assertTrue(isNotBlank(specClassFile));
158         File file = new File(specClassFile);
159         assertNotNull(file);
160         assertTrue(file.isFile());
161         assertEquals("SpecificationFactory.class", file.getName());
162         assertTrue(newlyCompiledSpecificationClass.isSatisfiedBy(file));
163     }
164 }