001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.juneau.assertions; 018 019import java.io.*; 020import java.time.*; 021import java.util.*; 022import java.util.function.*; 023 024import org.apache.juneau.*; 025import org.apache.juneau.common.utils.*; 026import org.apache.juneau.cp.*; 027import org.apache.juneau.internal.*; 028import org.apache.juneau.reflect.*; 029import org.apache.juneau.serializer.*; 030 031/** 032 * Used for assertion calls against generic POJOs. 033 * 034 * <p> 035 * Extends from {@link FluentObjectAssertion} allowing you to perform basic assertions, but adds several transform 036 * methods to convert to more-specific assertion types. 037 * 038 * <h5 class='section'>Example:</h5> 039 * <p class='bjava'> 040 * <jk>import static</jk> org.apache.juneau.assertions.Assertions.*; 041 * 042 * List<MyBean> <jv>listOfBeans</jv> = ...; 043 * <jsm>assertList</jsm>(<jv>listOfBeans</jv>) 044 * .asItem(1) <jc>// Returns an AnyAssertion.</jc> 045 * .asBean() <jc>// Transforms to BeanAssertion.</jc> 046 * .asProperty(<js>"foo"</js>) <jc>// Returns an AnyAssertion.</jc> 047 * .asString() <jc>// Transforms to StringAssertion.</jc> 048 * .is(<js>"bar"</js>); <jc>// Performs test.</jc> 049 * </p> 050 * 051 * <h5 class='section'>Test Methods:</h5> 052 * <p> 053 * <ul class='javatree'> 054 * <li class='jc'>{@link FluentObjectAssertion} 055 * <ul class='javatreec'> 056 * <li class='jm'>{@link FluentObjectAssertion#isExists() isExists()} 057 * <li class='jm'>{@link FluentObjectAssertion#is(Object) is(Object)} 058 * <li class='jm'>{@link FluentObjectAssertion#is(Predicate) is(Predicate)} 059 * <li class='jm'>{@link FluentObjectAssertion#isNot(Object) isNot(Object)} 060 * <li class='jm'>{@link FluentObjectAssertion#isAny(Object...) isAny(Object...)} 061 * <li class='jm'>{@link FluentObjectAssertion#isNotAny(Object...) isNotAny(Object...)} 062 * <li class='jm'>{@link FluentObjectAssertion#isNull() isNull()} 063 * <li class='jm'>{@link FluentObjectAssertion#isNotNull() isNotNull()} 064 * <li class='jm'>{@link FluentObjectAssertion#isString(String) isString(String)} 065 * <li class='jm'>{@link FluentObjectAssertion#isJson(String) isJson(String)} 066 * <li class='jm'>{@link FluentObjectAssertion#isSame(Object) isSame(Object)} 067 * <li class='jm'>{@link FluentObjectAssertion#isSameJsonAs(Object) isSameJsonAs(Object)} 068 * <li class='jm'>{@link FluentObjectAssertion#isSameSortedJsonAs(Object) isSameSortedJsonAs(Object)} 069 * <li class='jm'>{@link FluentObjectAssertion#isSameSerializedAs(Object, WriterSerializer) isSameSerializedAs(Object, WriterSerializer)} 070 * <li class='jm'>{@link FluentObjectAssertion#isType(Class) isType(Class)} 071 * <li class='jm'>{@link FluentObjectAssertion#isExactType(Class) isExactType(Class)} 072 * </ul> 073 * </ul> 074 * 075 * <h5 class='section'>Transform Methods:</h5> 076 * <p> 077 * <ul class='javatree'> 078 * <li class='jc'>{@link FluentAnyAssertion} 079 * <ul class='javatreec'> 080 * <li class='jm'>{@link FluentAnyAssertion#asArray(Class) asArray(Class)} 081 * <li class='jm'>{@link FluentAnyAssertion#asIntArray() asIntArray()} 082 * <li class='jm'>{@link FluentAnyAssertion#asLongArray() asLongArray()} 083 * <li class='jm'>{@link FluentAnyAssertion#asShortArray() asShortArray()} 084 * <li class='jm'>{@link FluentAnyAssertion#asFloatArray() asFloatArray()} 085 * <li class='jm'>{@link FluentAnyAssertion#asDoubleArray() asDoubleArray()} 086 * <li class='jm'>{@link FluentAnyAssertion#asCharArray() asCharArray()} 087 * <li class='jm'>{@link FluentAnyAssertion#asByteArray() asByteArray()} 088 * <li class='jm'>{@link FluentAnyAssertion#asBooleanArray() asBooleanArray()} 089 * <li class='jm'>{@link FluentAnyAssertion#asBoolean() asBoolean()} 090 * <li class='jm'>{@link FluentAnyAssertion#asBytes() asBytes()} 091 * <li class='jm'>{@link FluentAnyAssertion#asCollection() asCollection()} 092 * <li class='jm'>{@link FluentAnyAssertion#asCollection(Class) asCollection(Class)} 093 * <li class='jm'>{@link FluentAnyAssertion#asStringList() asStringList()} 094 * <li class='jm'>{@link FluentAnyAssertion#asComparable() asComparable()} 095 * <li class='jm'>{@link FluentAnyAssertion#asDate() asDate()} 096 * <li class='jm'>{@link FluentAnyAssertion#asInteger() asInteger()} 097 * <li class='jm'>{@link FluentAnyAssertion#asLong() asLong()} 098 * <li class='jm'>{@link FluentAnyAssertion#asList() asList()} 099 * <li class='jm'>{@link FluentAnyAssertion#asList(Class) asList(Class)} 100 * <li class='jm'>{@link FluentAnyAssertion#asMap() asMap()} 101 * <li class='jm'>{@link FluentAnyAssertion#asMap(Class,Class) asMap(Class,Class)} 102 * <li class='jm'>{@link FluentAnyAssertion#asBean() asBean()} 103 * <li class='jm'>{@link FluentAnyAssertion#asBean(Class) asBean(Class)} 104 * <li class='jm'>{@link FluentAnyAssertion#asBeanList(Class) asBeanList(Class)} 105 * <li class='jm'>{@link FluentAnyAssertion#asZonedDateTime() asZonedDateTime()} 106 * </ul> 107 * <li class='jc'>{@link FluentObjectAssertion} 108 * <ul class='javatreec'> 109 * <li class='jm'>{@link FluentObjectAssertion#asString() asString()} 110 * <li class='jm'>{@link FluentObjectAssertion#asString(WriterSerializer) asString(WriterSerializer)} 111 * <li class='jm'>{@link FluentObjectAssertion#asString(Function) asString(Function)} 112 * <li class='jm'>{@link FluentObjectAssertion#asJson() asJson()} 113 * <li class='jm'>{@link FluentObjectAssertion#asJsonSorted() asJsonSorted()} 114 * <li class='jm'>{@link FluentObjectAssertion#asTransformed(Function) asApplied(Function)} 115 * <li class='jm'>{@link FluentObjectAssertion#asAny() asAny()} 116 * </ul> 117 * </ul> 118 * 119 * <h5 class='section'>Configuration Methods:</h5> 120 * <p> 121 * <ul class='javatree'> 122 * <li class='jc'>{@link Assertion} 123 * <ul class='javatreec'> 124 * <li class='jm'>{@link Assertion#setMsg(String, Object...) setMsg(String, Object...)} 125 * <li class='jm'>{@link Assertion#setOut(PrintStream) setOut(PrintStream)} 126 * <li class='jm'>{@link Assertion#setSilent() setSilent()} 127 * <li class='jm'>{@link Assertion#setStdOut() setStdOut()} 128 * <li class='jm'>{@link Assertion#setThrowable(Class) setThrowable(Class)} 129 * </ul> 130 * </ul> 131 * 132 * <h5 class='section'>See Also:</h5><ul> 133 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauEcosystemOverview">Juneau Ecosystem Overview</a> 134 * </ul> 135 * 136 * @param <T> The object type. 137 * @param <R> The return type. 138 */ 139public class FluentAnyAssertion<T,R> extends FluentObjectAssertion<T,R> { 140 141 //----------------------------------------------------------------------------------------------------------------- 142 // Static 143 //----------------------------------------------------------------------------------------------------------------- 144 145 private static final Messages MESSAGES = Messages.of(FluentAnyAssertion.class, "Messages"); 146 private static final String 147 MSG_objectWasNotType = MESSAGES.getString("objectWasNotType"); 148 149 //----------------------------------------------------------------------------------------------------------------- 150 // Instance 151 //----------------------------------------------------------------------------------------------------------------- 152 153 /** 154 * Constructor. 155 * 156 * @param value 157 * The object being tested. 158 * <br>Can be <jk>null</jk>. 159 * @param returns 160 * The object to return after a test method is called. 161 * <br>If <jk>null</jk>, the test method returns this object allowing multiple test method calls to be 162 * used on the same assertion. 163 */ 164 public FluentAnyAssertion(T value, R returns) { 165 this(null, value, returns); 166 } 167 168 /** 169 * Chained constructor. 170 * 171 * <p> 172 * Used when transforming one assertion into another so that the assertion config can be used by the new assertion. 173 * 174 * @param creator 175 * The assertion that created this assertion. 176 * <br>Should be <jk>null</jk> if this is the top-level assertion. 177 * @param value 178 * The object being tested. 179 * <br>Can be <jk>null</jk>. 180 * @param returns 181 * The object to return after a test method is called. 182 * <br>If <jk>null</jk>, the test method returns this object allowing multiple test method calls to be 183 * used on the same assertion. 184 */ 185 public FluentAnyAssertion(Assertion creator, T value, R returns) { 186 super(creator, value, returns); 187 } 188 189 //----------------------------------------------------------------------------------------------------------------- 190 // Transform methods 191 //----------------------------------------------------------------------------------------------------------------- 192 193 /** 194 * Converts this object assertion into an array assertion. 195 * 196 * @param <E> The element type of the array. 197 * @param elementType The element type of the array. 198 * @return A new assertion. 199 * @throws AssertionError If object is not an array. 200 */ 201 public <E> FluentArrayAssertion<E,R> asArray(Class<E> elementType) throws AssertionError { 202 Utils.assertArgNotNull("elementType", elementType); 203 return new FluentArrayAssertion<>(this, cast(arrayClass(elementType)), returns()); 204 } 205 206 /** 207 * Converts this object assertion into a primitive int array assertion. 208 * 209 * @return A new assertion. 210 * @throws AssertionError If object is not an int array. 211 */ 212 public FluentPrimitiveArrayAssertion<Integer,int[],R> asIntArray() throws AssertionError { 213 return new FluentPrimitiveArrayAssertion<>(this, cast(int[].class), returns()); 214 } 215 216 /** 217 * Converts this object assertion into a primitive long array assertion. 218 * 219 * @return A new assertion. 220 * @throws AssertionError If object is not an long array. 221 */ 222 public FluentPrimitiveArrayAssertion<Long,long[],R> asLongArray() throws AssertionError { 223 return new FluentPrimitiveArrayAssertion<>(this, cast(long[].class), returns()); 224 } 225 226 /** 227 * Converts this object assertion into a primitive short array assertion. 228 * 229 * @return A new assertion. 230 * @throws AssertionError If object is not an short array. 231 */ 232 public FluentPrimitiveArrayAssertion<Short,short[],R> asShortArray() throws AssertionError { 233 return new FluentPrimitiveArrayAssertion<>(this, cast(short[].class), returns()); 234 } 235 236 /** 237 * Converts this object assertion into a primitive float array assertion. 238 * 239 * @return A new assertion. 240 * @throws AssertionError If object is not an float array. 241 */ 242 public FluentPrimitiveArrayAssertion<Float,float[],R> asFloatArray() throws AssertionError { 243 return new FluentPrimitiveArrayAssertion<>(this, cast(float[].class), returns()); 244 } 245 246 /** 247 * Converts this object assertion into a primitive double array assertion. 248 * 249 * @return A new assertion. 250 * @throws AssertionError If object is not an double array. 251 */ 252 public FluentPrimitiveArrayAssertion<Double,double[],R> asDoubleArray() throws AssertionError { 253 return new FluentPrimitiveArrayAssertion<>(this, cast(double[].class), returns()); 254 } 255 256 /** 257 * Converts this object assertion into a primitive char array assertion. 258 * 259 * @return A new assertion. 260 * @throws AssertionError If object is not an char array. 261 */ 262 public FluentPrimitiveArrayAssertion<Character,char[],R> asCharArray() throws AssertionError { 263 return new FluentPrimitiveArrayAssertion<>(this, cast(char[].class), returns()); 264 } 265 266 /** 267 * Converts this object assertion into a primitive byte array assertion. 268 * 269 * @return A new assertion. 270 * @throws AssertionError If object is not an byte array. 271 */ 272 public FluentPrimitiveArrayAssertion<Byte,byte[],R> asByteArray() throws AssertionError { 273 return new FluentPrimitiveArrayAssertion<>(this, cast(byte[].class), returns()); 274 } 275 276 /** 277 * Converts this object assertion into a primitive boolean array assertion. 278 * 279 * @return A new assertion. 280 * @throws AssertionError If object is not an boolean array. 281 */ 282 public FluentPrimitiveArrayAssertion<Boolean,boolean[],R> asBooleanArray() throws AssertionError { 283 return new FluentPrimitiveArrayAssertion<>(this, cast(boolean[].class), returns()); 284 } 285 286 /** 287 * Converts this object assertion into a boolean assertion. 288 * 289 * @return A new assertion. 290 * @throws AssertionError If object is not a boolean. 291 */ 292 public FluentBooleanAssertion<R> asBoolean() { 293 return new FluentBooleanAssertion<>(this, cast(Boolean.class), returns()); 294 } 295 296 /** 297 * Converts this object assertion into a byte array assertion. 298 * 299 * @return A new assertion. 300 * @throws AssertionError If object is not a byte array. 301 */ 302 public FluentByteArrayAssertion<R> asBytes() { 303 return new FluentByteArrayAssertion<>(this, cast(byte[].class), returns()); 304 } 305 306 /** 307 * Converts this object assertion into a collection assertion. 308 * 309 * @return A new assertion. 310 * @throws AssertionError If object is not a collection. 311 */ 312 public FluentCollectionAssertion<Object,R> asCollection() { 313 return asCollection(Object.class); 314 } 315 316 /** 317 * Converts this object assertion into a collection assertion. 318 * 319 * @param <E> The element type of the collection. 320 * @param elementType The element type of the collection. 321 * @return A new assertion. 322 * @throws AssertionError If object is not a collection. 323 */ 324 public <E> FluentCollectionAssertion<E,R> asCollection(Class<E> elementType) { 325 Utils.assertArgNotNull("elementType", elementType); 326 return new FluentCollectionAssertion<>(this, cast(Collection.class), returns()); 327 } 328 329 /** 330 * Converts this object assertion into a collection assertion. 331 * 332 * @return A new assertion. 333 * @throws AssertionError If object is not a collection. 334 */ 335 public FluentStringListAssertion<R> asStringList() { 336 return new FluentStringListAssertion<>(this, cast(List.class), returns()); 337 } 338 339 /** 340 * Converts this object assertion into a comparable object assertion. 341 * 342 * @param <T2> The comparable type. 343 * @return A new assertion. 344 * @throws AssertionError If object is not an instance of {@link Comparable}. 345 */ 346 public <T2 extends Comparable<T2>> FluentComparableAssertion<T2,R> asComparable() { 347 return new FluentComparableAssertion<>(this, (T2)cast(Comparable.class), returns()); 348 } 349 350 /** 351 * Converts this object assertion into a date assertion. 352 * 353 * @return A new assertion. 354 * @throws AssertionError If object is not a date. 355 */ 356 public FluentDateAssertion<R> asDate() { 357 return new FluentDateAssertion<>(this, cast(Date.class), returns()); 358 } 359 360 /** 361 * Converts this object assertion into an integer assertion. 362 * 363 * @return A new assertion. 364 * @throws AssertionError If object is not an integer. 365 */ 366 public FluentIntegerAssertion<R> asInteger() { 367 return new FluentIntegerAssertion<>(this, cast(Integer.class), returns()); 368 } 369 370 /** 371 * Converts this object assertion into a long assertion. 372 * 373 * @return A new assertion. 374 * @throws AssertionError If object is not a long. 375 */ 376 public FluentLongAssertion<R> asLong() { 377 return new FluentLongAssertion<>(this, cast(Long.class), returns()); 378 } 379 380 /** 381 * Converts this object assertion into a list assertion. 382 * 383 * @return A new assertion. 384 * @throws AssertionError If object is not a list. 385 */ 386 public FluentListAssertion<Object,R> asList() { 387 return asList(Object.class); 388 } 389 390 /** 391 * Converts this object assertion into a list assertion. 392 * 393 * @param <E> The element type. 394 * @param elementType The element type. 395 * @return A new assertion. 396 * @throws AssertionError If object is not a list. 397 */ 398 public <E> FluentListAssertion<E,R> asList(Class<E> elementType) { 399 Utils.assertArgNotNull("elementType", elementType); 400 return new FluentListAssertion<>(this, cast(List.class), returns()); 401 } 402 403 /** 404 * Converts this object assertion into a map assertion. 405 * 406 * @return A new assertion. 407 * @throws AssertionError If object is not a map. 408 */ 409 public FluentMapAssertion<String,Object,R> asMap() { 410 return asMap(String.class,Object.class); 411 } 412 413 /** 414 * Converts this object assertion into a map assertion with the specified key and value types. 415 * 416 * @param <K> The key type. 417 * @param <V> The value type. 418 * @param keyType The key type. 419 * @param valueType The value type. 420 * @return A new assertion. 421 * @throws AssertionError If object is not a map. 422 */ 423 public <K,V> FluentMapAssertion<K,V,R> asMap(Class<K> keyType, Class<V> valueType) { 424 Utils.assertArgNotNull("keyType", keyType); 425 Utils.assertArgNotNull("valueType", valueType); 426 return new FluentMapAssertion<>(this, cast(Map.class), returns()); 427 } 428 429 /** 430 * Converts this object assertion into a bean assertion. 431 * 432 * @param <T2> The bean type. 433 * @param beanType The bean type. 434 * @return A new assertion. 435 * @throws AssertionError If object is not a bean. 436 */ 437 public <T2> FluentBeanAssertion<T2,R> asBean(Class<T2> beanType) { 438 Utils.assertArgNotNull("beanType", beanType); 439 return new FluentBeanAssertion<>(this, cast(beanType), returns()); 440 } 441 442 /** 443 * Converts this object assertion into a bean assertion. 444 * 445 * @return A new assertion. 446 * @throws AssertionError If object is not a bean. 447 */ 448 public FluentBeanAssertion<T,R> asBean() { 449 return new FluentBeanAssertion<>(this, orElse(null), returns()); 450 } 451 452 /** 453 * Converts this object assertion into a list-of-beans assertion. 454 * 455 * @param <T2> The bean type. 456 * @param beanType The bean type. 457 * @return A new assertion. 458 * @throws AssertionError If object is not a bean. 459 */ 460 public <T2> FluentBeanListAssertion<T2,R> asBeanList(Class<T2> beanType) { 461 Utils.assertArgNotNull("beanType", beanType); 462 return new FluentBeanListAssertion<>(this, cast(List.class), returns()); 463 } 464 465 /** 466 * Converts this object assertion into a zoned-datetime assertion. 467 * 468 * @return A new assertion. 469 * @throws AssertionError If object is not a zoned-datetime. 470 */ 471 public FluentZonedDateTimeAssertion<R> asZonedDateTime() { 472 return new FluentZonedDateTimeAssertion<>(this, cast(ZonedDateTime.class), returns()); 473 } 474 475 //----------------------------------------------------------------------------------------------------------------- 476 // Fluent setters 477 //----------------------------------------------------------------------------------------------------------------- 478 @Override /* Overridden from Assertion */ 479 public FluentAnyAssertion<T,R> setMsg(String msg, Object...args) { 480 super.setMsg(msg, args); 481 return this; 482 } 483 484 @Override /* Overridden from Assertion */ 485 public FluentAnyAssertion<T,R> setOut(PrintStream value) { 486 super.setOut(value); 487 return this; 488 } 489 490 @Override /* Overridden from Assertion */ 491 public FluentAnyAssertion<T,R> setSilent() { 492 super.setSilent(); 493 return this; 494 } 495 496 @Override /* Overridden from Assertion */ 497 public FluentAnyAssertion<T,R> setStdOut() { 498 super.setStdOut(); 499 return this; 500 } 501 502 @Override /* Overridden from Assertion */ 503 public FluentAnyAssertion<T,R> setThrowable(Class<? extends java.lang.RuntimeException> value) { 504 super.setThrowable(value); 505 return this; 506 } 507 //----------------------------------------------------------------------------------------------------------------- 508 // Utility methods 509 //----------------------------------------------------------------------------------------------------------------- 510 511 private <T2> T2 cast(Class<T2> c) throws AssertionError { 512 Object o = orElse(null); 513 if (o == null || c.isInstance(o)) 514 return c.cast(o); 515 throw new BasicAssertionError(MSG_objectWasNotType, ClassInfo.of(c).getFullName(), o.getClass()); 516 } 517}