001// *************************************************************************************************************************** 002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * 003// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * 004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * 005// * with 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 an * 010// * "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// *************************************************************************************************************************** 013package org.apache.juneau.assertions; 014 015import static org.apache.juneau.common.internal.ArgUtils.*; 016import static org.apache.juneau.internal.ObjectUtils.*; 017 018import java.io.*; 019import java.time.temporal.*; 020import java.util.*; 021import java.util.function.*; 022 023import org.apache.juneau.cp.*; 024import org.apache.juneau.internal.*; 025import org.apache.juneau.serializer.*; 026 027/** 028 * Used for fluent assertion calls against dates. 029 * 030 * <h5 class='section'>Example:</h5> 031 * <p class='bjava'> 032 * <jc>// Validates the response expiration is after the current date.</jc> 033 * <jv>client</jv> 034 * .get(<jsf>URL</jsf>) 035 * .run() 036 * .assertDateHeader(<js>"Expires"</js>).isAfterNow(); 037 * </p> 038 * 039 * 040 * <h5 class='section'>Test Methods:</h5> 041 * <p> 042 * <ul class='javatree'> 043 * <li class='jc'>{@link FluentDateAssertion} 044 * <ul class='javatreec'> 045 * <li class='jm'>{@link FluentDateAssertion#is(Date,ChronoUnit) is(Date,ChronoUnit)} 046 * <li class='jm'>{@link FluentDateAssertion#isAfter(Date) isAfter(Date)} 047 * <li class='jm'>{@link FluentDateAssertion#isAfterNow() isAfterNow()} 048 * <li class='jm'>{@link FluentDateAssertion#isBefore(Date) isBefore(Date)} 049 * <li class='jm'>{@link FluentDateAssertion#isBeforeNow() isBeforeNow()} 050 * <li class='jm'>{@link FluentDateAssertion#isBetween(Date,Date) isBetween(Date,Date)} 051 * </ul> 052 * <li class='jc'>{@link FluentComparableAssertion} 053 * <ul class='javatreec'> 054 * <li class='jm'>{@link FluentComparableAssertion#isGt(Comparable) isGt(Comparable)} 055 * <li class='jm'>{@link FluentComparableAssertion#isGte(Comparable) isGte(Comparable)} 056 * <li class='jm'>{@link FluentComparableAssertion#isLt(Comparable) isLt(Comparable)} 057 * <li class='jm'>{@link FluentComparableAssertion#isLte(Comparable) isLte(Comparable)} 058 * <li class='jm'>{@link FluentComparableAssertion#isBetween(Comparable,Comparable) isBetween(Comparable,Comparable)} 059 * </ul> 060 * <li class='jc'>{@link FluentObjectAssertion} 061 * <ul class='javatreec'> 062 * <li class='jm'>{@link FluentObjectAssertion#isExists() isExists()} 063 * <li class='jm'>{@link FluentObjectAssertion#is(Object) is(Object)} 064 * <li class='jm'>{@link FluentObjectAssertion#is(Predicate) is(Predicate)} 065 * <li class='jm'>{@link FluentObjectAssertion#isNot(Object) isNot(Object)} 066 * <li class='jm'>{@link FluentObjectAssertion#isAny(Object...) isAny(Object...)} 067 * <li class='jm'>{@link FluentObjectAssertion#isNotAny(Object...) isNotAny(Object...)} 068 * <li class='jm'>{@link FluentObjectAssertion#isNull() isNull()} 069 * <li class='jm'>{@link FluentObjectAssertion#isNotNull() isNotNull()} 070 * <li class='jm'>{@link FluentObjectAssertion#isString(String) isString(String)} 071 * <li class='jm'>{@link FluentObjectAssertion#isJson(String) isJson(String)} 072 * <li class='jm'>{@link FluentObjectAssertion#isSame(Object) isSame(Object)} 073 * <li class='jm'>{@link FluentObjectAssertion#isSameJsonAs(Object) isSameJsonAs(Object)} 074 * <li class='jm'>{@link FluentObjectAssertion#isSameSortedJsonAs(Object) isSameSortedJsonAs(Object)} 075 * <li class='jm'>{@link FluentObjectAssertion#isSameSerializedAs(Object, WriterSerializer) isSameSerializedAs(Object, WriterSerializer)} 076 * <li class='jm'>{@link FluentObjectAssertion#isType(Class) isType(Class)} 077 * <li class='jm'>{@link FluentObjectAssertion#isExactType(Class) isExactType(Class)} 078 * </ul> 079 * </ul> 080 * 081 * <h5 class='section'>Transform Methods:</h5> 082 * <p> 083 * <ul class='javatree'> 084 * <li class='jc'>{@link FluentDateAssertion} 085 * <ul class='javatreec'> 086 * <li class='jm'>{@link FluentDateAssertion#asEpochMillis() asEpochMillis()} 087 * <li class='jm'>{@link FluentDateAssertion#asEpochSeconds() asEpochSeconds()} 088 * </ul> 089 * <li class='jc'>{@link FluentObjectAssertion} 090 * <ul class='javatreec'> 091 * <li class='jm'>{@link FluentObjectAssertion#asString() asString()} 092 * <li class='jm'>{@link FluentObjectAssertion#asString(WriterSerializer) asString(WriterSerializer)} 093 * <li class='jm'>{@link FluentObjectAssertion#asString(Function) asString(Function)} 094 * <li class='jm'>{@link FluentObjectAssertion#asJson() asJson()} 095 * <li class='jm'>{@link FluentObjectAssertion#asJsonSorted() asJsonSorted()} 096 * <li class='jm'>{@link FluentObjectAssertion#asTransformed(Function) asApplied(Function)} 097 * <li class='jm'>{@link FluentObjectAssertion#asAny() asAny()} 098 * </ul> 099 * </ul> 100 * 101 * <h5 class='section'>Configuration Methods:</h5> 102 * <p> 103 * <ul class='javatree'> 104 * <li class='jc'>{@link Assertion} 105 * <ul class='javatreec'> 106 * <li class='jm'>{@link Assertion#setMsg(String, Object...) setMsg(String, Object...)} 107 * <li class='jm'>{@link Assertion#setOut(PrintStream) setOut(PrintStream)} 108 * <li class='jm'>{@link Assertion#setSilent() setSilent()} 109 * <li class='jm'>{@link Assertion#setStdOut() setStdOut()} 110 * <li class='jm'>{@link Assertion#setThrowable(Class) setThrowable(Class)} 111 * </ul> 112 * </ul> 113 * 114 * <h5 class='section'>See Also:</h5><ul> 115 * <li class='link'><a class="doclink" href="../../../../index.html#ja.Overview">Overview > juneau-assertions > Overview</a> 116 * </ul> 117 * 118 * @param <R> The return type. 119 */ 120@FluentSetters(returns="FluentDateAssertion<R>") 121public class FluentDateAssertion<R> extends FluentComparableAssertion<Date,R> { 122 123 //----------------------------------------------------------------------------------------------------------------- 124 // Static 125 //----------------------------------------------------------------------------------------------------------------- 126 127 private static final Messages MESSAGES = Messages.of(FluentDateAssertion.class, "Messages"); 128 private static final String 129 MSG_unexpectedValue = MESSAGES.getString("unexpectedValue"), 130 MSG_valueWasNotAfterExpected = MESSAGES.getString("valueWasNotAfterExpected"), 131 MSG_valueWasNotBeforeExpected = MESSAGES.getString("valueWasNotBeforeExpected"); 132 133 //----------------------------------------------------------------------------------------------------------------- 134 // Instance 135 //----------------------------------------------------------------------------------------------------------------- 136 137 /** 138 * Constructor. 139 * 140 * @param value 141 * The object being tested. 142 * <br>Can be <jk>null</jk>. 143 * @param returns 144 * The object to return after a test method is called. 145 * <br>If <jk>null</jk>, the test method returns this object allowing multiple test method calls to be 146 * used on the same assertion. 147 */ 148 public FluentDateAssertion(Date value, R returns) { 149 this(null, value, returns); 150 } 151 152 /** 153 * Chained constructor. 154 * 155 * <p> 156 * Used when transforming one assertion into another so that the assertion config can be used by the new assertion. 157 * 158 * @param creator 159 * The assertion that created this assertion. 160 * <br>Should be <jk>null</jk> if this is the top-level assertion. 161 * @param value 162 * The object being tested. 163 * <br>Can be <jk>null</jk>. 164 * @param returns 165 * The object to return after a test method is called. 166 * <br>If <jk>null</jk>, the test method returns this object allowing multiple test method calls to be 167 * used on the same assertion. 168 */ 169 public FluentDateAssertion(Assertion creator, Date value, R returns) { 170 super(creator, value, returns); 171 } 172 173 //----------------------------------------------------------------------------------------------------------------- 174 // Transform methods 175 //----------------------------------------------------------------------------------------------------------------- 176 177 /** 178 * Returns an long assertion on the epoch milliseconds of this date. 179 * 180 * <p> 181 * If the date is <jk>null</jk>, the returned assertion is a null assertion 182 * (meaning {@link FluentLongAssertion#isExists()} returns <jk>false</jk>). 183 * 184 * @return A new assertion. 185 */ 186 public FluentLongAssertion<R> asEpochMillis() { 187 return new FluentLongAssertion<>(this, valueIsNull() ? null : value().getTime(), returns()); 188 } 189 190 /** 191 * Returns an long assertion on the epoch seconds of this date. 192 * 193 * <p> 194 * If the date is <jk>null</jk>, the returned assertion is a null assertion 195 * (meaning {@link FluentLongAssertion#isExists()} returns <jk>false</jk>). 196 * 197 * @return A new assertion. 198 */ 199 public FluentLongAssertion<R> asEpochSeconds() { 200 return new FluentLongAssertion<>(this, valueIsNull() ? null : value().getTime() / 1000, returns()); 201 } 202 203 //----------------------------------------------------------------------------------------------------------------- 204 // Test methods 205 //----------------------------------------------------------------------------------------------------------------- 206 207 /** 208 * Asserts that the value equals the specified value at the specified precision. 209 * 210 * @param value The value to check against. 211 * @param precision The precision (e.g. {@link ChronoUnit#SECONDS}). 212 * @return The fluent return object. 213 * @throws AssertionError If assertion failed. 214 */ 215 public R is(Date value, ChronoUnit precision) throws AssertionError { 216 if (ne(value(), value, (x,y)->x.toInstant().truncatedTo(precision).equals(y.toInstant().truncatedTo(precision)))) 217 throw error(MSG_unexpectedValue, value, value()); 218 return returns(); 219 } 220 221 /** 222 * Asserts that the value is after the specified value. 223 * 224 * @param value The values to check against. 225 * @return The fluent return object. 226 * @throws AssertionError If assertion failed. 227 */ 228 public R isAfter(Date value) throws AssertionError { 229 assertArgNotNull("value", value); 230 if (! (value().after(value))) 231 throw error(MSG_valueWasNotAfterExpected, value, value()); 232 return returns(); 233 } 234 235 /** 236 * Asserts that the value is after the current date. 237 * 238 * @return The fluent return object. 239 * @throws AssertionError If assertion failed. 240 */ 241 public R isAfterNow() throws AssertionError { 242 return isAfter(new Date()); 243 } 244 245 /** 246 * Asserts that the value is before the specified value. 247 * 248 * @param value The values to check against. 249 * @return The fluent return object. 250 * @throws AssertionError If assertion failed. 251 */ 252 public R isBefore(Date value) throws AssertionError { 253 assertArgNotNull("value", value); 254 if (! (value().before(value))) 255 throw error(MSG_valueWasNotBeforeExpected, value, value()); 256 return returns(); 257 } 258 259 /** 260 * Asserts that the value is before the current date. 261 * 262 * @return The fluent return object. 263 * @throws AssertionError If assertion failed. 264 */ 265 public R isBeforeNow() throws AssertionError { 266 return isBefore(new Date()); 267 } 268 269 /** 270 * Asserts that the value is between (inclusive) the specified upper and lower values. 271 * 272 * @param lower The lower value to check against. 273 * @param upper The upper value to check against. 274 * @return The fluent return object. 275 * @throws AssertionError If assertion failed. 276 */ 277 public R isBetween(Date lower, Date upper) throws AssertionError { 278 isExists(); 279 assertArgNotNull("lower", lower); 280 assertArgNotNull("upper", upper); 281 isLte(upper); 282 isGte(lower); 283 return returns(); 284 } 285 286 //----------------------------------------------------------------------------------------------------------------- 287 // Fluent setters 288 //----------------------------------------------------------------------------------------------------------------- 289 290 // <FluentSetters> 291 292 @Override /* GENERATED - org.apache.juneau.assertions.Assertion */ 293 public FluentDateAssertion<R> setMsg(String msg, Object...args) { 294 super.setMsg(msg, args); 295 return this; 296 } 297 298 @Override /* GENERATED - org.apache.juneau.assertions.Assertion */ 299 public FluentDateAssertion<R> setOut(PrintStream value) { 300 super.setOut(value); 301 return this; 302 } 303 304 @Override /* GENERATED - org.apache.juneau.assertions.Assertion */ 305 public FluentDateAssertion<R> setSilent() { 306 super.setSilent(); 307 return this; 308 } 309 310 @Override /* GENERATED - org.apache.juneau.assertions.Assertion */ 311 public FluentDateAssertion<R> setStdOut() { 312 super.setStdOut(); 313 return this; 314 } 315 316 @Override /* GENERATED - org.apache.juneau.assertions.Assertion */ 317 public FluentDateAssertion<R> setThrowable(Class<? extends java.lang.RuntimeException> value) { 318 super.setThrowable(value); 319 return this; 320 } 321 322 // </FluentSetters> 323}