/*
 * Created on Jul 1, 2010
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 *
 * Copyright @2010-2013 the original author or authors.
 */
package org.fest.assertions;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.List;
import java.util.Set;

import static org.fest.assertions.Collections.found;
import static org.fest.assertions.Collections.notFound;
import static org.fest.assertions.Formatting.format;
import static org.fest.util.Collections.duplicatesFrom;
import static org.fest.util.Lists.emptyList;
import static org.fest.util.Lists.newArrayList;
import static org.fest.util.Preconditions.checkNotNull;
import static org.fest.util.Sets.newLinkedHashSet;

/**
 * Template for assertions for groups of items (e.g. collections or arrays.)
 *
 * @param <S> used to simulate "self types." For more information please read "Emulating 'self types' using Java Generics to simplify fluent API
 *            implementation."
 * @param  the type the "actual" value.
 * @author Yvonne Wang
 * @since 1.3
 */
public abstract class ItemGroupAssert<S, A> extends GroupAssert<S, A> {
  /**
   * Creates a new {@link ItemGroupAssert}.
   *
   * @param selfType the "self type."
   * @param actual   the actual group.
   */
  public ItemGroupAssert(@NotNull Class<S> selfType, @Nullable A actual) {
    super(selfType, actual);
  }

  /**
   * Verifies that the actual actual group of objects contains the given objects, in any order.
   *
   * @param objects the objects to look for.
   * @throws AssertionError       if the actual actual group of objects is {@code null}.
   * @throws NullPointerException if the given array is {@code null}.
   * @throws AssertionError       if the actual actual group of objects does not contain the given objects.
   */
  protected final void assertContains(@NotNull Object... objects) {
    isNotNull();
    checkNotNull(objects);
    Collection<Object> notFound = notFoundInActual(objects);
    if (notFound.isEmpty()) {
      return;
    }
    throw failureIfExpectedElementsNotFound(notFound);
  }

  private Collection<Object> notFoundInActual(@NotNull Object... objects) {
    return notFound(actualAsSet(), objects);
  }

  /**
   * Verifies that the actual group of objects contains the given objects only, in any order.
   *
   * @param objects the objects to look for.
   * @throws AssertionError       if the actual group of objects is {@code null}.
   * @throws NullPointerException if the given group of objects is {@code null}.
   * @throws AssertionError       if the actual group of objects does not contain the given objects, or if the actual
   *                              group of objects contains elements other than the ones specified.
   */
  protected final void assertContainsOnly(@NotNull Object... objects) {
    isNotNull();
    checkNotNull(objects);
    Set<Object> copy = actualAsSet();
    List<Object> notFound = notFoundInCopy(copy, newLinkedHashSet(objects));
    if (!notFound.isEmpty()) {
      throw failureIfExpectedElementsNotFound(notFound);
    }
    if (copy == null || copy.isEmpty()) {
      return;
    }
    throw failureIfUnexpectedElementsFound(copy);
  }

  /**
   * @return the actual value as a {@code Set}.
   */
  protected abstract @Nullable Set<Object> actualAsSet();

  private @NotNull List<Object> notFoundInCopy(@Nullable Set<Object> copy, @NotNull Set<Object> objects) {
    if (copy == null) {
      return emptyList();
    }
    List<Object> notFound = newArrayList();
    for (Object o : objects) {
      if (!copy.contains(o)) {
        notFound.add(o);
        continue;
      }
      copy.remove(o);
    }
    return notFound;
  }

  private @NotNull AssertionError failureIfExpectedElementsNotFound(@NotNull Collection<Object> notFound) {
    failIfCustomMessageIsSet();
    return failure(format("<%s> does not contain element(s):<%s>", actual, notFound));
  }

  private @NotNull AssertionError failureIfUnexpectedElementsFound(@NotNull Collection<Object> unexpected) {
    failIfCustomMessageIsSet();
    return failure(format("unexpected element(s):<%s> in <%s>", unexpected, actual));
  }

  /**
   * Verifies that the actual group of objects does not contain the given objects.
   *
   * @param objects the objects that the group of objects should exclude.
   * @throws AssertionError       if the actual group of objects is {@code null}.
   * @throws NullPointerException if the given array is {@code null}.
   * @throws AssertionError       if the actual group of objects contains any of the given objects.
   */
  protected final void assertExcludes(@NotNull Object... objects) {
    isNotNull();
    checkNotNull(objects);
    Collection<Object> found = found(actualAsSet(), objects);
    if (found.isEmpty()) {
      return;
    }
    failIfCustomMessageIsSet();
    throw failure(format("<%s> does not exclude element(s):<%s>", actual, found));
  }

  /**
   * Verifies that the actual group of objects does not have duplicates.
   *
   * @throws AssertionError if the actual group of objects is {@code null}.
   * @throws AssertionError if the actual group of objects has duplicates.
   */
  protected final void assertDoesNotHaveDuplicates() {
    isNotNull();
    Collection<?> duplicates = duplicatesFrom(actualAsList());
    if (duplicates.isEmpty()) {
      return;
    }
    failIfCustomMessageIsSet();
    throw failure(format("<%s> contains duplicate(s):<%s>", actual, duplicates));
  }

  /**
   * @return the actual value as a {@code List}.
   */
  protected abstract @Nullable List<Object> actualAsList();

}


/*
 * Created on Sep 14, 2007
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 *
 * Copyright @2007-2013 the original author or authors.
 */
package org.fest.assertions;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.IllegalFormatException;

import static org.fest.util.Preconditions.checkNotNull;
import static org.fest.util.Strings.concat;
import static org.fest.util.Strings.isNullOrEmpty;
import static org.fest.util.ToString.toStringOf;

/**
 * Utility methods for formatting values.
 *
 * @author Yvonne Wang
 * @author Alex Ruiz
 */
public final class Formatting {
  private static final String EMPTY_MESSAGE = "";

  private Formatting() {
  }

  static @NotNull String createMessageFrom(@Nullable Description description, @NotNull Object[] message) {
    return format(description, concat(message));
  }

  /**
   * Returns the given message formatted as follows:
   *

   * [description] message.
   *

   *
   * @param description the description of the actual value in the failed assertion. It can be {@code null}.
   * @param message     the message to format.
   * @return the formatted message.
   * @throws NullPointerException if the given message is {@code null}.
   * @since 1.2
   */
  public static @NotNull String format(@Nullable Description description, @NotNull String message) {
    checkNotNull(message);
    String s = valueOf(description);
    return format(s) + message;
  }

  /**
   * Returns the value of the given {@link Description}.
   *
   * @param description the given {@code Description}.
   * @return the value of the given {@code Description}, or {@code null} if the given {@code Description} is
   *         {@code null}.
   */
  public static @Nullable String valueOf(@Nullable Description description) {
    return description == null ? null : description.value();
  }

  /**
   * Formats the given message:
if it is {@code null} or empty, an empty {@code String} is returned, otherwise uses
   * the following format:
   *

   * [message]{whitespace}
   *

   *
   * @param message the message to format.
   * @return the formatted message.
   */
  public static @NotNull String format(@Nullable String message) {
    if (isNullOrEmpty(message)) {
      return EMPTY_MESSAGE;
    }
    return String.format("[%s] ", message);
  }

  /**
   * Returns the {@code String} representation of the given object in between brackets ("<" and ">"). This method has
   * special support for arrays, {@code Class<?>}, {@code Collection}s, {@code Map}s, {@code File}s and
   * {@code Dimension}s. For any other types, this method simply calls its {@code toString} implementation.
   *
   * @param o the given object.
   * @return the {@code String} representation of the given object in between brackets.
   */
  public static @NotNull String inBrackets(@Nullable Object o) {
    return doBracketAround(toStringOf(o));
  }

  private static @NotNull String doBracketAround(@Nullable String s) {
    return String.format("<%s>", s);
  }

  /**
   * Returns a formatted string using the specified format {@code String} and arguments.
   *
   * @param format a format {@code String}.
   * @param args   Arguments referenced by the format specifiers in the format {@code String}. If there are more
   *               arguments than format specifiers, the extra arguments are ignored. The number of arguments is
   *               variable and may be zero.
   * @return A formatted {@code String}.
   * @throws IllegalFormatException If a format string contains an illegal syntax, a format specifier that is
   *                                incompatible with the given arguments, insufficient arguments given the format
   *                                {@code String}, or other illegal conditions.
   * @throws NullPointerException   if the given format is {@code null}.
   * @since 1.3.1
   */
  public static @NotNull String format(@NotNull String format, @NotNull Object... args) {
    Object[] argsAsText = new String[args.length];
    for (int i = 0; i < args.length; i++) {
      argsAsText[i] = toStringOf(args[i]);
    }
    return String.format(format, argsAsText);
  }
}


/*
 * Created on Dec 27, 2006
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 *
 * Copyright @2006-2013 the original author or authors.
 */
package org.fest.assertions;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.awt.image.BufferedImage;
import java.io.File;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * Entry point for assertion methods for different data types. Each method in this class is a static factory for the
 * type-specific assertion objects. The purpose of this class is to make test code more readable.
 *

 * For example:
 *

 * int removed = employees.removeFired();
 * {@link org.fest.assertions.Assertions#assertThat(int) assertThat}(removed).{@link org.fest.assertions.IntAssert#isZero isZero}();
 *
 * List<Employee> newEmployees = employees.hired(TODAY);
 * {@link org.fest.assertions.Assertions#assertThat(java.util.Collection) assertThat}(newEmployees).{@link org.fest.assertions.CollectionAssert#hasSize(int) hasSize}(6);
 *

 *
 * @author Alex Ruiz
 * @author Yvonne Wang
 * @author David DIDIER
 * @author Ted Young
 */
public class Assertions {
  /**
   * This constructor is protected to make it possible to subclass this class. Since all its methods are static, there
   * is no point on creating a new instance of it.
   */
  protected Assertions() {
  }

  /**
   * Creates a new instance of {@link BigDecimalAssert}.
   *
   * @param actual the value to be the target of the assertions methods.
   * @return the created assertion object.
   */
  public static @NotNull BigDecimalAssert assertThat(@Nullable BigDecimal actual) {
    return new BigDecimalAssert(actual);
  }

  /**
   * Creates a new instance of {@link BooleanAssert}.
   *
   * @param actual the value to be the target of the assertions methods.
   * @return the created assertion object.
   */
  public static @NotNull BooleanAssert assertThat(boolean actual) {
    return new BooleanAssert(actual);
  }

  /**
   * Creates a new instance of {@link BooleanAssert}.
   *
   * @param actual the value to be the target of the assertions methods.
   * @return the created assertion object.
   */
  public static @NotNull BooleanAssert assertThat(@Nullable Boolean actual) {
    return new BooleanAssert(actual);
  }

  /**
   * Creates a new instance of {@link BooleanArrayAssert}.
   *
   * @param actual the value to be the target of the assertions methods.
   * @return the created assertion object.
   */
  public static @NotNull BooleanArrayAssert assertThat(@Nullable boolean[] actual) {
    return new BooleanArrayAssert(actual);
  }

  /**
   * Creates a new instance of {@link ImageAssert}.
   *
   * @param actual the value to be the target of the assertions methods.
   * @return the created assertion object.
   */
  public static @NotNull ImageAssert assertThat(@Nullable BufferedImage actual) {
    return new ImageAssert(actual);
  }

  /**
   * Creates a new instance of {@link ByteAssert}.
   *
   * @param actual the value to be the target of the assertions methods.
   * @return the created assertion object.
   */
  public static @NotNull ByteAssert assertThat(byte actual) {
    return new ByteAssert(actual);
  }

  /**
   * Creates a new instance of {@link ByteAssert}.
   *
   * @param actual the value to be the target of the assertions methods.
   * @return the created assertion object.
   */
  public static @NotNull ByteAssert assertThat(@Nullable Byte actual) {
    return new ByteAssert(actual);
  }

  /**
   * Creates a new instance of {@link ByteArrayAssert}.
   *
   * @param actual the value to be the target of the assertions methods.
   * @return the created assertion object.
   */
  public static @NotNull ByteArrayAssert assertThat(@Nullable byte[] actual) {
    return new ByteArrayAssert(actual);
  }

  /**
   * Creates a new instance of {@link CharAssert}.
   *
   * @param actual the value to be the target of the assertions methods.
   * @return the created assertion object.
   */
  public static @NotNull CharAssert assertThat(char actual) {
    return new CharAssert(actual);
  }

  /**
   * Creates a new instance of {@link CharAssert}.
   *
   * @param actual the value to be the target of the assertions methods.
   * @return the created assertion object.
   */
  public static @NotNull CharAssert assertThat(@Nullable Character actual) {
    return new CharAssert(actual);
  }

  /**
   * Creates a new instance of {@link CharArrayAssert}.
   *
   * @param actual the value to be the target of the assertions methods.
   * @return the created assertion object.
   */
  public static @NotNull CharArrayAssert assertThat(@Nullable char[] actual) {
    return new CharArrayAssert(actual);
  }

  /**
   * Creates a new instance of {@link CollectionAssert}.
   *
   * @param actual the value to be the target of the assertions methods.
   * @return the created assertion object.
   */
  public static @NotNull CollectionAssert assertThat(@Nullable Collection<?> actual) {
    return new CollectionAssert(actual);
  }

  /**
   * Creates a new instance of {@link ListAssert}.
   *
   * @param actual the value to be the target of the assertions methods.
   * @return the created assertion object.
   * @since 1.1
   */
  public static @NotNull ListAssert assertThat(@Nullable List<?> actual) {
    return new ListAssert(actual);
  }

  /**
   * Creates a new instance of {@link DoubleAssert}.
   *
   * @param actual the value to be the target of the assertions methods.
   * @return the created assertion object.
   */
  public static @NotNull DoubleAssert assertThat(double actual) {
    return new DoubleAssert(actual);
  }

  /**
   * Creates a new instance of {@link DoubleAssert}.
   *
   * @param actual the value to be the target of the assertions methods.
   * @return the created assertion object.
   */
  public static @NotNull DoubleAssert assertThat(@Nullable Double actual) {
    return new DoubleAssert(actual);
  }

  /**
   * Creates a new instance of {@link DoubleArrayAssert}.
   *
   * @param actual the value to be the target of the assertions methods.
   * @return the created assertion object.
   */
  public static @NotNull DoubleArrayAssert assertThat(@Nullable double[] actual) {
    return new DoubleArrayAssert(actual);
  }

  /**
   * Creates a new instance of {@link FileAssert}.
   *
   * @param actual the value to be the target of the assertions methods.
   * @return the created assertion object.
   */
  public static @NotNull FileAssert assertThat(@Nullable File actual) {
    return new FileAssert(actual);
  }

  /**
   * Creates a new instance of {@link FloatAssert}.
   *
   * @param actual the value to be the target of the assertions methods.
   * @return the created assertion object.
   */
  public static @NotNull FloatAssert assertThat(float actual) {
    return new FloatAssert(actual);
  }

  /**
   * Creates a new instance of {@link FloatAssert}.
   *
   * @param actual the value to be the target of the assertions methods.
   * @return the created assertion object.
   */
  public static @NotNull FloatAssert assertThat(@Nullable Float actual) {
    return new FloatAssert(actual);
  }

  /**
   * Creates a new instance of {@link FloatArrayAssert}.
   *
   * @param actual the value to be the target of the assertions methods.
   * @return the created assertion object.
   */
  public static @NotNull FloatArrayAssert assertThat(@Nullable float[] actual) {
    return new FloatArrayAssert(actual);
  }

  /**
   * Creates a new instance of {@link IntAssert}.
   *
   * @param actual the value to be the target of the assertions methods.
   * @return the created assertion object.
   */
  public static @NotNull IntAssert assertThat(int actual) {
    return new IntAssert(actual);
  }

  /**
   * Creates a new instance of {@link IntAssert}.
   *
   * @param actual the value to be the target of the assertions methods.
   * @return the created assertion object.
   */
  public static @NotNull IntAssert assertThat(@Nullable Integer actual) {
    return new IntAssert(actual);
  }

  /**
   * Creates a new instance of {@link IntArrayAssert}.
   *
   * @param actual the value to be the target of the assertions methods.
   * @return the created assertion object.
   */
  public static @NotNull IntArrayAssert assertThat(@Nullable int[] actual) {
    return new IntArrayAssert(actual);
  }

  /**
   * Creates a new instance of {@link IteratorAssert}.
   *
   * @param actual an {@code Iterable} whose contents will be added to a new {@code Collection}.
   * @return the created assertion object.
   */
  public static @NotNull IteratorAssert assertThat(@Nullable Iterable<?> actual) {
    Iterator<?> iterator = actual == null ? null : actual.iterator();
    return assertThat(iterator);
  }

  /**
   * Creates a new instance of {@link IteratorAssert}.
   *
   * @param actual an {@code Iterator} whose contents will be added to a new {@code Collection}.
   * @return the created assertion object.
   */
  public static @NotNull IteratorAssert assertThat(@Nullable Iterator<?> actual) {
    return new IteratorAssert(actual);
  }

  /**
   * Creates a new instance of {@link LongAssert}.
   *
   * @param actual the value to be the target of the assertions methods.
   * @return the created assertion object.
   */
  public static @NotNull LongAssert assertThat(long actual) {
    return new LongAssert(actual);
  }

  /**
   * Creates a new instance of {@link LongAssert}.
   *
   * @param actual the value to be the target of the assertions methods.
   * @return the created assertion object.
   */
  public static @NotNull LongAssert assertThat(@Nullable Long actual) {
    return new LongAssert(actual);
  }

  /**
   * Creates a new instance of {@link LongArrayAssert}.
   *
   * @param actual the value to be the target of the assertions methods.
   * @return the created assertion object.
   */
  public static @NotNull LongArrayAssert assertThat(@Nullable long[] actual) {
    return new LongArrayAssert(actual);
  }

  /**
   * Creates a new instance of {@link MapAssert}.
   *
   * @param actual the value to be the target of the assertions methods.
   * @return the created assertion object.
   */
  public static @NotNull MapAssert assertThat(@Nullable Map<?, ?> actual) {
    return new MapAssert(actual);
  }

  /**
   * Creates a new instance of {@link ObjectAssert}.
   *
   * @param actual the value to be the target of the assertions methods.
   * @return the created assertion object.
   */
  public static @NotNull ObjectAssert assertThat(@Nullable Object actual) {
    return new ObjectAssert(actual);
  }

  /**
   * Creates a new instance of {@link ObjectArrayAssert}.
   *
   * @param actual the value to be the target of the assertions methods.
   * @return the created assertion object.
   */
  public static @NotNull ObjectArrayAssert assertThat(@Nullable Object[] actual) {
    return new ObjectArrayAssert(actual);
  }

  /**
   * Creates a new instance of {@link ShortAssert}.
   *
   * @param actual the value to be the target of the assertions methods.
   * @return the created assertion object.
   */
  public static @NotNull ShortAssert assertThat(short actual) {
    return new ShortAssert(actual);
  }

  /**
   * Creates a new instance of {@link ShortAssert}.
   *
   * @param actual the value to be the target of the assertions methods.
   * @return the created assertion object.
   */
  public static @NotNull ShortAssert assertThat(@Nullable Short actual) {
    return new ShortAssert(actual);
  }

  /**
   * Creates a new instance of {@link ShortArrayAssert}.
   *
   * @param actual the value to be the target of the assertions methods.
   * @return the created assertion object.
   */
  public static @NotNull ShortArrayAssert assertThat(@Nullable short[] actual) {
    return new ShortArrayAssert(actual);
  }

  /**
   * Creates a new instance of {@link StringAssert}.
   *
   * @param actual the value to be the target of the assertions methods.
   * @return the created assertion object.
   */
  public static @NotNull StringAssert assertThat(@Nullable String actual) {
    return new StringAssert(actual);
  }

  /**
   * Returns the given assertion. This method improves code readability by surrounding the given assertion with
   * "{@code assertThat}".
   *

   * For example, let's assume we have the following custom assertion class:
   *

   * public class ServerSocketAssertion implements AssertExtension {
   *   private final ServerSocket socket;
   *
   *   public ServerSocketAssertion(ServerSocket socket) {
   *     this.socket = socket;
   *   }
   *
   *   public ServerSocketAssert isConnectedTo(int port) {
   *     assertThat(socket.isBound()).isTrue();
   *     assertThat(socket.getLocalPort()).isEqualTo(port);
   *     assertThat(socket.isClosed()).isFalse();
   *     return this;
   *   }
   * }
   *

   *

   * We can wrap that assertion with "{@code assertThat}" to improve test code readability.
   *

   * ServerSocketAssertion socket = new ServerSocketAssertion(server.getSocket());
   * assertThat(socket).isConnectedTo(2000);
   *

   *
   * @param assertion the assertion to return.
   * @return the given assertion.
   * @throws NullPointerException if the given assertion is {@code null}.
   */
  public static @NotNull <T extends AssertExtension> T assertThat(@NotNull T assertion) {
    return assertion;
  }

  /**
   * Creates a new instance of {@link ThrowableAssert}.
   *
   * @param actual the value to be the target of the assertions methods.
   * @return the created assertion object.
   */
  public static @NotNull ThrowableAssert assertThat(@Nullable Throwable actual) {
    return new ThrowableAssert(actual);
  }
}


/*
 * Created on Jun 18, 2007
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 *
 * Copyright @2007-2013 the original author or authors.
 */
package org.fest.assertions;

import org.jetbrains.annotations.NotNull;

import static java.lang.Character.valueOf;
import static org.fest.assertions.ErrorMessages.*;

/**
 * Assertions for {@code Character}s and {@code char}s.
 * <p/>
 * To create a new instance of this class invoke either {@link Assertions#assertThat(Character)} or
 * {@link Assertions#assertThat(char)}.
 *
 * @author Yvonne Wang
 * @author David DIDIER
 * @author Ansgar Konermann
 * @author Alex Ruiz
 */
public class CharAssert extends GenericAssert<CharAssert, Character> {
  /**
   * Creates a new {@link CharAssert}.
   *
   * @param actual the actual value to verify.
   */
  protected CharAssert(char actual) {
    super(CharAssert.class, actual);
  }

  /**
   * Creates a new {@link CharAssert}.
   *
   * @param actual the actual value to verify.
   */
  protected CharAssert(Character actual) {
    super(CharAssert.class, actual);
  }

  /**
   * Verifies that the {@code Character} value is equal to the given one.
   *
   * @param expected the value to compare the actual one to.
   * @return this assertion object.
   * @throws AssertionError if the {@code Character} value is not equal to the given one.
   */
  public @NotNull CharAssert isEqualTo(char expected) {
    return isEqualTo(valueOf(expected));
  }

  /**
   * Verifies that the {@code Character} value is not equal to the given one.
   *
   * @param other the given value.
   * @return this assertion object.
   * @throws AssertionError if the {@code Character} value is equal to the given one.
   */
  public @NotNull CharAssert isNotEqualTo(char other) {
    return isNotEqualTo(valueOf(other));
  }

  /**
   * Verifies that the {@code Character} value is greater than the given one.
   *
   * @param other the given value.
   * @return this assertion object.
   * @throws AssertionError if the {@code Character} value is not greater than the given one.
   */
  public @NotNull CharAssert isGreaterThan(char other) {
    if (actual > other) {
      return this;
    }
    failIfCustomMessageIsSet();
    throw failure(unexpectedLessThanOrEqualTo(actual, other));
  }

  /**
   * Verifies that the {@code Character} value is less than the given one.
   *
   * @param other the given value.
   * @return this assertion object.
   * @throws AssertionError if the {@code Character} value is not less than the given one.
   */
  public @NotNull CharAssert isLessThan(char other) {
    if (actual < other) {
      return this;
    }
    failIfCustomMessageIsSet();
    throw failure(unexpectedGreaterThanOrEqualTo(actual, other));
  }

  /**
   * Verifies that the {@code Character} value is greater or equal to the given one.
   *
   * @param other the given value.
   * @return this assertion object.
   * @throws AssertionError if the {@code Character} value is not greater than or equal to the given one.
   */
  public @NotNull CharAssert isGreaterThanOrEqualTo(char other) {
    if (actual >= other) {
      return this;
    }
    failIfCustomMessageIsSet();
    throw failure(unexpectedLessThan(actual, other));
  }

  /**
   * Verifies that the {@code Character} value is less or equal to the given one.
   *
   * @param other the given value.
   * @return this assertion object.
   * @throws AssertionError if the {@code Character} value is not less than or equal to the given one.
   */
  public @NotNull CharAssert isLessThanOrEqualTo(char other) {
    if (actual <= other) {
      return this;
    }
    failIfCustomMessageIsSet();
    throw failure(unexpectedGreaterThan(actual, other));
  }

  /**
   * Verifies that the {@code Character} value is an upper-case value.
   *
   * @return this assertion object.
   * @throws AssertionError if the {@code Character} value is not an upper-case value.
   */
  public @NotNull CharAssert isUpperCase() {
    if (Character.isUpperCase(actual)) {
      return this;
    }
    failIfCustomMessageIsSet();
    throw failure(String.format("<%s> should be an upper-case character", actual));
  }

  /**
   * Verifies that the {@code Character} value is an lower-case value.
   *
   * @return this assertion object.
   * @throws AssertionError if the {@code Character} value is not an lower-case value.
   */
  public @NotNull CharAssert isLowerCase() {
    if (Character.isLowerCase(actual)) {
      return this;
    }
    failIfCustomMessageIsSet();
    throw failure(String.format("<%s> should be a lower-case character", actual));
  }
}


/*
 * Created on Mar 19, 2007
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 *
 * Copyright @2007-2013 the original author or authors.
 */
package org.fest.assertions;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import static org.fest.assertions.ComparisonFailureFactory.comparisonFailure;
import static org.fest.assertions.ErrorMessages.unexpectedEqual;
import static org.fest.assertions.ErrorMessages.unexpectedNotEqual;
import static org.fest.assertions.Formatting.*;
import static org.fest.util.Arrays.array;
import static org.fest.util.Objects.areEqual;

/**
 * Common failures.
 *
 * @author Alex Ruiz
 * @author Yvonne Wang
 */
public final class Fail {
  /**
   * This constructor is protected to make it possible to subclass this class. Since all its methods are static, there
   * is no point on creating a new instance of it.
   */
  protected Fail() {
  }

  /**
   * Fails with no message.
   *
   * @throws AssertionError without any message.
   */
  public static void fail() {
    fail(null);
  }

  /**
   * Throws an {@code AssertionError} if the given objects are equal.
   *
   * @param customErrorMessage  any custom error message. This message will replace the default one only if it (the
   *                            custom message) is not {@code null}.
   * @param descriptionOfActual the description of the actual value.
   * @param actual              the actual object.
   * @param other               the object to compare to.
   * @throws AssertionError if the given objects are equal.
   * @since 1.2
   */
  protected static void failIfEqual(@Nullable String customErrorMessage, @Nullable Description descriptionOfActual,
                                    @Nullable Object actual, @Nullable Object other) {
    if (!areEqual(actual, other)) {
      return;
    }
    failWithMessage(customErrorMessage);
    fail(format(descriptionOfActual, unexpectedEqual(actual, other)));
  }

  /**
   * Throws an {@code AssertionError} if 'actual' is not equal to 'expected'. If JUnit 4 (or greater) is in the
   * classpath, this method will throw a {@code ComparisonFailure} instead. More details about this feature can be
   * found here.
   *
   * @param customErrorMessage  any custom error message. This message will replace the default one only if it (the
   *                            custom message) is not {@code null}.
   * @param descriptionOfActual the description of the actual value.
   * @param actual              the actual object.
   * @param expected            the expected object.
   * @throws AssertionError if the given objects are not equal.
   * @since 1.2
   */
  protected static void failIfNotEqual(@Nullable String customErrorMessage, @Nullable Description descriptionOfActual,
                                       @Nullable Object actual, @Nullable Object expected) {
    if (areEqual(actual, expected)) {
      return;
    }
    failWithMessage(customErrorMessage);
    throw comparisonFailed(descriptionOfActual, actual, expected);
  }

  /**
   * Returns a {@code AssertionError} describing a comparison failure.
   *
   * @param description the description of the comparison.
   * @param actual      the actual value.
   * @param expected    the expected value.
   * @return a {@code AssertionError} describing the comparison failure.
   * @since 1.3
   */
  protected static @NotNull AssertionError comparisonFailed(
      @Nullable Description description, @Nullable Object actual, @Nullable Object expected) {
    AssertionError comparisonFailure = comparisonFailure(valueOf(description), expected, actual);
    if (comparisonFailure != null) {
      return comparisonFailure;
    }
    return failure(format(description, unexpectedNotEqual(actual, expected)));
  }

  /**
   * Throws an {@code AssertionError} if the actual value is {@code null}.
   *
   * @param customErrorMessage any custom error message. This message will replace the default one only if it (the
   *                           custom message) is not {@code null}.
   * @param description        the description of the actual value.
   * @param actual             the actual value.
   * @throws AssertionError if the actual value is {@code null}.
   * @since 1.3
   */
  protected static void failIfActualIsNull(@Nullable String customErrorMessage, @Nullable Description description,
                                           @Nullable Object actual) {
    if (actual != null) {
      return;
    }
    failWithMessage(customErrorMessage);
    fail(description, array("expecting actual value not to be null"));
  }

  /**
   * Throws an {@code AssertionError} if the given object is {@code null}.
   *
   * @param customErrorMessage any custom error message. This message will replace the default one only if it (the
   *                           custom message) is not {@code null}.
   * @param description        the description of the given object.
   * @param o                  the given object.
   * @throws AssertionError if the given object is {@code null}.
   * @since 1.2
   */
  protected static void failIfNull(@Nullable String customErrorMessage, @Nullable Description description,
                                   @Nullable Object o) {
    if (o != null) {
      return;
    }
    failWithMessage(customErrorMessage);
    fail(description, array("expecting a non-null object, but it was null"));
  }

  /**
   * Throws an {@code AssertionError} if the given object is not {@code null}.
   *
   * @param customErrorMessage any custom error message. This message will replace the default one only if it (the
   *                           custom message) is not {@code null}.
   * @param description        the description of the given object.
   * @param o                  the given object.
   * @throws AssertionError if the given object is not {@code null}.
   * @since 1.2
   */
  protected static void failIfNotNull(@Nullable String customErrorMessage, @Nullable Description description,
                                      @Nullable Object o) {
    if (o == null) {
      return;
    }
    failWithMessage(customErrorMessage);
    fail(description, array(inBrackets(o), " should be null"));
  }

  /**
   * Throws an {@code AssertionError} if the given objects are the same.
   *
   * @param customErrorMessage  any custom error message. This message will replace the default one only if it (the
   *                            custom message) is not {@code null}.
   * @param descriptionOfActual the description of the actual value.
   * @param actual              the actual object.
   * @param other               the object to compare to.
   * @throws AssertionError if the given objects are the same.
   * @since 1.2
   */
  protected static void failIfSame(@Nullable String customErrorMessage, @Nullable Description descriptionOfActual,
                                   @Nullable Object actual, @Nullable Object other) {
    if (actual != other) {
      return;
    }
    failWithMessage(customErrorMessage);
    fail(descriptionOfActual, array("given objects are same:", inBrackets(actual)));
  }

  /**
   * Throws an {@code AssertionError} if the given objects are not the same.
   *
   * @param customErrorMessage  any custom error message. This message will replace the default one only if it (the
   *                            custom message) is not {@code null}.
   * @param descriptionOfActual the description of the actual value.
   * @param actual              the actual object.
   * @param other               the object to compare to.
   * @throws AssertionError if the given objects are not the same.
   * @since 1.2
   */
  protected static void failIfNotSame(@Nullable String customErrorMessage, @Nullable Description descriptionOfActual,
                                      @Nullable Object actual, @Nullable Object other) {
    if (actual == other) {
      return;
    }
    failWithMessage(customErrorMessage);
    fail(descriptionOfActual,
        array("expected same instance but found:", inBrackets(actual), " and:", inBrackets(other)));
  }

  private static void fail(@Nullable Description description, @NotNull Object[] message) {
    throw failure(createMessageFrom(description, message));
  }

  /**
   * Throws an {@code AssertionError} only if the given custom message is not {@code null}.
   *
   * @param customErrorMessage the custom error message.
   * @throws AssertionError only if the custom error message is not {@code null}.
   * @since 1.2
   */
  protected static void failWithMessage(@Nullable String customErrorMessage) {
    if (customErrorMessage != null) {
      fail(customErrorMessage);
    }
  }

  /**
   * Throws an {@code AssertionError} only if the given custom message is not {@code null}.
   *
   * @param customErrorMessage the custom error message.
   * @param realCause          cause of the error.
   * @throws AssertionError only if the custom error message is not {@code null}.
   * @since 1.2
   */
  protected static void failWithMessage(@Nullable String customErrorMessage, Throwable realCause) {
    if (customErrorMessage != null) {
      fail(customErrorMessage, realCause);
    }
  }

  /**
   * Throws an {@code AssertionError} with the given message and with the {@code Throwable} that caused the failure.
   *
   * @param description the description of the failed assertion. It can be {@code null}.
   * @param realCause   cause of the error.
   */
  public static void fail(String description, @Nullable Throwable realCause) {
    AssertionError error = failure(description);
    error.initCause(realCause);
    throw error;
  }

  /**
   * Fails with the given message.
   *

   * Note: This method appears to return {@code AssertionError}, but it is really not the case, since
   * the exception is thrown and not returned. In version 2.0 the return type of this method will change to
   * {@code void}. Since we cannot create an overloaded version with return type {@code void}, we cannot deprecate this
   * method. Please pretend this method does not return anything :)
   *
   * @param message error message.
   * @return the thrown {@code AssertionError}.
   * @throws AssertionError with the given message.
   * @see #failure(String)
   */
  public static @NotNull AssertionError fail(@Nullable String message) {
    // TODO in 2.0: change return type to 'void'
    throw failure(message);
  }

  /**
   * Creates a {@code AssertionError} with the given message.
   *
   * @param message the message of the exception to create.
   * @return the created exception.
   * @since 1.2
   */
  public static @NotNull AssertionError failure(@Nullable String message) {
    return new AssertionError(message);
  }
}


/*
 * Created on Dec 27, 2006
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 *
 * Copyright @2006-2013 the original author or authors.
 */
package org.fest.assertions;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;

import static org.fest.assertions.Formatting.format;
import static org.fest.util.Objects.namesOf;
import static org.fest.util.Preconditions.checkNotNull;

/**
 * Assertions for {@code Object}s.
 * <p/>
 * To create a new instance of this class use the method {@link Assertions#assertThat(Object)}.
 *
 * @author Yvonne Wang
 * @author Alex Ruiz
 */
public class ObjectAssert extends GenericAssert<ObjectAssert, Object> {
  /**
   * Creates a new {@link ObjectAssert}.
   *
   * @param actual the target to verify.
   */
  protected ObjectAssert(@Nullable Object actual) {
    super(ObjectAssert.class, actual);
  }

  /**
   * Verifies that the actual {@code Object} is an instance of the given type.
   *
   * @param type the type to check the actual {@code Object} against.
   * @return this assertion object.
   * @throws AssertionError       if the actual {@code Object} is {@code null}.
   * @throws AssertionError       if the actual {@code Object} is not an instance of the given type.
   * @throws NullPointerException if the given type is {@code null}.
   */
  public @NotNull ObjectAssert isInstanceOf(@NotNull Class<?> type) {
    isNotNull();
    checkNotNull(type);
    Class<?> current = actual.getClass();
    if (type.isAssignableFrom(current)) {
      return this;
    }
    failIfCustomMessageIsSet();
    throw failure(format("expected instance of:<%s> but was instance of:<%s>", type, current));
  }

  /**
   * Verifies that the actual {@code Object} is an instance of any of the given types.
   *
   * @param types the types to check the actual {@code Object} against.
   * @return this assertion object.
   * @throws AssertionError       if the actual {@code Object} is {@code null}.
   * @throws AssertionError       if the actual {@code Object} is not an instance of any of the given types.
   * @throws NullPointerException if the given array of types is {@code null}.
   * @throws NullPointerException if the given array of types contains {@code null}s.
   */
  public @NotNull ObjectAssert isInstanceOfAny(@NotNull Class<?>... types) {
    isNotNull();
    checkNotNull(types);
    if (!foundInstanceOfAny(types)) {
      String format = "expected instance of any:<%s> but was instance of:<%s>";
      fail(String.format(format, typeNames(types), actual.getClass().getName()));
    }
    return this;
  }

  private boolean foundInstanceOfAny(@NotNull Class<?>... types) {
    Class<?> current = actual.getClass();
    for (Class<?> type : types) {
      checkNotNull(type);
      if (type.isAssignableFrom(current)) {
        return true;
      }
    }
    return false;
  }

  private @NotNull String typeNames(@NotNull Class<?>... types) {
    return Arrays.toString(namesOf(types));
  }
}


/*
 * Created on Dec 23, 2007
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 *
 * Copyright @2007-2013 the original author or authors.
 */
package org.fest.assertions;

import org.fest.util.VisibleForTesting;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import static org.fest.assertions.Fail.failIfNotEqual;
import static org.fest.assertions.Formatting.format;
import static org.fest.util.Preconditions.checkNotNull;

/**
 * Assertions for {@code Throwable}.
 * <p/>
 * To create a new instance of this class invoke {@link Assertions#assertThat(Throwable)}.
 *
 * @author David DIDIER
 * @author Alex Ruiz
 */
public class ThrowableAssert extends GenericAssert<ThrowableAssert, Throwable> {
  // TODO remove dependency on ObjectAssert.
  @VisibleForTesting
  final ObjectAssert objectAssert;

  /**
   * Creates a new {@link ThrowableAssert}.
   *
   * @param actual the target to verify.
   */
  protected ThrowableAssert(@Nullable Throwable actual) {
    super(ThrowableAssert.class, actual);
    objectAssert = new ObjectAssert(actual);
  }

  /**
   * Verifies that the actual {@code Throwable} is an instance of the given type.
   *
   * @param type the type to check the actual {@code Throwable} against.
   * @return this assertion object.
   * @throws AssertionError       if the actual {@code Throwable} is {@code null}.
   * @throws AssertionError       if the actual {@code Throwable} is not an instance of the given type.
   * @throws NullPointerException if the given type is {@code null}.
   */
  public @NotNull ThrowableAssert isInstanceOf(@NotNull Class<? extends Throwable> type) {
    objectAssert.isInstanceOf(type);
    return this;
  }

  /**
   * Verifies that the actual {@code Throwable} is an instance of the given type. In order for the assertion to pass,
   * the type of the actual {@code Throwable} has to be exactly the same as the given type.
   *
   * @param type the type to check the actual {@code Throwable} against.
   * @return this assertion object.
   * @throws AssertionError       if the actual {@code Throwable} is {@code null}.
   * @throws AssertionError       if the actual {@code Throwable} is not an instance of the given type.
   * @throws NullPointerException if the given type is {@code null}.
   */
  public @NotNull ThrowableAssert isExactlyInstanceOf(@NotNull Class<?> type) {
    isNotNull();
    checkNotNull(type);
    Class<?> current = actual.getClass();
    if (type.equals(current)) {
      return this;
    }
    failIfCustomMessageIsSet();
    throw failure(format("expected exactly the same type:<%s> but was:<%s>", type, current));
  }

  /**
   * Verifies that the message of the actual {@code Throwable} is equal to the given one.
   *
   * @param message the expected message.
   * @return this assertion error.
   * @throws AssertionError if the actual {@code Throwable} is {@code null}.
   * @throws AssertionError if the message of the actual {@code Throwable} is not equal to the given one.
   */
  public @NotNull ThrowableAssert hasMessage(@Nullable String message) {
    isNotNull();
    failIfNotEqual(customErrorMessage(), rawDescription(), actual.getMessage(), message);
    return this;
  }

  /**
   * Verifies that the actual {@code Throwable} does not have a cause.
   *
   * @return this assertion object.
   * @throws AssertionError if the actual {@code Throwable} is {@code null}.
   * @throws AssertionError if the actual {@code Throwable} has a cause.
   */
  public @NotNull ThrowableAssert hasNoCause() {
    isNotNull();
    Throwable actualCause = actual.getCause();
    if (actualCause == null) {
      return this;
    }
    failIfCustomMessageIsSet();
    throw failure(format("expected exception without cause, but cause was:<%s>", actualCause.getClass()));
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public @NotNull ThrowableAssert as(@Nullable String description) {
    objectAssert.as(description);
    return super.as(description);
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public @NotNull ThrowableAssert describedAs(@Nullable String description) {
    return as(description);
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public @NotNull ThrowableAssert as(@Nullable Description description) {
    objectAssert.as(description);
    return super.as(description);
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public @NotNull ThrowableAssert describedAs(@Nullable Description description) {
    return as(description);
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public @NotNull ThrowableAssert overridingErrorMessage(@Nullable String message) {
    objectAssert.overridingErrorMessage(message);
    return super.overridingErrorMessage(message);
  }
}


/*
 * Created on Jan 23, 2008
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 *
 * Copyright @2008-2013 the original author or authors.
 */
package org.fest.assertions;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import static org.fest.util.Lists.newArrayList;
import static org.fest.util.Preconditions.checkNotNull;
import static org.fest.util.Strings.quote;
import static org.fest.util.ToString.toStringOf;

/**
 * Assertions for {@code Map}s.
 *

 * To create a new instance of this class invoke {@link Assertions#assertThat(Map)}.
 *
 * @author David DIDIER
 * @author Yvonne Wang
 * @author Alex Ruiz
 */
public class MapAssert extends GroupAssert<MapAssert, Map<?, ?>> {
  private static final String ENTRY = "entry";
  private static final String ENTRIES = "entries";

  /**
   * Creates a new {@link MapAssert}.
   *
   * @param actual the target to verify.
   */
  protected MapAssert(@Nullable Map<?, ?> actual) {
    super(MapAssert.class, actual);
  }

  /**
   * Creates a new map entry.
   *
   * @param key   the key of the entry.
   * @param value the value of the entry.
   * @return the created entry.
   * @see #includes(org.fest.assertions.MapAssert.Entry...)
   */
  public static @NotNull Entry entry(@Nullable Object key, @Nullable Object value) {
    return new Entry(key, value);
  }

  /**
   * Verifies that the actual {@code Map} contains the given entries.
   *

   * Example:
   *

   * // static import org.fest.assertions.Assertions.*;
   * // static import org.fest.assertions.MapAssert.*;
   *
   * assertThat(myMap).{@link #includes(org.fest.assertions.MapAssert.Entry...) includes}({@link #entry(Object, Object) entry}("jedi", yoda), {@link #entry(Object, Object) entry}("sith", anakin));
   *

   *
   * @param entries the given entries.
   * @return this assertion error.
   * @throws AssertionError       if the actual map is {@code null}.
   * @throws AssertionError       if the actual {@code Map} does not contain any of the given entries.
   * @throws NullPointerException if the given array of entries is {@code null}.
   * @throws NullPointerException if any of the entries in the given array is {@code null}.
   */
  public @NotNull MapAssert includes(@NotNull Entry... entries) {
    isNotNull();
    checkNotNull(entries);
    List<Entry> notFound = newArrayList();
    for (Entry e : entries) {
      if (!containsEntry(checkNotNull(e))) {
        notFound.add(e);
      }
    }
    if (!notFound.isEmpty()) {
      failIfNotFound(entryOrEntries(notFound), notFound);
    }
    return this;
  }

  /**
   * Verifies that the actual {@code Map} does not contain the given entries.
   *

   * Example:
   *

   * // static import org.fest.assertions.Assertions.*;
   * // static import org.fest.assertions.MapAssert.*;
   *
   * assertThat(myMap).{@link #excludes(org.fest.assertions.MapAssert.Entry...) excludes}({@link #entry(Object, Object) entry}("jedi", yoda), {@link #entry(Object, Object) entry}("sith", anakin));
   *

   *
   * @param entries the given entries.
   * @return this assertion error.
   * @throws AssertionError       if the actual map is {@code null}.
   * @throws AssertionError       if the actual {@code Map} contains any of the given entries.
   * @throws NullPointerException if the given array of entries is {@code null}.
   * @throws NullPointerException if any of the entries in the given array is {@code null}.
   */
  public @NotNull MapAssert excludes(@NotNull Entry... entries) {
    isNotNull();
    checkNotNull(entries);
    List<Entry> found = newArrayList();
    for (Entry e : entries) {
      if (containsEntry(checkNotNull(e))) {
        found.add(e);
      }
    }
    if (!found.isEmpty()) {
      failIfFound(entryOrEntries(found), found);
    }
    return this;
  }

  private boolean containsEntry(@NotNull Entry e) {
    if (!actual.containsKey(e.key)) {
      return false;
    }
    return actual.get(e.key).equals(e.value);
  }

  private @NotNull String entryOrEntries(@NotNull List<Entry> found) {
    return found.size() == 1 ? ENTRY : ENTRIES;
  }

  private void failIfNotFound(@NotNull String description, @NotNull Collection<?> notFound) {
    failIfCustomMessageIsSet();
    String format = "the map:<%s> does not contain the %s:<%s>";
    fail(String.format(format, formattedActual(), description, toStringOf(notFound)));
  }

  private void failIfFound(@NotNull String description, @NotNull Collection<?> found) {
    failIfCustomMessageIsSet();
    fail(String.format("the map:<%s> contains the %s:<%s>", formattedActual(), description, toStringOf(found)));
  }

  private @NotNull String formattedActual() {
    return checkNotNull(toStringOf(actual));
  }

  /**
   * @return the number of elements in the actual {@code Map}.
   */
  @Override
  protected int actualGroupSize() {
    isNotNull();
    return actual.size();
  }

  /**
   * An entry in a {@code Map}.
   *
   * @author Yvonne Wang
   */
  public static class Entry {
    final Object key;
    final Object value;

    Entry(@Nullable Object key, @Nullable Object value) {
      this.key = key;
      this.value = value;
    }

    /**
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {
      return String.format("%s=%s", quote(key), quote(value));
    }
  }
}


/*
 * Created on Jun 18, 2007
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 *
 * Copyright @2007-2013 the original author or authors.
 */
package org.fest.assertions;

import org.fest.util.VisibleForTesting;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import static java.lang.Short.valueOf;
import static org.fest.assertions.ErrorMessages.*;

/**
 * Assertions for {@code Short}s and {@code short}s.
 * <p/>
 * To create a new instance of this class invoke either {@link Assertions#assertThat(Short)} or
 * {@link Assertions#assertThat(short)}.
 *
 * @author Yvonne Wang
 * @author David DIDIER
 * @author Ansgar Konermann
 * @author Alex Ruiz
 */
public class ShortAssert extends GenericAssert<ShortAssert, Short> implements NumberAssert {
  private static final short ZERO = (short) 0;

  @VisibleForTesting ShortAssert(int actual) {
    this((short) actual);
  }

  /**
   * Creates a new {@link ShortAssert}.
   *
   * @param actual the actual value to verify.
   */
  protected ShortAssert(short actual) {
    super(ShortAssert.class, actual);
  }

  /**
   * Creates a new {@link ShortAssert}.
   *
   * @param actual the actual value to verify.
   */
  protected ShortAssert(@Nullable Short actual) {
    super(ShortAssert.class, actual);
  }

  /**
   * Verifies that the actual {@code Short} is equal to the given one.
   *
   * @param expected the value to compare the actual one to.
   * @return this assertion object.
   * @throws AssertionError if the actual {@code Short} is not equal to the given one.
   */
  public @NotNull ShortAssert isEqualTo(short expected) {
    return isEqualTo(valueOf(expected));
  }

  /**
   * Verifies that the actual {@code Short} is not equal to the given one.
   *
   * @param other the given value.
   * @return this assertion object.
   * @throws AssertionError if the actual {@code Short} is equal to the given one.
   */
  public @NotNull ShortAssert isNotEqualTo(short other) {
    return isNotEqualTo(valueOf(other));
  }

  /**
   * Verifies that the actual {@code Short} is greater than the given one.
   *
   * @param other the given value.
   * @return this assertion object.
   * @throws AssertionError if the actual {@code Short} is not greater than the given one.
   */
  public @NotNull ShortAssert isGreaterThan(short other) {
    if (actual > other) {
      return this;
    }
    failIfCustomMessageIsSet();
    throw failure(unexpectedLessThanOrEqualTo(actual, other));
  }

  /**
   * Verifies that the actual {@code Short} is less than the given one.
   *
   * @param other the given value.
   * @return this assertion object.
   * @throws AssertionError if the actual {@code Short} is not less than the given one.
   */
  public @NotNull ShortAssert isLessThan(short other) {
    if (actual < other) {
      return this;
    }
    failIfCustomMessageIsSet();
    throw failure(unexpectedGreaterThanOrEqualTo(actual, other));
  }

  /**
   * Verifies that the actual {@code Short} is greater or equal to the given one.
   *
   * @param other the given value.
   * @return this assertion object.
   * @throws AssertionError if the actual {@code Short} is not greater than or equal to the given one.
   */
  public @NotNull ShortAssert isGreaterThanOrEqualTo(short other) {
    if (actual >= other) {
      return this;
    }
    failIfCustomMessageIsSet();
    throw failure(unexpectedLessThan(actual, other));
  }

  /**
   * Verifies that the actual {@code Short} is less or equal to the given one.
   *
   * @param other the given value.
   * @return this assertion object.
   * @throws AssertionError if the actual {@code Short} is not less than or equal to the given one.
   */
  public @NotNull ShortAssert isLessThanOrEqualTo(short other) {
    if (actual <= other) {
      return this;
    }
    failIfCustomMessageIsSet();
    throw failure(unexpectedGreaterThan(actual, other));
  }

  /**
   * Verifies that the actual {@code Short} is equal to zero.
   *
   * @return this assertion object.
   * @throws AssertionError if the actual {@code Short} is not equal to zero.
   */
  @Override
  public @NotNull ShortAssert isZero() {
    return isEqualTo(ZERO);
  }

  /**
   * Verifies that the actual {@code Short} is positive.
   *
   * @return this assertion object.
   * @throws AssertionError if the actual {@code Short} is not positive.
   */
  @Override
  public @NotNull ShortAssert isPositive() {
    return isGreaterThan(ZERO);
  }

  /**
   * Verifies that the actual {@code Short} is negative.
   *
   * @return this assertion object.
   * @throws AssertionError if the actual {@code Short} is not negative.
   */
  @Override
  public @NotNull ShortAssert isNegative() {
    return isLessThan(ZERO);
  }
}


/*
 * Created on May 21, 2007
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 *
 * Copyright @2007-2013 the original author or authors.
 */
package org.fest.assertions;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;

import static org.fest.assertions.ErrorMessages.unexpectedIn;
import static org.fest.assertions.ErrorMessages.unexpectedNotIn;
import static org.fest.assertions.Fail.*;
import static org.fest.assertions.Formatting.format;
import static org.fest.util.Lists.newArrayList;
import static org.fest.util.Objects.areEqual;
import static org.fest.util.Preconditions.checkNotNull;

/**
 * Template for assertions.
 *
 * @param <S> used to simulate "self types." For more information please read "Emulating 'self types' using Java Generics to simplify fluent API
 *            implementation."
 * @param  the type the "actual" value.
 * @author Yvonne Wang
 * @author Alex Ruiz
 */
public abstract class GenericAssert<S, A> extends Assert {
  protected final A actual;
  protected final S myself;

  /**
   * Creates a new {@link GenericAssert}.
   *
   * @param selfType the "self type."
   * @param actual   the actual value to verify.
   */
  protected GenericAssert(@NotNull Class<S> selfType, @Nullable A actual) {
    this.actual = actual;
    myself = selfType.cast(this);
  }

  /**
   * Asserts that the actual value (specified in the constructor of this class) is {@code null}.
   *
   * @throws AssertionError if the actual value is not {@code null}.
   */
  public final void isNull() {
    failIfNotNull(customErrorMessage(), rawDescription(), actual);
  }

  /**
   * Verifies that the actual value satisfies the given condition.
   *
   * @param condition the given condition.
   * @return this assertion object.
   * @throws NullPointerException if the given condition is {@code null}.
   * @throws AssertionError       if the actual value does not satisfy the given condition.
   * @see #is(Condition)
   */
  public final @NotNull S satisfies(@NotNull Condition condition) {
    if (matches(condition)) {
      return myself();
    }
    failIfCustomMessageIsSet();
    throw failure(errorMessageIfConditionNotSatisfied(condition));
  }

  private @NotNull String errorMessageIfConditionNotSatisfied(@NotNull Condition condition) {
    return condition.addDescriptionTo(format("actual value:<%s> should satisfy condition", actual));
  }

  /**
   * Verifies that the actual value does not satisfy the given condition.
   *
   * @param condition the given condition.
   * @return this assertion object.
   * @throws NullPointerException if the given condition is {@code null}.
   * @throws AssertionError       if the actual value satisfies the given condition.
   * @see #isNot(Condition)
   */
  public final @NotNull S doesNotSatisfy(@NotNull Condition condition) {
    if (!matches(condition)) {
      return myself();
    }
    failIfCustomMessageIsSet();
    throw failure(errorMessageIfConditionSatisfied(condition));
  }

  private @NotNull String errorMessageIfConditionSatisfied(@NotNull Condition condition) {
    return condition.addDescriptionTo(format("actual value:<%s> should not satisfy condition", actual));
  }

  /**
   * Alias for {@link #satisfies(Condition)}.
   *
   * @param condition the given condition.
   * @return this assertion object.
   * @throws NullPointerException if the given condition is {@code null}.
   * @throws AssertionError       if the actual value does not satisfy the given condition.
   * @since 1.2
   */
  public final @NotNull S is(@NotNull Condition condition) {
    if (matches(condition)) {
      return myself();
    }
    failIfCustomMessageIsSet();
    throw failure(errorMessageIfIsNot(condition));
  }

  private @NotNull String errorMessageIfIsNot(@NotNull Condition condition) {
    return condition.addDescriptionTo(format("actual value:<%s> should be", actual));
  }

  /**
   * Alias for {@link #doesNotSatisfy(Condition)}.
   *
   * @param condition the given condition.
   * @return this assertion object.
   * @throws NullPointerException if the given condition is {@code null}.
   * @throws AssertionError       if the actual value satisfies the given condition.
   * @since 1.2
   */
  public final @NotNull S isNot(@NotNull Condition condition) {
    if (!matches(condition)) {
      return myself();
    }
    failIfCustomMessageIsSet();
    throw failure(errorMessageIfIs(condition));
  }

  private boolean matches(@NotNull Condition condition) {
    checkNotNull(condition);
    return condition.matches(actual);
  }

  private @NotNull String errorMessageIfIs(@NotNull Condition condition) {
    return condition.addDescriptionTo(format("actual value:<%s> should not be", actual));
  }

  /**
   * Sets the description of the actual value, to be used in as message of any {@code AssertionError} thrown when an
   * assertion fails. This method should be called before any assertion method, otherwise any assertion failure will not
   * show the provided description.
   *

   * For example:
   *

   * assertThat(val).as("name").isEqualTo("Frodo");
   *

   *
   * @param description the description of the actual value.
   * @return this assertion object.
   */
  public @NotNull S as(@Nullable String description) {
    description(description);
    return myself();
  }

  /**
   * Alias for {@link #as(String)}, since "as" is a keyword in Groovy. This method should be called before any assertion method, otherwise any assertion
   * failure will not show the provided description.
   *

   * For example:
   *

   * assertThat(val).describedAs("name").isEqualTo("Frodo");
   *

   *
   * @param description the description of the actual value.
   * @return this assertion object.
   */
  public @NotNull S describedAs(@Nullable String description) {
    return as(description);
  }

  /**
   * Sets the description of the actual value, to be used in as message of any {@code AssertionError} thrown when an
   * assertion fails. This method should be called before any assertion method, otherwise any assertion failure will not
   * show the provided description.
   *

   * For example:
   *

   * assertThat(val).as(new BasicDescription("name")).isEqualTo("Frodo");
   *

   *
   * @param description the description of the actual value.
   * @return this assertion object.
   */
  public @NotNull S as(@Nullable Description description) {
    description(description);
    return myself();
  }

  /**
   * Alias for {@link #as(Description)}, since "as" is a keyword in Groovy. This method should be called before any assertion method, otherwise any assertion
   * failure will not show the provided description.
   *

   * For example:
   *

   * assertThat(val).describedAs(new BasicDescription("name")).isEqualTo("Frodo");
   *

   *
   * @param description the description of the actual value.
   * @return this assertion object.
   */
  public @NotNull S describedAs(@Nullable Description description) {
    return as(description);
  }

  /**
   * Verifies that the actual value is equal to the given one.
   *
   * @param expected the given value to compare the actual value to.
   * @return this assertion object.
   * @throws AssertionError if the actual value is not equal to the given one.
   */
  public @NotNull S isEqualTo(@Nullable A expected) {
    failIfNotEqual(customErrorMessage(), rawDescription(), actual, expected);
    return myself();
  }

  /**
   * Verifies that the actual value is not equal to the given one.
   *
   * @param other the given value to compare the actual value to.
   * @return this assertion object.
   * @throws AssertionError if the actual value is equal to the given one.
   */
  public @NotNull S isNotEqualTo(@Nullable A other) {
    failIfEqual(customErrorMessage(), rawDescription(), actual, other);
    return myself();
  }

  /**
   * Verifies that the actual value is not {@code null}.
   *
   * @return this assertion object.
   * @throws AssertionError if the actual value is {@code null}.
   */
  public final @NotNull S isNotNull() {
    failIfActualIsNull(customErrorMessage(), rawDescription(), actual);
    return myself();
  }

  /**
   * Verifies that the actual value is the same as the given one.
   *
   * @param expected the given value to compare the actual value to.
   * @return this assertion object.
   * @throws AssertionError if the actual value is not the same as the given one.
   */
  public final @NotNull S isSameAs(@Nullable A expected) {
    failIfNotSame(customErrorMessage(), rawDescription(), actual, expected);
    return myself();
  }

  /**
   * Verifies that the actual value is not the same as the given one.
   *
   * @param other the given value to compare the actual value to.
   * @return this assertion object.
   * @throws AssertionError if the actual value is the same as the given one.
   */
  public final @NotNull S isNotSameAs(@Nullable A other) {
    failIfSame(customErrorMessage(), rawDescription(), actual, other);
    return myself();
  }

  /**
   * Verifies that the actual value is in the given values.
   *
   * @param values the given values to search the actual value in.
   * @return this assertion object.
   * @throws AssertionError       if the actual value is not in the given values.
   * @throws NullPointerException if the given parameter is null.
   */
  public final @NotNull S isIn(@NotNull Object... values) {
    return isIn(newArrayList(values));
  }

  /**
   * Verifies that the actual value is in the given collection.
   *
   * @param values the given collection to search the actual value in. must not be null.
   * @return this assertion object.
   * @throws AssertionError       if the actual value is not in the given collection.
   * @throws NullPointerException if the given collection is null.
   */
  public final @NotNull S isIn(@NotNull Collection<?> values) {
    checkNotNull(values);
    if (isActualIn(values)) {
      return myself();
    }
    failIfCustomMessageIsSet();
    throw failure(unexpectedNotIn(actual, values));
  }

  /**
   * Verifies that the actual value is in the given values.
   *
   * @param values the given values to search the actual value in.
   * @return this assertion object.
   * @throws AssertionError       if the actual value is not in the given values.
   * @throws NullPointerException if the given parameter is null.
   */
  public final @NotNull S isNotIn(@NotNull Object... values) {
    return isNotIn(newArrayList(values));
  }

  /**
   * Verifies that the actual value is in the given collection.
   *
   * @param values the given collection to search the actual value in. must not be null.
   * @return this assertion object.
   * @throws AssertionError       if the actual value is not in the given collection.
   * @throws NullPointerException if the given collection is null.
   */
  public final @NotNull S isNotIn(@NotNull Collection<?> values) {
    checkNotNull(values);
    if (!isActualIn(values)) {
      return myself();
    }
    failIfCustomMessageIsSet();
    throw failure(unexpectedIn(actual, values));
  }

  private boolean isActualIn(@NotNull Collection<?> values) {
    if (values.isEmpty()) {
      return false;
    }
    for (Object value : values) {
      if (areEqual(actual, value)) {
        return true;
      }
    }
    return false;
  }

  /**
   * Replaces the default message displayed in case of a failure with the given one.
   *

   * For example, the following assertion:
   *

   * assertThat("Hello").isEqualTo("Bye");
   *

   * will fail with the default message "expected:<'[Bye]'> but was:<'[Hello]'>."
   *

   * We can replace this message with our own:
   *

   * assertThat("Hello").overridingErrorMessage("'Hello' should be equal to 'Bye'").isEqualTo("Bye");
   *

   * in this case, the assertion will fail showing the message "'Hello' should be equal to 'Bye'".
   *
   * @param message the given error message, which will replace the default one.
   * @return this assertion.
   * @since 1.2
   */
  public @NotNull S overridingErrorMessage(@Nullable String message) {
    replaceDefaultErrorMessagesWith(message);
    return myself();
  }

  protected final @NotNull S myself() {
    return checkNotNull(myself);
  }
}


/*
 * Created on Feb 14, 2008
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 *
 * Copyright @2008-2013 the original author or authors.
 */
package org.fest.assertions;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;

import static java.lang.Math.abs;
import static org.fest.assertions.ArrayInspection.copy;
import static org.fest.assertions.ErrorMessages.unexpectedEqual;
import static org.fest.assertions.ErrorMessages.unexpectedNotEqual;
import static org.fest.assertions.Formatting.format;
import static org.fest.util.Preconditions.checkNotNull;

/**
 * Assertions for arrays of {@code double}.
 *

 * To create a new instance of this class invoke {@link Assertions#assertThat(double[])}.
 *
 * @author Yvonne Wang
 * @author Alex Ruiz
 */
public class DoubleArrayAssert extends ArrayAssert<DoubleArrayAssert, double[]> {
  /**
   * Creates a new {@link DoubleArrayAssert}.
   *
   * @param actual the target to verify.
   */
  protected DoubleArrayAssert(@Nullable double... actual) {
    super(DoubleArrayAssert.class, actual);
  }

  /**
   * Verifies that the actual {@code double} array contains the given values.
   *
   * @param values the values to look for.
   * @return this assertion object.
   * @throws AssertionError       if the actual {@code double} array is {@code null}.
   * @throws NullPointerException if the given {@code double} array is {@code null}.
   * @throws AssertionError       if the actual {@code double} array does not contain the given values.
   */
  public @NotNull DoubleArrayAssert contains(@NotNull double... values) {
    assertContains(copy(values));
    return this;
  }

  /**
   * Verifies that the actual {@code double} array contains the given values only.
   *
   * @param values the values to look for.
   * @return this assertion object.
   * @throws AssertionError       if the actual {@code double} array is {@code null}.
   * @throws NullPointerException if the given {@code double} array is {@code null}.
   * @throws AssertionError       if the actual {@code double} array does not contain the given objects, or if the actual
   *                              {@code double} array contains elements other than the ones specified.
   */
  public @NotNull DoubleArrayAssert containsOnly(@NotNull double... values) {
    assertContainsOnly(copy(values));
    return this;
  }

  /**
   * Verifies that the actual {@code double} array does not contain the given values.
   *
   * @param values the values the array should exclude.
   * @return this assertion object.
   * @throws AssertionError       if the actual {@code double} array is {@code null}.
   * @throws NullPointerException if the given {@code double} array is {@code null}.
   * @throws AssertionError       if the actual {@code double} array contains any of the given values.
   */
  public @NotNull DoubleArrayAssert excludes(@NotNull double... values) {
    assertExcludes(copy(values));
    return this;
  }

  /**
   * Verifies that the actual {@code double} array is equal to the given array. Array equality is checked by
   * {@link Arrays#equals(double[], double[])}.
   *
   * @param expected the given array to compare the actual array to.
   * @return this assertion object.
   * @throws AssertionError if the actual {@code double} array is not equal to the given one.
   */
  @Override
  public @NotNull DoubleArrayAssert isEqualTo(@Nullable double[] expected) {
    if (Arrays.equals(actual, expected)) {
      return this;
    }
    failIfCustomMessageIsSet();
    throw failure(unexpectedNotEqual(actual, expected));
  }

  /**
   * Verifies that the actual {@code double} array is equal to the given array, within a positive delta.
   *
   * @param expected the given array to compare the actual array to.
   * @param delta    the given delta.
   * @return this assertion object.
   * @throws NullPointerException if {@code delta} is {@code null}.
   * @throws AssertionError       if the actual {@code double} array is not equal to the given one.
   * @since 1.1
   */
  public @NotNull DoubleArrayAssert isEqualTo(@Nullable double[] expected, @NotNull Delta delta) {
    checkNotNull(delta);
    if (actual == expected) {
      return this;
    }
    if (actual == null || expected == null) {
      throw failureWhenNotEqual(expected, delta);
    }
    int length = expected.length;
    if (actual.length != length) {
      failureWhenNotEqual(expected, delta);
    }
    for (int i = 0; i < length; i++) {
      if (!equals(expected[i], actual[i], delta)) {
        failureWhenNotEqual(expected, delta);
      }
    }
    return this;
  }

  private @NotNull AssertionError failureWhenNotEqual(@Nullable double[] expected, @NotNull Delta delta) {
    failIfCustomMessageIsSet();
    throw failure(unexpectedNotEqual(actual, expected) + format(" using delta:<%s>", delta.doubleValue()));
  }

  private boolean equals(double e, double a, @NotNull Delta delta) {
    if (Double.compare(e, a) == 0) {
      return true;
    }
    return abs(e - a) <= delta.doubleValue();
  }

  /**
   * Verifies that the actual {@code double} array is not equal to the given array. Array equality is checked by
   * {@link Arrays#equals(double[], double[])}.
   *
   * @param array the given array to compare the actual array to.
   * @return this assertion object.
   * @throws AssertionError if the actual {@code double} array is equal to the given one.
   */
  @Override
  public @NotNull DoubleArrayAssert isNotEqualTo(@Nullable double[] array) {
    if (!Arrays.equals(actual, array)) {
      return this;
    }
    failIfCustomMessageIsSet();
    throw failure(unexpectedEqual(actual, array));
  }
}


/*
 * Created on Mar 3, 2007
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 *
 * Copyright @2007-2013 the original author or authors.
 */
package org.fest.assertions;

import org.fest.util.IntrospectionError;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.List;
import java.util.Set;

import static org.fest.assertions.ErrorMessages.unexpectedEqual;
import static org.fest.assertions.ErrorMessages.unexpectedNotEqual;
import static org.fest.assertions.Formatting.format;
import static org.fest.util.Lists.newArrayList;
import static org.fest.util.Preconditions.checkNotNull;
import static org.fest.util.Sets.newLinkedHashSet;

/**
 * Assertions for arrays of {@code Object}.
 *

 * To create a new instance of this class invoke {@link Assertions#assertThat(Object[])}.
 *
 * @author Yvonne Wang
 * @author Alex Ruiz
 */
public class ObjectArrayAssert extends ObjectGroupAssert<ObjectArrayAssert, Object[]> {
  /**
   * Creates a new {@link ObjectArrayAssert}.
   *
   * @param actual the target to verify.
   */
  protected ObjectArrayAssert(@Nullable Object... actual) {
    super(ObjectArrayAssert.class, actual);
  }

  /**
   * Verifies that all the elements in the actual {@code Object} array belong to the specified type. Matching includes
   * subclasses of the given type.
   *

   * For example, consider the following code listing:
   *

   * Number[] numbers = { 2, 6, 8 };
   * assertThat(numbers).hasAllElementsOfType(Integer.class);
   *

   *

   * The assertion {@code hasAllElementsOfType} will be successful.
   *
   * @param type the expected type.
   * @return this assertion object.
   * @throws NullPointerException if the given type is {@code null}.
   * @throws AssertionError       if the component type of the actual {@code Object} array is not the same as the specified
   *                              one.
   */
  public @NotNull ObjectArrayAssert hasAllElementsOfType(@NotNull Class<?> type) {
    checkNotNull(type);
    isNotNull();
    for (Object o : actual) {
      if (type.isInstance(o)) {
        continue;
      }
      failIfCustomMessageIsSet();
      fail(format("not all elements in array:<%s> belong to the type:<%s>", actual, type));
    }
    return this;
  }

  /**
   * Verifies that at least one element in the actual {@code Object} array belong to the specified type. Matching
   * includes subclasses of the given type.
   *
   * @param type the expected type.
   * @return this assertion object.
   * @throws AssertionError if the actual {@code Object} does not have any elements of the given type.
   */
  public @NotNull ObjectArrayAssert hasAtLeastOneElementOfType(@NotNull Class<?> type) {
    checkNotNull(type);
    isNotNull();
    boolean found = false;
    for (Object o : actual) {
      if (!type.isInstance(o)) {
        continue;
      }
      found = true;
      break;
    }
    if (found) {
      return this;
    }
    failIfCustomMessageIsSet();
    throw failure(format("array:<%s> does not have any elements of type:<%s>", actual, type));
  }

  /**
   * Verifies that the actual {@code Object} array is equal to the given array. Array equality is checked by
   * {@link Arrays#deepEquals(Object[], Object[])}.
   *
   * @param expected the given array to compare the actual array to.
   * @return this assertion object.
   * @throws AssertionError if the actual {@code Object} array is not equal to the given one.
   */
  @Override
  public @NotNull ObjectArrayAssert isEqualTo(@Nullable Object[] expected) {
    if (Arrays.deepEquals(actual, expected)) {
      return this;
    }
    failIfCustomMessageIsSet();
    throw failure(unexpectedNotEqual(actual, expected));
  }

  /**
   * Verifies that the actual {@code Object} array is not equal to the given array. Array equality is checked by
   * {@link Arrays#deepEquals(Object[], Object[])}.
   *
   * @param array the given array to compare the actual array to.
   * @return this assertion object.
   * @throws AssertionError if the actual {@code Object} array is equal to the given one.
   */
  @Override
  public @NotNull ObjectArrayAssert isNotEqualTo(@Nullable Object[] array) {
    if (!Arrays.deepEquals(actual, array)) {
      return this;
    }
    failIfCustomMessageIsSet();
    throw failure(unexpectedEqual(actual, array));
  }

  /**
   * Creates a new instance of {@link ObjectArrayAssert} whose target array contains the values of the
   * given property name from the elements of this {@code ObjectArrayAssert}'s array. Property access works with both
   * simple properties like {@code Person.age} and nested properties {@code Person.father.age}.
   *

   * For example, let's say we have a array of {@code Person} objects and you want to verify their age:
   *

   * assertThat(persons).onProperty("age").containsOnly(25, 16, 44, 37); // simple property
   * assertThat(persons).onProperty("father.age").containsOnly(55, 46, 74, 62); // nested property
   *
   * @param propertyName the name of the property to extract values from the actual array to build a new
   *                     {@code ObjectArrayAssert}.
   * @return a new {@code ObjectArrayAssert} containing the values of the given property name from the elements of this
   *         {@code ObjectArrayAssert}'s array.
   * @throws AssertionError     if the actual array is {@code null}.
   * @throws IntrospectionError if an element in the given array does not have a matching property.
   * @since 1.3
   */
  @Override
  public @NotNull ObjectArrayAssert onProperty(@NotNull String propertyName) {
    isNotNull();
    if (actual.length == 0) {
      return new ObjectArrayAssert(new Object[0]);
    }
    List<Object> values = PropertySupport.instance().propertyValues(propertyName, newArrayList(actual));
    return new ObjectArrayAssert(values.toArray());
  }

  /**
   * {@inheritDoc}
   */
  @Override
  protected Set<Object> actualAsSet() {
    return actual == null ? null : newLinkedHashSet(actual);
  }

  /**
   * {@inheritDoc}
   */
  @Override
  protected @Nullable List<Object> actualAsList() {
    return actual == null ? null : newArrayList(actual);
  }

  /**
   * {@inheritDoc}
   */
  @Override
  protected int actualGroupSize() {
    isNotNull();
    return actual.length;
  }
}


/*
 * Created on Oct 10, 2007
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 *
 * Copyright @2007-2013 the original author or authors.
 */
package org.fest.assertions;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import static org.fest.assertions.Fail.failWithMessage;
import static org.fest.assertions.Formatting.format;
import static org.fest.assertions.Formatting.valueOf;

/**
 * Base class for all assertion classes.
 *
 * @author Yvonne Wang
 * @author Alex Ruiz
 */
public abstract class Assert {
  private Description description;
  private String errorMessage;

  /**
   * @return the description of the actual value in this assertion.
   */
  public final @Nullable String description() {
    return valueOf(description);
  }

  /**
   * Sets the description of the actual value, to be used in as message of any {@code AssertionError} thrown when an
   * assertion fails.
   *
   * @param d the new description.
   */
  protected final void description(@Nullable String d) {
    description(d == null ? null : new BasicDescription(d));
  }

  /**
   * Sets the description of the actual value, to be used in as message of any {@code AssertionError} thrown when an
   * assertion fails.
   *
   * @param d the new description.
   */
  protected final void description(@Nullable Description d) {
    this.description = d;
  }

  /**
   * Returns the description of the actual value in this assertion.
   *
   * @return the description of the actual value in this assertion.
   * @since 1.2
   */
  protected final @Nullable Description rawDescription() {
    return description;
  }

  /**
   * Returns the given message formatted as follows:
   *

   *

   * [assertion description] given message.
   *

   *
   * @param message the message to format.
   * @return the formatted message.
   * @throws NullPointerException if the given message is {@code null}.
   */
  protected final @NotNull String formattedErrorMessage(@NotNull String message) {
    return format(description, message);
  }

  /**
   * Specifies the message to use in case of a failure, replacing the default one.
   *
   * @param message the new error message.
   */
  protected final void replaceDefaultErrorMessagesWith(@Nullable String message) {
    errorMessage = message;
  }

  /**
   * Returns the message to use when a failure occurs, if one has been specified.
   *
   * @return the message to use when a failure occurs, or {@code null} if none has been specified.
   */
  protected final @Nullable String customErrorMessage() {
    return errorMessage;
  }

  /**
   * Throws an {@code AssertionError} only if the the custom message in this assertion object is not {@code null}.
   *
   * @throws AssertionError only if the custom error message in this assertion object is not {@code null}.
   * @since 1.2
   */
  protected final void failIfCustomMessageIsSet() {
    failWithMessage(customErrorMessage());
  }

  /**
   * Throws an {@code AssertionError} only if the the custom message in this assertion object is not {@code null}.
   *
   * @param realCause cause of the error.
   * @throws AssertionError only if the custom error message in this assertion object is not {@code null}.
   * @since 1.2
   */
  protected final void failIfCustomMessageIsSet(@Nullable Throwable realCause) {
    failWithMessage(customErrorMessage(), realCause);
  }

  /**
   * Fails by throwing an {@code AssertionError}.
   *
   * @param reason the reason for the failure, used as the message for the thrown exception.
   * @param cause  the root cause of the failure, included in the thrown exception.
   * @throws NullPointerException if the given reason is {@code null}.
   */
  protected final void fail(@NotNull String reason, @Nullable Throwable cause) {
    Fail.fail(formattedErrorMessage(reason), cause);
  }

  /**
   * Fails by throwing an {@code AssertionError}.
   *

   * Note: This method appears to return {@code AssertionError}, but it is really not the case, since
   * the exception is thrown and not returned. In version 2.0 the return type of this method will change to {@code void}
   * . Since we cannot create an overloaded version with return type {@code void}, we cannot deprecate this method.
   * Please pretend this method does not return anything :)
   *
   * @param reason the reason for the failure, used as the message for the thrown exception.
   * @return the thrown {@code AssertionError}.
   * @throws AssertionError using the given reason as the message.
   * @see #failure(String)
   */
  protected final @NotNull AssertionError fail(@NotNull String reason) {
    // TODO in 2.0: change return type to 'void'
    throw failure(reason);
  }

  /**
   * Creates an {@code AssertionError}, adding the description of the actual value to the given message.
   *
   * @param reason the reason for the failure, used as the message for the thrown exception.
   * @return the created exception.
   */
  protected final @NotNull AssertionError failure(@NotNull String reason) {
    return Fail.failure(formattedErrorMessage(reason));
  }

  /**
   * Throws {@code UnsupportedOperationException} if called. It is easy to accidentally call {@link #equals(Object)}
   * instead of {@code isEqualTo}.
   *
   * @throws UnsupportedOperationException if this method is called.
   */
  @Override
  public final boolean equals(Object obj) {
    throw new UnsupportedOperationException("'equals' is not supported...maybe you intended to call 'isEqualTo'");
  }

  /**
   * Always returns 1.
   *
   * @return 1.
   */
  @Override
  public final int hashCode() {
    return 1;
  }
}


/*
 * Created on Jun 18, 2007
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 *
 * Copyright @2007-2013 the original author or authors.
 */
package org.fest.assertions;

import org.fest.util.VisibleForTesting;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import static java.lang.Byte.valueOf;
import static org.fest.assertions.ErrorMessages.*;

/**
 * Assertions for {@code Byte}s and {@code byte}s.
 * <p/>
 * To create a new instance of this class invoke either {@link Assertions#assertThat(Byte)} or
 * {@link Assertions#assertThat(byte)}.
 *
 * @author Yvonne Wang
 * @author David DIDIER
 * @author Ansgar Konermann
 * @author Alex Ruiz
 * @since 1.2
 */
public class ByteAssert extends GenericAssert<ByteAssert, Byte> implements NumberAssert {
  private static final byte ZERO = (byte) 0;

  @VisibleForTesting ByteAssert(int actual) {
    this((byte) actual);
  }

  /**
   * Creates a new {@link ByteAssert}.
   *
   * @param actual the actual value to verify.
   */
  protected ByteAssert(byte actual) {
    super(ByteAssert.class, actual);
  }

  /**
   * Creates a new {@link ByteAssert}.
   *
   * @param actual the actual value to verify.
   */
  protected ByteAssert(@Nullable Byte actual) {
    super(ByteAssert.class, actual);
  }

  /**
   * Verifies that the actual {@code Byte} value is equal to the given one.
   *
   * @param expected the value to compare the actual one to.
   * @return this assertion object.
   * @throws AssertionError if the actual {@code Byte} value is not equal to the given one.
   */
  public @NotNull ByteAssert isEqualTo(byte expected) {
    return isEqualTo(valueOf(expected));
  }

  /**
   * Verifies that the actual {@code Byte} value is not equal to the given one.
   *
   * @param other the given value.
   * @return this assertion object.
   * @throws AssertionError if the actual {@code Byte} value is equal to the given one.
   */
  public @NotNull ByteAssert isNotEqualTo(byte other) {
    return isNotEqualTo(valueOf(other));
  }

  /**
   * Verifies that the actual {@code Byte} value is greater than the given one.
   *
   * @param other the given value.
   * @return this assertion object.
   * @throws AssertionError if the actual {@code Byte} value is not greater than the given one.
   */
  public @NotNull ByteAssert isGreaterThan(byte other) {
    // TODO check for NPE
    if (actual > other) {
      return this;
    }
    failIfCustomMessageIsSet();
    throw failure(unexpectedLessThanOrEqualTo(actual, other));
  }

  /**
   * Verifies that the actual {@code Byte} value is less than the given one.
   *
   * @param other the given value.
   * @return this assertion object.
   * @throws AssertionError if the actual {@code Byte} value is not less than the given one.
   */
  public @NotNull ByteAssert isLessThan(byte other) {
    if (actual < other) {
      return this;
    }
    failIfCustomMessageIsSet();
    throw failure(unexpectedGreaterThanOrEqualTo(actual, other));
  }

  /**
   * Verifies that the actual {@code Byte} value is greater or equal to the given one.
   *
   * @param other the given value.
   * @return this assertion object.
   * @throws AssertionError if the actual {@code Byte} value is not greater than or equal to the given one.
   */
  public @NotNull ByteAssert isGreaterThanOrEqualTo(byte other) {
    if (actual >= other) {
      return this;
    }
    failIfCustomMessageIsSet();
    throw failure(unexpectedLessThan(actual, other));
  }

  /**
   * Verifies that the actual {@code Byte} value is less or equal to the given one.
   *
   * @param other the given value.
   * @return this assertion object.
   * @throws AssertionError if the actual {@code Byte} value is not less than or equal to the given one.
   */
  public @NotNull ByteAssert isLessThanOrEqualTo(byte other) {
    if (actual <= other) {
      return this;
    }
    failIfCustomMessageIsSet();
    throw failure(unexpectedGreaterThan(actual, other));
  }

  /**
   * Verifies that the actual {@code Byte} value is equal to zero.
   *
   * @return this assertion object.
   * @throws AssertionError if the actual {@code Byte} value is not equal to zero.
   */
  @Override
  public @NotNull ByteAssert isZero() {
    return isEqualTo(ZERO);
  }

  /**
   * Verifies that the actual {@code Byte} value is positive.
   *
   * @return this assertion object.
   * @throws AssertionError if the actual {@code Byte} value is not positive.
   */
  @Override
  public @NotNull ByteAssert isPositive() {
    return isGreaterThan(ZERO);
  }

  /**
   * Verifies that the actual {@code Byte} value is negative.
   *
   * @return this assertion object.
   * @throws AssertionError if the actual {@code Byte} value is not negative.
   */
  @Override
  public @NotNull ByteAssert isNegative() {
    return isLessThan(ZERO);
  }
}