001    /*
002     * Created on Dec 22, 2010
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
005     * the License. You may obtain a copy of the License at
006     *
007     * http://www.apache.org/licenses/LICENSE-2.0
008     *
009     * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
010     * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
011     * specific language governing permissions and limitations under the License.
012     *
013     * Copyright @2010-2011 the original author or authors.
014     */
015    package org.fest.assertions.internal;
016    
017    import static org.fest.assertions.error.ShouldBeEmpty.shouldBeEmpty;
018    import static org.fest.assertions.error.ShouldBeEqualIgnoringCase.shouldBeEqual;
019    import static org.fest.assertions.error.ShouldBeNullOrEmpty.shouldBeNullOrEmpty;
020    import static org.fest.assertions.error.ShouldContainString.*;
021    import static org.fest.assertions.error.ShouldEndWith.shouldEndWith;
022    import static org.fest.assertions.error.ShouldHaveSize.shouldHaveSize;
023    import static org.fest.assertions.error.ShouldMatchPattern.shouldMatch;
024    import static org.fest.assertions.error.ShouldNotBeEmpty.shouldNotBeEmpty;
025    import static org.fest.assertions.error.ShouldNotContainString.shouldNotContain;
026    import static org.fest.assertions.error.ShouldNotMatchPattern.shouldNotMatch;
027    import static org.fest.assertions.error.ShouldStartWith.shouldStartWith;
028    
029    import java.util.Comparator;
030    import java.util.regex.Pattern;
031    import java.util.regex.PatternSyntaxException;
032    
033    import org.fest.assertions.core.AssertionInfo;
034    import org.fest.util.ComparatorBasedComparisonStrategy;
035    import org.fest.util.ComparisonStrategy;
036    import org.fest.util.StandardComparisonStrategy;
037    import org.fest.util.VisibleForTesting;
038    
039    /**
040     * Reusable assertions for <code>{@link String}</code>s.
041     *
042     * @author Alex Ruiz
043     * @author Joel Costigliola
044     */
045    public class Strings {
046    
047      private static final Strings INSTANCE = new Strings();
048    
049      /**
050       * Returns the singleton instance of this class based on {@link StandardComparisonStrategy}.
051       * @return the singleton instance of this class based on {@link StandardComparisonStrategy}.
052       */
053      public static Strings instance() {
054        return INSTANCE;
055      }
056    
057      @VisibleForTesting Failures failures = Failures.instance();
058    
059      @VisibleForTesting Strings() {
060        this(StandardComparisonStrategy.instance());
061      }
062    
063      private ComparisonStrategy comparisonStrategy;
064    
065      public Strings(ComparisonStrategy comparisonStrategy) {
066        this.comparisonStrategy = comparisonStrategy;
067      }  
068      
069      @VisibleForTesting
070      public Comparator<?> getComparator() {
071        if (comparisonStrategy instanceof ComparatorBasedComparisonStrategy) {
072          return ((ComparatorBasedComparisonStrategy)comparisonStrategy).getComparator();
073        }
074        return null;
075      }
076    
077      /**
078       * Asserts that the given {@code String} is {@code null} or empty.
079       * @param info contains information about the assertion.
080       * @param actual the given {@code String}.
081       * @throws AssertionError if the given {@code String} is not {@code null} *and* it is not empty.
082       */
083      public void assertNullOrEmpty(AssertionInfo info, String actual) {
084        if (actual == null || !hasContents(actual)) return;
085        throw failures.failure(info, shouldBeNullOrEmpty(actual));
086      }
087    
088      /**
089       * Asserts that the given {@code String} is empty.
090       * @param info contains information about the assertion.
091       * @param actual the given {@code String}.
092       * @throws AssertionError if the given {@code String} is {@code null}.
093       * @throws AssertionError if the given {@code String} is not empty.
094       */
095      public void assertEmpty(AssertionInfo info, String actual) {
096        assertNotNull(info, actual);
097        if (!hasContents(actual)) return;
098        throw failures.failure(info, shouldBeEmpty(actual));
099      }
100    
101      /**
102       * Asserts that the given {@code String} is not empty.
103       * @param info contains information about the assertion.
104       * @param actual the given {@code String}.
105       * @throws AssertionError if the given {@code String} is {@code null}.
106       * @throws AssertionError if the given {@code String} is empty.
107       */
108      public void assertNotEmpty(AssertionInfo info, String actual) {
109        assertNotNull(info, actual);
110        if (hasContents(actual)) return;
111        throw failures.failure(info, shouldNotBeEmpty());
112      }
113    
114      private static boolean hasContents(String s) {
115        return s.length() > 0;
116      }
117    
118      /**
119       * Asserts that the size of the given {@code String} is equal to the expected one.
120       * @param info contains information about the assertion.
121       * @param actual the given {@code String}.
122       * @param expectedSize the expected size of {@code actual}.
123       * @throws AssertionError if the given {@code String} is {@code null}.
124       * @throws AssertionError if the size of the given {@code String} is different than the expected one.
125       */
126      public void assertHasSize(AssertionInfo info, String actual, int expectedSize) {
127        assertNotNull(info, actual);
128        int sizeOfActual = actual.length();
129        if (sizeOfActual == expectedSize) return;
130        throw failures.failure(info, shouldHaveSize(actual, sizeOfActual, expectedSize));
131      }
132    
133      /**
134       * Verifies that the given {@code String} contains the given sequence.
135       * @param info contains information about the assertion.
136       * @param actual the actual {@code String}.
137       * @param sequence the sequence to search for.
138       * @throws NullPointerException if the given sequence is {@code null}.
139       * @throws AssertionError if the given {@code String} is {@code null}.
140       * @throws AssertionError if the actual {@code String} does not contain the given sequence.
141       */
142      public void assertContains(AssertionInfo info, String actual, String sequence) {
143        checkSequenceIsNotNull(sequence);
144        assertNotNull(info, actual);
145        if (stringContains(actual, sequence)) return;
146        throw failures.failure(info, shouldContain(actual, sequence, comparisonStrategy));
147      }
148    
149      /**
150       * Delegates to {@link ComparisonStrategy#stringContains(String, String)}
151       */
152      private boolean stringContains(String actual, String sequence) {
153        return comparisonStrategy.stringContains(actual, sequence);
154      }
155    
156      /**
157       * Verifies that the given {@code String} contains the given sequence, ignoring case considerations.
158       * @param info contains information about the assertion.
159       * @param actual the actual {@code String}.
160       * @param sequence the sequence to search for.
161       * @throws NullPointerException if the given sequence is {@code null}.
162       * @throws AssertionError if the given {@code String} is {@code null}.
163       * @throws AssertionError if the actual {@code String} does not contain the given sequence.
164       */
165      public void assertContainsIgnoringCase(AssertionInfo info, String actual, String sequence) {
166        checkSequenceIsNotNull(sequence);
167        assertNotNull(info, actual);
168        if (actual.toLowerCase().contains(sequence.toLowerCase())) return;
169        throw failures.failure(info, shouldContainIgnoringCase(actual, sequence));
170      }
171    
172      /**
173       * Verifies that the given {@code String} does not contain the given sequence.
174       * @param info contains information about the assertion.
175       * @param actual the actual {@code String}.
176       * @param sequence the sequence to search for.
177       * @throws NullPointerException if the given sequence is {@code null}.
178       * @throws AssertionError if the given {@code String} is {@code null}.
179       * @throws AssertionError if the actual {@code String} contains the given sequence.
180       */
181      public void assertDoesNotContain(AssertionInfo info, String actual, String sequence) {
182        checkSequenceIsNotNull(sequence);
183        assertNotNull(info, actual);
184        if (!stringContains(actual, sequence)) return;
185        throw failures.failure(info, shouldNotContain(actual, sequence, comparisonStrategy));
186      }
187    
188      private void checkSequenceIsNotNull(String sequence) {
189        if (sequence == null) throw new NullPointerException("The sequence to look for should not be null");
190      }
191    
192      /**
193       * Verifies that two {@code String}s are equal, ignoring case considerations.
194       * @param info contains information about the assertion.
195       * @param actual the actual {@code String}.
196       * @param expected the expected {@code String}.
197       * @throws AssertionError if the given {@code String}s are not equal.
198       */
199      public void assertEqualsIgnoringCase(AssertionInfo info, String actual, String expected) {
200        if (areEqualIgnoringCase(actual, expected)) return;
201        throw failures.failure(info, shouldBeEqual(actual, expected));
202      }
203    
204      private boolean areEqualIgnoringCase(String actual, String expected) {
205        if (actual == null) return expected == null;
206        return actual.equalsIgnoreCase(expected);
207      }
208    
209      /**
210       * Verifies that the given {@code String} starts with the given prefix.
211       * @param info contains information about the assertion.
212       * @param actual the actual {@code String}.
213       * @param prefix the given prefix.
214       * @throws NullPointerException if the given sequence is {@code null}.
215       * @throws AssertionError if the given {@code String} is {@code null}.
216       * @throws AssertionError if the actual {@code String} does not start with the given prefix.
217       */
218      public void assertStartsWith(AssertionInfo info, String actual, String prefix) {
219        if (prefix == null) throw new NullPointerException("The given prefix should not be null");
220        assertNotNull(info, actual);
221        if (comparisonStrategy.stringStartsWith(actual, prefix)) return;
222        throw failures.failure(info, shouldStartWith(actual, prefix, comparisonStrategy));
223      }
224      
225      /**
226       * Verifies that the given {@code String} ends with the given suffix.
227       * @param info contains information about the assertion.
228       * @param actual the actual {@code String}.
229       * @param suffix the given suffix.
230       * @throws NullPointerException if the given sequence is {@code null}.
231       * @throws AssertionError if the given {@code String} is {@code null}.
232       * @throws AssertionError if the actual {@code String} does not end with the given suffix.
233       */
234      public void assertEndsWith(AssertionInfo info, String actual, String suffix) {
235        if (suffix == null) throw new NullPointerException("The given suffix should not be null");
236        assertNotNull(info, actual);
237        if (comparisonStrategy.stringEndsWith(actual, suffix)) return;
238        throw failures.failure(info, shouldEndWith(actual, suffix, comparisonStrategy)); 
239      }
240    
241      /**
242       * Verifies that the given {@code String} matches the given regular expression.
243       * @param info contains information about the assertion.
244       * @param actual the given {@code String}.
245       * @param regex the regular expression to which the actual {@code String} is to be matched.
246       * @throws NullPointerException if the given pattern is {@code null}.
247       * @throws PatternSyntaxException if the regular expression's syntax is invalid.
248       * @throws AssertionError if the given {@code String} is {@code null}.
249       * @throws AssertionError if the actual {@code String} does not match the given regular expression.
250       */
251      public void assertMatches(AssertionInfo info, String actual, String regex) {
252        checkRegexIsNotNull(regex);
253        assertNotNull(info, actual);
254        if (Pattern.matches(regex, actual)) return;
255        throw failures.failure(info, shouldMatch(actual, regex));
256      }
257    
258      /**
259       * Verifies that the given {@code String} does not match the given regular expression.
260       * @param info contains information about the assertion.
261       * @param actual the given {@code String}.
262       * @param regex the regular expression to which the actual {@code String} is to be matched.
263       * @throws NullPointerException if the given pattern is {@code null}.
264       * @throws PatternSyntaxException if the regular expression's syntax is invalid.
265       * @throws AssertionError if the actual {@code String} matches the given regular expression.
266       */
267      public void assertDoesNotMatch(AssertionInfo info, String actual, String regex) {
268        checkRegexIsNotNull(regex);
269        if (actual == null || !Pattern.matches(regex, actual)) return;
270        throw failures.failure(info, shouldNotMatch(actual, regex));
271      }
272    
273      private void checkRegexIsNotNull(String regex) {
274        if (regex == null) throw patternToMatchIsNull();
275      }
276    
277      /**
278       * Verifies that the given {@code String} matches the given regular expression.
279       * @param info contains information about the assertion.
280       * @param actual the given {@code String}.
281       * @param pattern the regular expression to which the actual {@code String} is to be matched.
282       * @throws NullPointerException if the given pattern is {@code null}.
283       * @throws AssertionError if the given {@code String} is {@code null}.
284       * @throws AssertionError if the given {@code String} does not match the given regular expression.
285       */
286      public void assertMatches(AssertionInfo info, String actual, Pattern pattern) {
287        checkIsNotNull(pattern);
288        assertNotNull(info, actual);
289        if (pattern.matcher(actual).matches()) return;
290        throw failures.failure(info, shouldMatch(actual, pattern.pattern()));
291      }
292    
293      /**
294       * Verifies that the given {@code String} does not match the given regular expression.
295       * @param info contains information about the assertion.
296       * @param actual the given {@code String}.
297       * @param pattern the regular expression to which the actual {@code String} is to be matched.
298       * @throws NullPointerException if the given pattern is {@code null}.
299       * @throws AssertionError if the given {@code String} matches the given regular expression.
300       */
301      public void assertDoesNotMatch(AssertionInfo info, String actual, Pattern pattern) {
302        checkIsNotNull(pattern);
303        if (actual == null || !pattern.matcher(actual).matches()) return;
304        throw failures.failure(info, shouldNotMatch(actual, pattern.pattern()));
305      }
306    
307      private void checkIsNotNull(Pattern pattern) {
308        if (pattern == null) throw patternToMatchIsNull();
309      }
310    
311      private NullPointerException patternToMatchIsNull() {
312        return new NullPointerException("The regular expression pattern to match should not be null");
313      }
314    
315      private void assertNotNull(AssertionInfo info, String actual) {
316        Objects.instance().assertNotNull(info, actual);
317      }
318    }