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 java.util.function.*;
016
017import org.apache.juneau.internal.*;
018
019/**
020 * Utility class for performing simple validations on objects.
021 *
022 * <p>
023 * Verifications that pass return a null string.  Verifications that don't pass return a string with a useful
024 * error message.
025 *
026 * <h5 class='section'>Example:</h5>
027 * <p class='bcode w800'>
028 *    <jc>// Validates that our POJO is of type MyBean.</jc>
029 *    String errorMessage = <jsm>verify</jsm>(myPojo).isType(MyBean.<jk>class</jk>);
030 *    <jk>if</jk> (errorMessage != <jk>null</jk>)
031 *       <jk>throw new</jk> RuntimeException(errorMessage);
032 * </p>
033 */
034public class Verify {
035
036   private final Object o;
037   private Supplier<String> msg;
038
039   /**
040    * Create a new verifier object.
041    *
042    * @param o The object being verified.
043    * @return A new verifier object.
044    */
045   public static Verify verify(Object o) {
046      return new Verify(o);
047   }
048
049   /**
050    * Create a new verifier object.
051    *
052    * @param o The object being verified.
053    */
054   protected Verify(Object o) {
055      this.o = o;
056   }
057
058   /**
059    * Overrides the default error message produced by the verification.
060    *
061    * @param msg The error message.
062    * @param args Optional message arguments.
063    * @return This object (for method chaining).
064    */
065   public Verify msg(String msg, Object args) {
066      this.msg = () -> StringUtils.format(msg, args);
067      return this;
068   }
069
070   /**
071    * Verifies that this object is of the specified type.
072    *
073    * @param type The type to test against.
074    * @return An error message if the object is not of the specified type, otherwise <jk>null</jk>.
075    */
076   public String isType(Class<?> type) {
077      if (type == null && o == null)
078         return null;
079      if (type != null && type.isInstance(o))
080         return null;
081      return msg != null ? msg.get() : StringUtils.format("Expected type [{0}] but was [{1}].", type, (o == null ? null : o.getClass()));
082   }
083
084   /**
085    * Verifies that this object is equal to the specified object.
086    *
087    * @param expected The object to test against for equality.
088    * @return An error message if the object is not equal to the specified object, otherwise <jk>null</jk>.
089    */
090   public String is(Object expected) {
091      if (expected == o)
092         return null;
093      if (expected == null || o == null)
094         return msg != null ? msg.get() : StringUtils.format("Expected [{0}] but was [{1}].", expected, o);
095      if (! expected.equals(o))
096         return msg != null ? msg.get() : StringUtils.format("Expected [{0}] but was [{1}].", expected, o);
097      return null;
098   }
099
100   /**
101    * Verifies that this object is equal to {@link Boolean#TRUE}.
102    *
103    * @return An error message if the object is not true, otherwise <jk>null</jk>.
104    */
105   public String isTrue() {
106      return is(true);
107   }
108
109   /**
110    * Verifies that this object is equal to {@link Boolean#FALSE}.
111    *
112    * @return An error message if the object is not false, otherwise <jk>null</jk>.
113    */
114   public String isFalse() {
115      return is(false);
116   }
117}