001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019 020package org.apache.isis.core.commons.matchers; 021 022import java.io.File; 023import java.io.IOException; 024import java.util.Arrays; 025import java.util.List; 026import org.hamcrest.*; 027import org.hamcrest.core.IsEqual; 028import org.hamcrest.core.StringContains; 029import org.hamcrest.core.StringEndsWith; 030import org.hamcrest.core.StringStartsWith; 031import org.apache.isis.core.commons.lang.StringExtensions; 032 033import static org.hamcrest.CoreMatchers.nullValue; 034 035/** 036 * Hamcrest {@link Matcher} implementations. 037 * 038 */ 039public final class IsisMatchers { 040 041 private IsisMatchers() { 042 } 043 044 @Factory 045 public static Matcher<String> containsStripNewLines(final String expected) { 046 final String strippedExpected = StringExtensions.stripNewLines(expected); 047 return new StringContains(strippedExpected) { 048 @Override 049 public boolean matchesSafely(final String actual) { 050 return super.matchesSafely(StringExtensions.stripNewLines(actual)); 051 } 052 053 @Override 054 public void describeTo(final Description description) { 055 description.appendText("a string (ignoring new lines) containing").appendValue(strippedExpected); 056 } 057 }; 058 } 059 060 @Factory 061 public static Matcher<String> equalToStripNewLines(final String expected) { 062 final String strippedExpected = StringExtensions.stripNewLines(expected); 063 return new IsEqual<String>(strippedExpected) { 064 @Override 065 public boolean matches(final Object actualObj) { 066 final String actual = (String) actualObj; 067 return super.matches(StringExtensions.stripNewLines(actual)); 068 } 069 070 @Override 071 public void describeTo(final Description description) { 072 description.appendText("a string (ignoring new lines) equal to").appendValue(strippedExpected); 073 } 074 }; 075 } 076 077 @Factory 078 public static StringStartsWith startsWithStripNewLines(final String expected) { 079 final String strippedExpected = StringExtensions.stripNewLines(expected); 080 return new StringStartsWith(strippedExpected) { 081 @Override 082 public boolean matchesSafely(final String actual) { 083 return super.matchesSafely(StringExtensions.stripNewLines(actual)); 084 } 085 086 @Override 087 public void describeTo(final Description description) { 088 description.appendText("a string (ignoring new lines) starting with").appendValue(strippedExpected); 089 } 090 }; 091 } 092 093 @Factory 094 public static Matcher<String> endsWithStripNewLines(final String expected) { 095 final String strippedExpected = StringExtensions.stripNewLines(expected); 096 return new StringEndsWith(strippedExpected) { 097 @Override 098 public boolean matchesSafely(final String actual) { 099 return super.matchesSafely(StringExtensions.stripNewLines(actual)); 100 } 101 102 @Override 103 public void describeTo(final Description description) { 104 description.appendText("a string (ignoring new lines) ending with").appendValue(strippedExpected); 105 } 106 }; 107 } 108 109 @Factory 110 public static <T> Matcher<T> anInstanceOf(final Class<T> expected) { 111 return new TypeSafeMatcher<T>() { 112 @Override 113 public boolean matchesSafely(final T actual) { 114 return expected.isAssignableFrom(actual.getClass()); 115 } 116 117 @Override 118 public void describeTo(final Description description) { 119 description.appendText("an instance of ").appendValue(expected); 120 } 121 }; 122 } 123 124 @Factory 125 public static Matcher<String> nonEmptyString() { 126 return new TypeSafeMatcher<String>() { 127 @Override 128 public boolean matchesSafely(final String str) { 129 return str != null && str.length() > 0; 130 } 131 132 @Override 133 public void describeTo(final Description description) { 134 description.appendText("a non empty string"); 135 } 136 137 }; 138 } 139 140 @Factory 141 @SuppressWarnings("unchecked") 142 public static Matcher<String> nonEmptyStringOrNull() { 143 return CoreMatchers.anyOf(nullValue(String.class), nonEmptyString()); 144 } 145 146 @Factory 147 public static Matcher<List<?>> containsElementThat(final Matcher<?> elementMatcher) { 148 return new TypeSafeMatcher<List<?>>() { 149 @Override 150 public boolean matchesSafely(final List<?> list) { 151 for (final Object o : list) { 152 if (elementMatcher.matches(o)) { 153 return true; 154 } 155 } 156 return false; 157 } 158 159 @Override 160 public void describeTo(final Description description) { 161 description.appendText("contains element that ").appendDescriptionOf(elementMatcher); 162 } 163 }; 164 } 165 166 @Factory 167 public static <T extends Comparable<T>> Matcher<T> greaterThan(final T c) { 168 return Matchers.greaterThan(c); 169 } 170 171 @Factory 172 public static Matcher<Class<?>> classEqualTo(final Class<?> operand) { 173 174 class ClassEqualsMatcher extends TypeSafeMatcher<Class<?>> { 175 private final Class<?> clazz; 176 177 public ClassEqualsMatcher(final Class<?> clazz) { 178 this.clazz = clazz; 179 } 180 181 @Override 182 public boolean matchesSafely(final Class<?> arg) { 183 return clazz == arg; 184 } 185 186 @Override 187 public void describeTo(final Description description) { 188 description.appendValue(clazz); 189 } 190 } 191 192 return new ClassEqualsMatcher(operand); 193 } 194 195 @Factory 196 public static Matcher<File> existsAndNotEmpty() { 197 198 return new TypeSafeMatcher<File>() { 199 200 @Override 201 public void describeTo(final Description arg0) { 202 arg0.appendText("exists and is not empty"); 203 } 204 205 @Override 206 public boolean matchesSafely(final File f) { 207 return f.exists() && f.length() > 0; 208 } 209 }; 210 } 211 212 @Factory 213 public static Matcher<String> matches(final String regex) { 214 return new TypeSafeMatcher<String>() { 215 216 @Override 217 public void describeTo(final Description description) { 218 description.appendText("string matching " + regex); 219 } 220 221 @Override 222 public boolean matchesSafely(final String str) { 223 return str.matches(regex); 224 } 225 }; 226 } 227 228 @Factory 229 public static <X> Matcher<Class<X>> anySubclassOf(final Class<X> cls) { 230 return new TypeSafeMatcher<Class<X>>() { 231 232 @Override 233 public void describeTo(final Description arg0) { 234 arg0.appendText("is subclass of ").appendText(cls.getName()); 235 } 236 237 @Override 238 public boolean matchesSafely(final Class<X> item) { 239 return cls.isAssignableFrom(item); 240 } 241 }; 242 } 243 244 @Factory 245 public static <T> Matcher<List<T>> sameContentsAs(final List<T> expected) { 246 return new TypeSafeMatcher<List<T>>() { 247 248 @Override 249 public void describeTo(final Description description) { 250 description.appendText("same sequence as " + expected); 251 } 252 253 @Override 254 public boolean matchesSafely(final List<T> actual) { 255 return actual.containsAll(expected) && expected.containsAll(actual); 256 } 257 }; 258 } 259 260 @Factory 261 public static <T> Matcher<List<T>> listContaining(final T t) { 262 return new TypeSafeMatcher<List<T>>() { 263 264 @Override 265 public void describeTo(Description arg0) { 266 arg0.appendText("list containing ").appendValue(t); 267 } 268 269 @Override 270 public boolean matchesSafely(List<T> arg0) { 271 return arg0.contains(t); 272 } 273 }; 274 } 275 276 @Factory 277 public static <T> Matcher<List<T>> listContainingAll(final T... items) { 278 return new TypeSafeMatcher<List<T>>() { 279 280 @Override 281 public void describeTo(Description arg0) { 282 arg0.appendText("has items ").appendValue(items); 283 284 } 285 286 @Override 287 public boolean matchesSafely(List<T> arg0) { 288 return arg0.containsAll(Arrays.asList(items)); 289 } 290 }; 291 } 292 293 @Factory 294 public static Matcher<List<Object>> containsObjectOfType(final Class<?> cls) { 295 return new TypeSafeMatcher<List<Object>>() { 296 297 @Override 298 public void describeTo(final Description desc) { 299 desc.appendText("contains instance of type " + cls.getName()); 300 } 301 302 @Override 303 public boolean matchesSafely(final List<Object> items) { 304 for (final Object object : items) { 305 if (cls.isAssignableFrom(object.getClass())) { 306 return true; 307 } 308 } 309 return false; 310 } 311 }; 312 } 313 314 @Factory 315 public static Matcher<String> startsWith(final String expected) { 316 return new TypeSafeMatcher<String>() { 317 318 @Override 319 public void describeTo(Description description) { 320 description.appendText(" starts with '" + expected + "'"); 321 } 322 323 @Override 324 public boolean matchesSafely(String actual) { 325 return actual.startsWith(expected); 326 } 327 }; 328 } 329 330 @Factory 331 public static Matcher<String> contains(final String expected) { 332 return new TypeSafeMatcher<String>() { 333 334 @Override 335 public void describeTo(Description description) { 336 description.appendText(" contains '" + expected + "'"); 337 } 338 339 @Override 340 public boolean matchesSafely(String actual) { 341 return actual.contains(expected); 342 } 343 }; 344 } 345 346 347 @Factory 348 public static Matcher<File> equalsFile(final File file) throws IOException { 349 final String canonicalPath = file.getCanonicalPath(); 350 return new TypeSafeMatcher<File>() { 351 352 @Override 353 public void describeTo(Description arg0) { 354 arg0.appendText("file '" + canonicalPath + "'"); 355 } 356 357 @Override 358 public boolean matchesSafely(File arg0) { 359 try { 360 return arg0.getCanonicalPath().equals(canonicalPath); 361 } catch (IOException e) { 362 return false; 363 } 364 } 365 }; 366 } 367 368}