/*
 * Created on Nov 3, 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.internal;

import org.fest.assertions.data.Index;
import org.fest.assertions.description.Description;
import org.fest.util.VisibleForTesting;

/**
 * Reusable assertions for arrays of objects.
 *
 * @author Alex Ruiz
 * @author Yvonne Wang
 */
public class ObjectArrays {

  private static final ObjectArrays INSTANCE = new ObjectArrays();

  /**
   * Returns the singleton instance of this class.
   *
   * @return the singleton instance of this class.
   */
  public static ObjectArrays instance() {
    return INSTANCE;
  }

  private final Arrays arrays = Arrays.instance();

  @VisibleForTesting
  ObjectArrays() {
  }

  @VisibleForTesting
  Failures failures = Failures.instance();

  @VisibleForTesting
  Matchers conditions = Matchers.instance();

  /**
   * Asserts that the given array is {@code null} or empty.
   *
   * @param description contains information about the assertion.
   * @param actual the given array.
   * @throws AssertionError if the given array is not {@code null} *and* contains one or more elements.
   */
  public void assertNullOrEmpty(Description description, Object[] actual) {
    arrays.assertNullOrEmpty(description, actual);
  }

  /**
   * Asserts that the given array is empty.
   *
   * @param description contains information about the assertion.
   * @param actual the given array.
   * @throws AssertionError if the given array is {@code null}.
   * @throws AssertionError if the given array is not empty.
   */
  public void assertEmpty(Description description, Object[] actual) {
    arrays.assertEmpty(description, actual);
  }

  /**
   * Asserts that the given array is not empty.
   *
   * @param description contains information about the assertion.
   * @param actual the given array.
   * @throws AssertionError if the given array is {@code null}.
   * @throws AssertionError if the given array is empty.
   */
  public void assertNotEmpty(Description description, Object[] actual) {
    arrays.assertNotEmpty(description, actual);
  }

  /**
   * Asserts that the number of elements in the given array is equal to the expected one.
   *
   * @param description contains information about the assertion.
   * @param actual the given array.
   * @param expectedSize the expected size of {@code actual}.
   * @throws AssertionError if the given array is {@code null}.
   * @throws AssertionError if the number of elements in the given array is different than the expected one.
   */
  public void assertHasSize(Description description, Object[] actual, int expectedSize) {
    arrays.assertHasSize(description, actual, expectedSize);
  }

  /**
   * Asserts that the given array contains the given values, in any order.
   *
   * @param description contains information about the assertion.
   * @param actual the given array.
   * @param values the values that are expected to be in the given array.
   * @throws NullPointerException if the array of values is {@code null}.
   * @throws IllegalArgumentException if the array of values is empty.
   * @throws AssertionError if the given array is {@code null}.
   * @throws AssertionError if the given array does not contain the given values.
   */
  public void assertContains(Description description, Object[] actual, Object[] values) {
    arrays.assertContains(description, actual, values);
  }

  /**
   * Verifies that the given array contains the given object at the given index.
   *
   * @param description contains information about the assertion.
   * @param actual the given array.
   * @param value the object to look for.
   * @param index the index where the object should be stored in the given array.
   * @throws AssertionError if the given array is {@code null} or empty.
   * @throws NullPointerException if the given {@code Index} is {@code null}.
   * @throws IndexOutOfBoundsException if the value of the given {@code Index} is equal to or greater than the size of
   *           the given array.
   * @throws AssertionError if the given array does not contain the given object at the given index.
   */
  public void assertContains(Description description, Object[] actual, Object value, Index index) {
    arrays.assertContains(description, actual, value, index);
  }

  /**
   * Verifies that the given array does not contain the given object at the given index.
   *
   * @param description contains information about the assertion.
   * @param actual the given array.
   * @param value the object to look for.
   * @param index the index where the object should be stored in the given array.
   * @throws AssertionError if the given array is {@code null}.
   * @throws NullPointerException if the given {@code Index} is {@code null}.
   * @throws AssertionError if the given array contains the given object at the given index.
   */
  public void assertDoesNotContain(Description description, Object[] actual, Object value, Index index) {
    arrays.assertDoesNotContain(description, actual, value, index);
  }

  /**
   * Asserts that the given array contains only the given values and nothing else, in any order.
   *
   * @param description contains information about the assertion.
   * @param actual the given array.
   * @param values the values that are expected to be in the given array.
   * @throws NullPointerException if the array of values is {@code null}.
   * @throws IllegalArgumentException if the array of values is empty.
   * @throws AssertionError if the given array is {@code null}.
   * @throws AssertionError if the given array does not contain the given values or if the given array contains values
   *           that are not in the given array.
   */
  public void assertContainsOnly(Description description, Object[] actual, Object[] values) {
    arrays.assertContainsOnly(description, actual, values);
  }

  /**
   * Verifies that the given array contains the given sequence of objects, without any other objects between them.
   *
   * @param description contains information about the assertion.
   * @param actual the given array.
   * @param sequence the sequence of objects to look for.
   * @throws AssertionError if the given array is {@code null}.
   * @throws NullPointerException if the given sequence is {@code null}.
   * @throws IllegalArgumentException if the given sequence is empty.
   * @throws AssertionError if the given array does not contain the given sequence of objects.
   */
  public void assertContainsSequence(Description description, Object[] actual, Object[] sequence) {
    arrays.assertContainsSequence(description, actual, sequence);
  }

  /**
   * Asserts that the given array does not contain the given values.
   *
   * @param description contains information about the assertion.
   * @param actual the given array.
   * @param values the values that are expected not to be in the given array.
   * @throws NullPointerException if the array of values is {@code null}.
   * @throws IllegalArgumentException if the array of values is empty.
   * @throws AssertionError if the given array is {@code null}.
   * @throws AssertionError if the given array contains any of given values.
   */
  public void assertDoesNotContain(Description description, Object[] actual, Object[] values) {
    arrays.assertDoesNotContain(description, actual, values);
  }

  /**
   * Asserts that the given array does not have duplicate values.
   *
   * @param description contains information about the assertion.
   * @param actual the given array.
   * @throws NullPointerException if the array of values is {@code null}.
   * @throws IllegalArgumentException if the array of values is empty.
   * @throws AssertionError if the given array is {@code null}.
   * @throws AssertionError if the given array contains duplicate values.
   */
  public void assertDoesNotHaveDuplicates(Description description, Object[] actual) {
    arrays.assertDoesNotHaveDuplicates(description, actual);
  }

  /**
   * Verifies that the given array starts with the given sequence of objects, without any other objects between them.
   * Similar to {@link #assertContainsSequence(Description, Object[], Object[])}, but it also verifies that
   * the first element in the sequence is also the first element of the given array.
   *
   * @param description contains information about the assertion.
   * @param actual the given array.
   * @param sequence the sequence of objects to look for.
   * @throws NullPointerException if the given argument is {@code null}.
   * @throws IllegalArgumentException if the given argument is an empty array.
   * @throws AssertionError if the given array is {@code null}.
   * @throws AssertionError if the given array does not start with the given sequence of objects.
   */
  public void assertStartsWith(Description description, Object[] actual, Object[] sequence) {
    arrays.assertStartsWith(description, actual, sequence);
  }

  /**
   * Verifies that the given array ends with the given sequence of objects, without any other objects between them.
   * Similar to {@link #assertContainsSequence(Description, Object[], Object[])}, but it also verifies that
   * the last element in the sequence is also the last element of the given array.
   *
   * @param description contains information about the assertion.
   * @param actual the given array.
   * @param sequence the sequence of objects to look for.
   * @throws NullPointerException if the given argument is {@code null}.
   * @throws IllegalArgumentException if the given argument is an empty array.
   * @throws AssertionError if the given array is {@code null}.
   * @throws AssertionError if the given array does not end with the given sequence of objects.
   */
  public void assertEndsWith(Description description, Object[] actual, Object[] sequence) {
    arrays.assertEndsWith(description, actual, sequence);
  }

  /**
   * Asserts that the given array contains at least a null element.
   *
   * @param description contains information about the assertion.
   * @param actual the given array.
   * @throws AssertionError if the given array is {@code null}.
   * @throws AssertionError if the given array does not contain a null element.
   */
  public void assertContainsNull(Description description, Object[] actual) {
    arrays.assertContainsNull(description, actual);
  }

  /**
   * Asserts that the given array does not contain null elements.
   *
   * @param description contains information about the assertion.
   * @param actual the given array.
   * @throws AssertionError if the given array is {@code null}.
   * @throws AssertionError if the given array contains a null element.
   */
  public void assertDoesNotContainNull(Description description, Object[] actual) {
    arrays.assertDoesNotContainNull(description, actual);
  }
}


/*
 * Created on Aug 5, 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-2012 the original author or authors.
 */
package org.fest.assertions.error;

import static org.fest.util.Lists.newArrayList;
import static org.fest.util.Objects.HASH_CODE_PRIME;
import static org.fest.util.Objects.areEqual;
import static org.fest.util.Objects.hashCodeFor;
import static org.fest.util.ToString.toStringOf;

import java.util.List;

import org.fest.assertions.description.Description;
import org.fest.assertions.internal.Failures;
import org.fest.util.VisibleForTesting;

/**
 * Creates an {@link AssertionError} indicating that an assertion that verifies that two objects are equal failed.
 *
 * @author Alex Ruiz
 * @author Yvonne Wang
 * @author Joel Costigliola
 */
public class NotEqualErrorFactory implements AssertionErrorFactory {
  private static final Class<?>[] MSG_ARG_TYPES = new Class<?>[] { String.class, String.class, String.class };
  private static final String DETAILED_TO_STRING_FORMAT = "%s (@%d)";

  @VisibleForTesting
  ConstructorInvoker constructorInvoker = new ConstructorInvoker();

  @VisibleForTesting
  MessageFormatter messageFormatter = MessageFormatter.instance();

  @VisibleForTesting
  DescriptionFormatter descriptionFormatter = DescriptionFormatter.instance();

  private final Object actual;
  private final Object expected;

  /**
   * Creates a new {@link NotEqualErrorFactory}.
   *
   * @param actual the actual value in the failed assertion.
   * @param expected the expected value in the failed assertion.
   * @return the created {@code NotEqualErrorFactory}.
   */
  public static NotEqualErrorFactory shouldBeEqual(Object actual, Object expected) {
    return new NotEqualErrorFactory(actual, expected);
  }

  @VisibleForTesting
  public NotEqualErrorFactory(Object actual, Object expected) {
    this.actual = actual;
    this.expected = expected;
  }

  /**
   * Creates an {@link AssertionError} indicating that an assertion that verifies that two objects are equal, failed.
   *

   * If JUnit 4 is in the classpath, this method will instead create a {@code org.junit.ComparisonFailure} that
   * highlights the difference(s) between the expected and actual objects.
   *

   *
   * @param description the description of the failed assertion.
   * @return the created {@code AssertionError}.
   */
  @Override
  public AssertionError newAssertionError(Description description) {
    AssertionError error = comparisonFailure(description);
    if (error != null) {
      return error;
    }
    return Failures.instance().failure(defaultErrorMessage(description));
  }

  private String defaultErrorMessage(Description d) {
    return messageFormatter.format(d, "expected:<%s> but was:<%s>", expected, actual);
  }

  private AssertionError comparisonFailure(Description description) {
    try {
      AssertionError comparisonFailure = newComparisonFailure(descriptionFormatter.format(description).trim());
      Failures.instance().removeFestRelatedElementsFromStackTraceIfNeeded(comparisonFailure);
      return comparisonFailure;
    } catch (Throwable e) {
      return null;
    }
  }

  private AssertionError newComparisonFailure(String description) throws Exception {
    Object o = constructorInvoker.newInstance("org.junit.ComparisonFailure", MSG_ARG_TYPES, msgArgs(description));
    if (o instanceof AssertionError) {
      return (AssertionError) o;
    }
    return null;
  }

  private Object[] msgArgs(String description) {
    List<Object> args = newArrayList();
    args.add(description);
    args.addAll(expectedAndActualToString());
    return args.toArray();
  }

  private List<String> expectedAndActualToString() {
    String e = toStringOf(expected);
    String a = toStringOf(actual);
    if (e != null && e.equals(a)) {
      e = String.format(DETAILED_TO_STRING_FORMAT, e, System.identityHashCode(expected));
      a = String.format(DETAILED_TO_STRING_FORMAT, a, System.identityHashCode(actual));
    }
    return newArrayList(e, a);
  }

  @Override
  public boolean equals(Object o) {
    if (this == o) {
      return true;
    }
    if (o == null) {
      return false;
    }
    if (getClass() != o.getClass()) {
      return false;
    }
    NotEqualErrorFactory other = (NotEqualErrorFactory) o;
    if (!areEqual(actual, other.actual)) {
      return false;
    }
    return areEqual(expected, other.expected);
  }

  @Override
  public int hashCode() {
    int result = 1;
    result = HASH_CODE_PRIME * result + hashCodeFor(actual);
    result = HASH_CODE_PRIME * result + hashCodeFor(expected);
    return result;
  }
}


/*
 * Created on Dec 22, 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.api;

import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

import org.fest.assertions.core.EnumerableAssert;
import org.fest.assertions.description.Description;
import org.fest.assertions.internal.Strings;
import org.fest.util.VisibleForTesting;

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

 * To create a new instance of this class, invoke {@link Assertions#assertThat(String)}.
 *

 *
 * @author Yvonne Wang
 * @author David DIDIER
 * @author Alex Ruiz
 * @author Joel Costigliola
 */
public class StringAssert extends AbstractAssert<StringAssert, String> implements EnumerableAssert<StringAssert> {

  @VisibleForTesting
  Strings strings = Strings.instance();

  protected StringAssert(String actual) {
    super(actual, StringAssert.class);
  }

  protected StringAssert(String actual, Description description) {
    super(actual, StringAssert.class, description);
  }

  /** {@inheritDoc} */
  @Override
  public StringAssert isNullOrEmpty() {
    strings.assertNullOrEmpty(description, actual);
    return this;
  }

  /** {@inheritDoc} */
  @Override
  public StringAssert isEmpty() {
    strings.assertEmpty(description, actual);
    return this;
  }

  /** {@inheritDoc} */
  @Override
  public @Nonnull
  StringAssert isNotEmpty() {
    strings.assertNotEmpty(description, actual);
    return this;
  }

  /** {@inheritDoc} */
  @Override
  public @Nonnull
  StringAssert hasSize(int expected) {
    strings.assertHasSize(description, actual, expected);
    return this;
  }

  /**
   * Verifies that the actual {@code String} is equal to the given one, ignoring case considerations.
   *
   * @param expected the given {@code String} to compare the actual {@code String} to.
   * @return {@code this} assertion object.
   * @throws AssertionError if the actual {@code String} is not equal to the given one.
   */
  public @Nonnull
  StringAssert isEqualToIgnoringCase(@Nullable String expected) {
    strings.assertEqualsIgnoringCase(description, actual, expected);
    return this;
  }

  /**
   * Verifies that the actual {@code String} contains the given sequence.
   *
   * @param sequence the sequence to look for.
   * @return {@code this} assertion object.
   * @throws NullPointerException if the given sequence is {@code null}.
   * @throws AssertionError if the actual {@code String} is {@code null}.
   * @throws AssertionError if the actual {@code String} does not contain the given one.
   */
  public @Nonnull
  StringAssert contains(@Nonnull String sequence) {
    strings.assertContains(description, actual, sequence);
    return this;
  }

  /**
   * Verifies that the actual {@code String} does not contain the given sequence.
   *
   * @param sequence the sequence to look for.
   * @return {@code this} assertion object.
   * @throws NullPointerException if the given sequence is {@code null}.
   * @throws AssertionError if the actual {@code String} is {@code null}.
   * @throws AssertionError if the actual {@code String} contains the given one.
   */
  public @Nonnull
  StringAssert doesNotContain(@Nonnull String sequence) {
    strings.assertDoesNotContain(description, actual, sequence);
    return this;
  }

  /**
   * Verifies that the actual {@code String} starts with the given prefix.
   *
   * @param prefix the given prefix.
   * @return {@code this} assertion object.
   * @throws NullPointerException if the given prefix is {@code null}.
   * @throws AssertionError if the actual {@code String} is {@code null}.
   * @throws AssertionError if the actual {@code String} does not start with the given prefix.
   */
  public @Nonnull
  StringAssert startsWith(@Nonnull String prefix) {
    strings.assertStartsWith(description, actual, prefix);
    return this;
  }

  /**
   * Verifies that the actual {@code String} ends with the given suffix.
   *
   * @param suffix the given suffix.
   * @return {@code this} assertion object.
   * @throws NullPointerException if the given suffix is {@code null}.
   * @throws AssertionError if the actual {@code String} is {@code null}.
   * @throws AssertionError if the actual {@code String} does not end with the given suffix.
   */
  public @Nonnull
  StringAssert endsWith(@Nonnull String suffix) {
    strings.assertEndsWith(description, actual, suffix);
    return this;
  }

  /**
   * Verifies that the actual {@code String} matches the given regular expression.
   *
   * @param regex the regular expression to which the actual {@code String} is to be matched.
   * @return {@code this} assertion object.
   * @throws NullPointerException if the given pattern is {@code null}.
   * @throws PatternSyntaxException if the regular expression's syntax is invalid.
   * @throws AssertionError if the actual {@code String} is {@code null}.
   * @throws AssertionError if the actual {@code String} does not match the given regular expression.
   */
  public @Nonnull
  StringAssert matches(@Nonnull String regex) {
    strings.assertMatches(description, actual, regex);
    return this;
  }

  /**
   * Verifies that the actual {@code String} does not match the given regular expression.
   *
   * @param regex the regular expression to which the actual {@code String} is to be matched.
   * @return {@code this} assertion object.
   * @throws NullPointerException if the given pattern is {@code null}.
   * @throws PatternSyntaxException if the regular expression's syntax is invalid.
   * @throws AssertionError if the actual {@code String} matches the given regular expression.
   */
  public @Nonnull
  StringAssert doesNotMatch(@Nonnull String regex) {
    strings.assertDoesNotMatch(description, actual, regex);
    return this;
  }

  /**
   * Verifies that the actual {@code String} matches the given regular expression.
   *
   * @param pattern the compiled representation of the regular expression to which the actual {@code String} is
   *          to be matched.
   * @return {@code this} assertion object.
   * @throws NullPointerException if the given pattern is {@code null}.
   * @throws AssertionError if the actual {@code String} is {@code null}.
   * @throws AssertionError if the actual {@code String} does not match the given regular expression.
   */
  public @Nonnull
  StringAssert matches(@Nonnull Pattern pattern) {
    strings.assertMatches(description, actual, pattern);
    return this;
  }

  /**
   * Verifies that the actual {@code String} does not match the given regular expression.
   *
   * @param pattern the compiled representation of the regular expression to which the actual {@code String} is
   *          to be matched.
   * @return {@code this} assertion object.
   * @throws NullPointerException if the given pattern is {@code null}.
   * @throws AssertionError if the actual {@code String} does not match the given regular expression.
   */
  public @Nonnull
  StringAssert doesNotMatch(@Nonnull Pattern pattern) {
    strings.assertDoesNotMatch(description, actual, pattern);
    return this;
  }
}


/*
 * Created on Mar 17, 2012
 *
 * 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 @2012 the original author or authors.
 */
package org.fest.assertions.error;

import org.fest.assertions.core.Matcher;

/**
 * Creates an error message indicating that an assertion that verifies elements of a group satisfies at least n times a
 * {@code Condition} A group of elements can be a collection, an array.

 *
 * @author Nicolas François
 * @author Mikhail Mazursky
 * @author Joel Costigliola
 */
public class ElementsShouldBeAtLeast extends BasicErrorMessageFactory {

  /**
   * Creates a new {@link ElementsShouldBeAtLeast}.
   * @param actual the actual value in the failed assertion.
   * @param times least time the condition should be verify.
   * @param condition the {@code Condition}.
   * @return the created {@code ErrorMessageFactory}.
   */
  public static ErrorMessageFactory elementsShouldBeAtLeast(Object actual, int times, Matcher<?> condition) {
    return new ElementsShouldBeAtLeast(actual, times, condition);
  }

  private ElementsShouldBeAtLeast(Object actual, int times, Matcher<?> condition) {
    super("expecting elements:\n<%s>\n to be at least %s times <%s>", actual, times, condition);
  }
}


/*
 * Created on Mar 22, 2012
 *
 * 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 @2012 the original author or authors.
 */
package org.fest.assertions.condition;

import org.fest.assertions.core.Matcher;

/**
 * Returns {@code true} if the condition is not satisfied.
 *
 * @author Nicolas François
 * @author Joel Costigliola
 * @author Mikhail Mazursky
 */
public class DoesNotHave<T> extends Negative<T> {

  /**
   * Creates a new </code>{@link DoesNotHave}</code>.
   *
   * @param condition the condition to inverse.
   * @return The Not condition created.
   */
  public static <T> DoesNotHave<T> doesNotHave(Matcher<? super T> condition) {
    return new DoesNotHave<T>(condition);
  }

  private DoesNotHave(Matcher<? super T> condition) {
    super(condition);
  }

  @Override
  public String toString() {
    return String.format("does not have :<%s>", condition);
  }

}


/*
 * Created on Dec 16, 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.internal;

import static org.fest.assertions.error.ShouldBeSorted.shouldBeSorted;

import org.fest.assertions.data.Index;
import org.fest.assertions.description.Description;
import org.fest.util.VisibleForTesting;

/**
 * Reusable assertions for arrays of {@code byte}s.
 *
 * @author Alex Ruiz
 * @author Mikhail Mazursky
 * @author Nicolas François
 * @author Yvonne Wang
 */
public class ByteArrays {

  private static final ByteArrays INSTANCE = new ByteArrays();

  /**
   * Returns the singleton instance of this class.
   *
   * @return the singleton instance of this class.
   */
  public static ByteArrays instance() {
    return INSTANCE;
  }

  private final Arrays arrays = Arrays.instance();

  @VisibleForTesting
  Failures failures = Failures.instance();

  /**
   * Asserts that the given array is {@code null} or empty.
   *
   * @param description contains information about the assertion.
   * @param actual the given array.
   * @throws AssertionError if the given array is not {@code null} *and* contains one or more elements.
   */
  public void assertNullOrEmpty(Description description, byte[] actual) {
    arrays.assertNullOrEmpty(description, actual);
  }

  /**
   * Asserts that the given array is empty.
   *
   * @param description contains information about the assertion.
   * @param actual the given array.
   * @throws AssertionError if the given array is {@code null}.
   * @throws AssertionError if the given array is not empty.
   */
  public void assertEmpty(Description description, byte[] actual) {
    arrays.assertEmpty(description, actual);
  }

  /**
   * Asserts that the given array is not empty.
   *
   * @param description contains information about the assertion.
   * @param actual the given array.
   * @throws AssertionError if the given array is {@code null}.
   * @throws AssertionError if the given array is empty.
   */
  public void assertNotEmpty(Description description, byte[] actual) {
    arrays.assertNotEmpty(description, actual);
  }

  /**
   * Asserts that the number of elements in the given array is equal to the expected one.
   *
   * @param description contains information about the assertion.
   * @param actual the given array.
   * @param expectedSize the expected size of {@code actual}.
   * @throws AssertionError if the given array is {@code null}.
   * @throws AssertionError if the number of elements in the given array is different than the expected one.
   */
  public void assertHasSize(Description description, byte[] actual, int expectedSize) {
    arrays.assertHasSize(description, actual, expectedSize);
  }

  /**
   * Asserts that the given array contains the given values, in any order.
   *
   * @param description contains information about the assertion.
   * @param actual the given array.
   * @param values the values that are expected to be in the given array.
   * @throws NullPointerException if the array of values is {@code null}.
   * @throws IllegalArgumentException if the array of values is empty.
   * @throws AssertionError if the given array is {@code null}.
   * @throws AssertionError if the given array does not contain the given values.
   */
  public void assertContains(Description description, byte[] actual, byte[] values) {
    arrays.assertContains(description, actual, values);
  }

  /**
   * Verifies that the given array contains the given value at the given index.
   *
   * @param description contains information about the assertion.
   * @param actual the given array.
   * @param value the value to look for.
   * @param index the index where the value should be stored in the given array.
   * @throws AssertionError if the given array is {@code null} or empty.
   * @throws NullPointerException if the given {@code Index} is {@code null}.
   * @throws IndexOutOfBoundsException if the value of the given {@code Index} is equal to or greater than the size of
   *           the given array.
   * @throws AssertionError if the given array does not contain the given value at the given index.
   */
  public void assertContains(Description description, byte[] actual, byte value, Index index) {
    arrays.assertContains(description, actual, value, index);
  }

  /**
   * Verifies that the given array does not contain the given value at the given index.
   *
   * @param description contains information about the assertion.
   * @param actual the given array.
   * @param value the value to look for.
   * @param index the index where the value should be stored in the given array.
   * @throws AssertionError if the given array is {@code null}.
   * @throws NullPointerException if the given {@code Index} is {@code null}.
   * @throws AssertionError if the given array contains the given value at the given index.
   */
  public void assertDoesNotContain(Description description, byte[] actual, byte value, Index index) {
    arrays.assertDoesNotContain(description, actual, value, index);
  }

  /**
   * Asserts that the given array contains only the given values and nothing else, in any order.
   *
   * @param description contains information about the assertion.
   * @param actual the given array.
   * @param values the values that are expected to be in the given array.
   * @throws NullPointerException if the array of values is {@code null}.
   * @throws IllegalArgumentException if the array of values is empty.
   * @throws AssertionError if the given array is {@code null}.
   * @throws AssertionError if the given array does not contain the given values or if the given array contains values
   *           that are not in the given array.
   */
  public void assertContainsOnly(Description description, byte[] actual, byte[] values) {
    arrays.assertContainsOnly(description, actual, values);
  }

  /**
   * Verifies that the given array contains the given sequence of values, without any other values between them.
   *
   * @param description contains information about the assertion.
   * @param actual the given array.
   * @param sequence the sequence of values to look for.
   * @throws AssertionError if the given array is {@code null}.
   * @throws NullPointerException if the given sequence is {@code null}.
   * @throws IllegalArgumentException if the given sequence is empty.
   * @throws AssertionError if the given array does not contain the given sequence of values.
   */
  public void assertContainsSequence(Description description, byte[] actual, byte[] sequence) {
    arrays.assertContainsSequence(description, actual, sequence);
  }

  /**
   * Asserts that the given array does not contain the given values.
   *
   * @param description contains information about the assertion.
   * @param actual the given array.
   * @param values the values that are expected not to be in the given array.
   * @throws NullPointerException if the array of values is {@code null}.
   * @throws IllegalArgumentException if the array of values is empty.
   * @throws AssertionError if the given array is {@code null}.
   * @throws AssertionError if the given array contains any of given values.
   */
  public void assertDoesNotContain(Description description, byte[] actual, byte[] values) {
    arrays.assertDoesNotContain(description, actual, values);
  }

  /**
   * Asserts that the given array does not have duplicate values.
   *
   * @param description contains information about the assertion.
   * @param actual the given array.
   * @throws NullPointerException if the array of values is {@code null}.
   * @throws IllegalArgumentException if the array of values is empty.
   * @throws AssertionError if the given array is {@code null}.
   * @throws AssertionError if the given array contains duplicate values.
   */
  public void assertDoesNotHaveDuplicates(Description description, byte[] actual) {
    arrays.assertDoesNotHaveDuplicates(description, actual);
  }

  /**
   * Verifies that the given array starts with the given sequence of values, without any other values between them.
   * Similar to {@link #assertContainsSequence(Description, byte[], byte[])}, but it also verifies that the
   * first element in the sequence is also the first element of the given array.
   *
   * @param description contains information about the assertion.
   * @param actual the given array.
   * @param sequence the sequence of values to look for.
   * @throws NullPointerException if the given argument is {@code null}.
   * @throws IllegalArgumentException if the given argument is an empty array.
   * @throws AssertionError if the given array is {@code null}.
   * @throws AssertionError if the given array does not start with the given sequence of values.
   */
  public void assertStartsWith(Description description, byte[] actual, byte[] sequence) {
    arrays.assertStartsWith(description, actual, sequence);
  }

  /**
   * Verifies that the given array ends with the given sequence of values, without any other values between them.
   * Similar to {@link #assertContainsSequence(Description, byte[], byte[])}, but it also verifies that the
   * last element in the sequence is also the last element of the given array.
   *
   * @param description contains information about the assertion.
   * @param actual the given array.
   * @param sequence the sequence of values to look for.
   * @throws NullPointerException if the given argument is {@code null}.
   * @throws IllegalArgumentException if the given argument is an empty array.
   * @throws AssertionError if the given array is {@code null}.
   * @throws AssertionError if the given array does not end with the given sequence of values.
   */
  public void assertEndsWith(Description description, byte[] actual, byte[] sequence) {
    arrays.assertEndsWith(description, actual, sequence);
  }

  /**
   * Verifies that the actual is sorted into ascending order according to the natural ordering of its elements.
   *

   * Empty arrays are considered sorted.
   *
   * @param description contains the information about the assertion.
   * @param actual the given array.
   * @throws AssertionError if the {@code actual} is {@code null}.
   */
  public void assertIsSorted(Description description, byte[] actual) {
    if (actual == null) {
      throw failures.failure("The actual is null");
    }
    if (actual.length == 0) {
      return;
    }
    for (int i = 0; i < actual.length - 1; i++) {
      if (actual[i] > actual[i + 1]) {
        throw failures.failure(description, shouldBeSorted(i, actual));
      }
    }
  }
}


/*
 * Created on Aug 4, 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.internal;

import static org.fest.assertions.error.NotEqualErrorFactory.shouldBeEqual;
import static org.fest.assertions.error.ShouldNotBeEqual.shouldNotBeEqual;
import static org.fest.assertions.error.ShouldNotBeNull.shouldNotBeNull;
import static org.fest.util.Objects.areEqual;
import static org.fest.util.Preconditions.checkNotNull;

import org.fest.assertions.description.Description;
import org.fest.assertions.error.BasicErrorMessageFactory;
import org.fest.util.VisibleForTesting;

/**
 * Reusable assertions for {@code Object}s.
 *
 * @author Yvonne Wang
 * @author Alex Ruiz
 */
public class Objects {
  private static final Objects INSTANCE = new Objects();

  public static Objects instance() {
    return INSTANCE;
  }

  @VisibleForTesting
  Failures failures = Failures.instance();

  @VisibleForTesting
  Objects() {
  }

  /**
   * Asserts that the actual object is {@code null}.
   *
   * @param description the description of the actual object.
   * @param actual the actual object.
   * @throws AssertionError if the actual object is not {@code null}.
   */
  public void assertNull(Description description, Object actual) {
    assertEqual(description, actual, null);
  }

  /**
   * Asserts that the actual object is not {@code null}.
   *
   * @param description the description of the actual object.
   * @param actual the actual object.
   * @throws AssertionError if the actual object is {@code null}.
   */
  public void assertNotNull(Description description, Object actual) {
    if (actual == null) {
      throw failures.failure(description, shouldNotBeNull());
    }
  }

  /**
   * Asserts that two objects are equal.
   *
   * @param description the description of the actual object.
   * @param actual the actual object.
   * @param expected the expected object.
   * @throws AssertionError if {@code actual} is not equal to {@code expected}. This method will throw a
   *           {@code org.junit.ComparisonFailure} instead if JUnit is in the classpath and the given objects are not
   *           equal.
   */
  public void assertEqual(Description description, Object actual, Object expected) {
    if (!areEqual(actual, expected)) {
      throw shouldBeEqual(actual, expected).newAssertionError(description);
    }
  }

  /**
   * Asserts that two objects are not equal.
   *
   * @param description the description of the actual object.
   * @param actual the actual object.
   * @param other the object to compare {@code actual} to.
   * @throws AssertionError if {@code actual} is equal to {@code other}.
   */
  public void assertNotEqual(Description description, Object actual, Object other) {
    if (areEqual(actual, other)) {
      throw failures.failure(description, shouldNotBeEqual(actual, other));
    }
  }

  /**
   * Asserts that two objects refer to the same instance.
   *
   * @param description the description of the actual object.
   * @param actual the actual object.
   * @param expected the expected object.
   * @throws AssertionError if the given objects do not refer to the same instance.
   */
  public void assertSame(Description description, Object actual, Object expected) {
    if (actual != expected) {
      String format = "expected:<%s> and actual:<%s> should refer to the same instance";
      throw failures.failure(description, new BasicErrorMessageFactory(format, expected, actual));
    }
  }

  /**
   * Asserts that two objects do not refer to the same instance.
   *
   * @param description the description of the actual object.
   * @param actual the actual object.
   * @param other the object to compare {@code actual} to.
   * @throws AssertionError if the given objects refer to the same instance.
   */
  public void assertNotSame(Description description, Object actual, Object other) {
    if (actual == other) {
      String format = "expected not same:<%s>";
      throw failures.failure(description, new BasicErrorMessageFactory(format, actual));
    }
  }

  /**
   * Asserts that the actual object is an instance of the given type.
   *
   * @param description the description of the actual object.
   * @param actual the actual object.
   * @param type the type to check the actual object against.
   * @throws NullPointerException if the given type is {@code null}.
   * @throws AssertionError if the actual object is {@code null}.
   * @throws AssertionError if the actual object is not an instance of the given type.
   */
  public void assertIsInstanceOf(Description description, Object actual, Class<?> type) {
    checkNotNull(type);
    assertNotNull(description, actual);
    if (!type.isInstance(actual)) {
      String format = "expecting <%s> to be an instance of:<%s> but was instance of:<%s>";
      throw failures.failure(description, new BasicErrorMessageFactory(format, actual, type, actual.getClass()));
    }
  }

  /**
   * Asserts that the actual object is not an instance of the given type.
   *
   * @param description the description of the actual object.
   * @param actual the actual object.
   * @param type the type to check the actual object against.
   * @throws NullPointerException if the given type is {@code null}.
   * @throws AssertionError if the actual object is an instance of the given type.
   */
  public void assertIsNotInstanceOf(Description description, Object actual, Class<?> type) {
    checkNotNull(type);
    if (type.isInstance(actual)) {
      String format = "expecting <%s> not to be an instance of:<%s>";
      throw failures.failure(description, new BasicErrorMessageFactory(format, actual, type));
    }
  }

  /**
   * Verifies that the actual object is an instance of any of the given types.
   *
   * @param description the description of the actual object.
   * @param actual the actual object.
   * @param types the types to check the actual object against.
   * @throws NullPointerException if the given array is {@code null}.
   * @throws IllegalArgumentException if the given array is empty.
   * @throws NullPointerException if the given array has {@code null} elements.
   * @throws AssertionError if the actual object is {@code null}.
   * @throws AssertionError if the actual object is not an instance of any of the given types.
   */
  public void assertIsInstanceOfAny(Description description, Object actual, Class<?>[] types) {
    checkNotNullOrEmpty(types);
    assertNotNull(description, actual);
    if (!isInstanceOfAny(actual, types)) {
      String format = "expecting <%s> to be an instance of any of:<%s> but was instance of:<%s>";
      throw failures.failure(description, new BasicErrorMessageFactory(format, actual, types, actual.getClass()));
    }
  }

  /**
   * Verifies that the actual object is not an instance of any of the given types.
   *
   * @param description the description of the actual object.
   * @param actual the actual object.
   * @param types the types to check the actual object against.
   * @throws NullPointerException if the given array is {@code null}.
   * @throws IllegalArgumentException if the given array is empty.
   * @throws NullPointerException if the given array has {@code null} elements.
   * @throws AssertionError if the actual object is an instance of any of the given types.
   */
  public void assertIsNotInstanceOfAny(Description description, Object actual, Class<?>[] types) {
    checkNotNullOrEmpty(types);
    if (isInstanceOfAny(actual, types)) {
      String format = "expecting <%s> not to be an instance of any of:<%s>";
      throw failures.failure(description, new BasicErrorMessageFactory(format, actual, types));
    }
  }

  private void checkNotNullOrEmpty(Class<?>[] types) {
    checkNotNull(types);
    if (types.length == 0) {
      throw new IllegalArgumentException();
    }
  }

  private boolean isInstanceOfAny(Object actual, Class<?>[] types) {
    for (Class<?> type : types) {
      type = checkNotNull(type);
      if (type.isInstance(actual)) {
        return true;
      }
    }
    return false;
  }
}


/*
 * Created on Mar 17, 2012
 *
 * 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 @2012 the original author or authors.
 */
package org.fest.assertions.error;

import org.fest.assertions.core.Matcher;

/**
 * Creates an error message indicating that an assertion that verifies elements of a group satisfies exactly n times a
 * {@code Condition} A group of elements can be a collection, an array.

 *
 * @author Nicolas François
 * @author Mikhail Mazursky
 * @author Joel Costigliola
 */
public class ElementsShouldBeExactly extends BasicErrorMessageFactory {

  /**
   * Creates a new {@link ElementsShouldBeExactly}.
   * @param actual the actual value in the failed assertion.
   * @param times exactly times the condition should be verify.
   * @param condition the {@code Condition}.
   * @return the created {@code ErrorMessageFactory}.
   */
  public static ErrorMessageFactory elementsShouldBeExactly(Object actual, int times, Matcher<?> condition) {
    return new ElementsShouldBeExactly(actual, times, condition);
  }

  private ElementsShouldBeExactly(Object actual, int times, Matcher<?> condition) {
    super("expecting elements:\n<%s>\n to be exactly %s times <%s>", actual, times, condition);
  }
}


/*
 * Created on Dec 20, 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.internal;

import static org.fest.assertions.error.ShouldBeSorted.shouldBeSorted;

import org.fest.assertions.data.Index;
import org.fest.assertions.description.Description;
import org.fest.util.VisibleForTesting;

/**
 * Reusable assertions for arrays of {@code char}s.
 *
 * @author Alex Ruiz
 * @author Joel Costigliola
 * @author Mikhail Mazursky
 * @author Nicolas François
 * @author Yvonne Wang
 */
public class CharArrays {

  private static final CharArrays INSTANCE = new CharArrays();

  /**
   * Returns the singleton instance of this class.
   *
   * @return the singleton instance of this class.
   */
  public static CharArrays instance() {
    return INSTANCE;
  }

  private final Arrays arrays = Arrays.instance();

  @VisibleForTesting
  Failures failures = Failures.instance();

  /**
   * Asserts that the given array is {@code null} or empty.
   *
   * @param description contains information about the assertion.
   * @param actual the given array.
   * @throws AssertionError if the given array is not {@code null} *and* contains one or more elements.
   */
  public void assertNullOrEmpty(Description description, char[] actual) {
    arrays.assertNullOrEmpty(description, actual);
  }

  /**
   * Asserts that the given array is empty.
   *
   * @param description contains information about the assertion.
   * @param actual the given array.
   * @throws AssertionError if the given array is {@code null}.
   * @throws AssertionError if the given array is not empty.
   */
  public void assertEmpty(Description description, char[] actual) {
    arrays.assertEmpty(description, actual);
  }

  /**
   * Asserts that the given array is not empty.
   *
   * @param description contains information about the assertion.
   * @param actual the given array.
   * @throws AssertionError if the given array is {@code null}.
   * @throws AssertionError if the given array is empty.
   */
  public void assertNotEmpty(Description description, char[] actual) {
    arrays.assertNotEmpty(description, actual);
  }

  /**
   * Asserts that the number of elements in the given array is equal to the expected one.
   *
   * @param description contains information about the assertion.
   * @param actual the given array.
   * @param expectedSize the expected size of {@code actual}.
   * @throws AssertionError if the given array is {@code null}.
   * @throws AssertionError if the number of elements in the given array is different than the expected one.
   */
  public void assertHasSize(Description description, char[] actual, int expectedSize) {
    arrays.assertHasSize(description, actual, expectedSize);
  }

  /**
   * Asserts that the given array contains the given values, in any order.
   *
   * @param description contains information about the assertion.
   * @param actual the given array.
   * @param values the values that are expected to be in the given array.
   * @throws NullPointerException if the array of values is {@code null}.
   * @throws IllegalArgumentException if the array of values is empty.
   * @throws AssertionError if the given array is {@code null}.
   * @throws AssertionError if the given array does not contain the given values.
   */
  public void assertContains(Description description, char[] actual, char[] values) {
    arrays.assertContains(description, actual, values);
  }

  /**
   * Verifies that the given array contains the given value at the given index.
   *
   * @param description contains information about the assertion.
   * @param actual the given array.
   * @param value the value to look for.
   * @param index the index where the value should be stored in the given array.
   * @throws AssertionError if the given array is {@code null} or empty.
   * @throws NullPointerException if the given {@code Index} is {@code null}.
   * @throws IndexOutOfBoundsException if the value of the given {@code Index} is equal to or greater than the size of
   *           the given array.
   * @throws AssertionError if the given array does not contain the given value at the given index.
   */
  public void assertContains(Description description, char[] actual, char value, Index index) {
    arrays.assertContains(description, actual, value, index);
  }

  /**
   * Verifies that the given array does not contain the given value at the given index.
   *
   * @param description contains information about the assertion.
   * @param actual the given array.
   * @param value the value to look for.
   * @param index the index where the value should be stored in the given array.
   * @throws AssertionError if the given array is {@code null}.
   * @throws NullPointerException if the given {@code Index} is {@code null}.
   * @throws AssertionError if the given array contains the given value at the given index.
   */
  public void assertDoesNotContain(Description description, char[] actual, char value, Index index) {
    arrays.assertDoesNotContain(description, actual, value, index);
  }

  /**
   * Asserts that the given array contains only the given values and nothing else, in any order.
   *
   * @param description contains information about the assertion.
   * @param actual the given array.
   * @param values the values that are expected to be in the given array.
   * @throws NullPointerException if the array of values is {@code null}.
   * @throws IllegalArgumentException if the array of values is empty.
   * @throws AssertionError if the given array is {@code null}.
   * @throws AssertionError if the given array does not contain the given values or if the given array contains values
   *           that are not in the given array.
   */
  public void assertContainsOnly(Description description, char[] actual, char[] values) {
    arrays.assertContainsOnly(description, actual, values);
  }

  /**
   * Verifies that the given array contains the given sequence of values, without any other values between them.
   *
   * @param description contains information about the assertion.
   * @param actual the given array.
   * @param sequence the sequence of values to look for.
   * @throws AssertionError if the given array is {@code null}.
   * @throws NullPointerException if the given sequence is {@code null}.
   * @throws IllegalArgumentException if the given sequence is empty.
   * @throws AssertionError if the given array does not contain the given sequence of values.
   */
  public void assertContainsSequence(Description description, char[] actual, char[] sequence) {
    arrays.assertContainsSequence(description, actual, sequence);
  }

  /**
   * Asserts that the given array does not contain the given values.
   *
   * @param description contains information about the assertion.
   * @param actual the given array.
   * @param values the values that are expected not to be in the given array.
   * @throws NullPointerException if the array of values is {@code null}.
   * @throws IllegalArgumentException if the array of values is empty.
   * @throws AssertionError if the given array is {@code null}.
   * @throws AssertionError if the given array contains any of given values.
   */
  public void assertDoesNotContain(Description description, char[] actual, char[] values) {
    arrays.assertDoesNotContain(description, actual, values);
  }

  /**
   * Asserts that the given array does not have duplicate values.
   *
   * @param description contains information about the assertion.
   * @param actual the given array.
   * @throws NullPointerException if the array of values is {@code null}.
   * @throws IllegalArgumentException if the array of values is empty.
   * @throws AssertionError if the given array is {@code null}.
   * @throws AssertionError if the given array contains duplicate values.
   */
  public void assertDoesNotHaveDuplicates(Description description, char[] actual) {
    arrays.assertDoesNotHaveDuplicates(description, actual);
  }

  /**
   * Verifies that the given array starts with the given sequence of values, without any other values between them.
   * Similar to {@link #assertContainsSequence(Description, char[], char[])}, but it also verifies that the
   * first element in the sequence is also the first element of the given array.
   *
   * @param description contains information about the assertion.
   * @param actual the given array.
   * @param sequence the sequence of values to look for.
   * @throws NullPointerException if the given argument is {@code null}.
   * @throws IllegalArgumentException if the given argument is an empty array.
   * @throws AssertionError if the given array is {@code null}.
   * @throws AssertionError if the given array does not start with the given sequence of values.
   */
  public void assertStartsWith(Description description, char[] actual, char[] sequence) {
    arrays.assertStartsWith(description, actual, sequence);
  }

  /**
   * Verifies that the given array ends with the given sequence of values, without any other values between them.
   * Similar to {@link #assertContainsSequence(Description, char[], char[])}, but it also verifies that the
   * last element in the sequence is also the last element of the given array.
   *
   * @param description contains information about the assertion.
   * @param actual the given array.
   * @param sequence the sequence of values to look for.
   * @throws NullPointerException if the given argument is {@code null}.
   * @throws IllegalArgumentException if the given argument is an empty array.
   * @throws AssertionError if the given array is {@code null}.
   * @throws AssertionError if the given array does not end with the given sequence of values.
   */
  public void assertEndsWith(Description description, char[] actual, char[] sequence) {
    arrays.assertEndsWith(description, actual, sequence);
  }

  /**
   * Verifies that the actual is sorted into ascending order according to the natural ordering of its elements.
   * Empty arrays are considered sorted.
   *
   * @param description contains the information about the assertion.
   * @param actual the given array.
   * @throws AssertionError if the {@code actual} is {@code null}.
   */
  public void assertIsSorted(Description description, char[] actual) {
    if(actual == null) {
      throw failures.failure("The actual is null");
    }
    if (actual.length == 0) {
      return;
    }
    for (int i = 0; i < actual.length - 1; i++) {
      if (actual[i] > actual[i + 1]) {
        throw failures.failure(description, shouldBeSorted(i, 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.api;

import static java.lang.String.format;

import org.fest.assertions.internal.Failures;

/**
 * Common failures.
 *
 * @author Alex Ruiz
 * @author Yvonne Wang
 * @author Joel Costigliola
 */
public final class Fail {

  /**
   * Sets whether we remove elements related to Fest from assertion error stack trace.
   *
   * @param removeFestRelatedElementsFromStackTrace flag.
   */
  public static void setRemoveFestRelatedElementsFromStackTrace(boolean removeFestRelatedElementsFromStackTrace) {
    Failures.instance().setRemoveFestRelatedElementsFromStackTrace(removeFestRelatedElementsFromStackTrace);
  }

  /**
   * Fails with the given message.
   *
   * @param failureMessage error message.
   * @throws AssertionError with the given message.
   */
  public static void fail(String failureMessage) {
    throw Failures.instance().failure(failureMessage);
  }

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

  /**
   * Throws an {@link AssertionError} with a message explaining that a {@link Throwable} of given class was expected to
   * be thrown but had not been.
   *
   * @param throwableClass the Throwable class that was expected to be thrown.
   * @throws AssertionError with a message explaining that a {@link Throwable} of given class was expected to be thrown
   *           but had not been.
   */
  public static void failBecauseExceptionWasNotThrown(Class<? extends Throwable> throwableClass) {
    throw Failures.instance().failure(format("Expected %s to be thrown", throwableClass.getSimpleName()));
  }

  /**
   * 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() {
  }
}


/*
 * Created on Jan 26, 2011
 *
 * 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 @2011-2013 the original author or authors.
 */
package org.fest.assertions.internal;

import static org.fest.util.Preconditions.checkNotNull;

import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;

import org.fest.assertions.description.Description;
import org.fest.assertions.error.BasicErrorMessageFactory;
import org.fest.util.IORuntimeException;
import org.fest.util.VisibleForTesting;

/**
 * Reusable assertions for {@link File}s.
 *
 * @author David DIDIER
 * @author Yvonne Wang
 * @author Alex Ruiz
 * @author Olivier Demeijer
 * @author Olivier Michallat
 */
public class Files {
  private static final Files INSTANCE = new Files();

  public static Files instance() {
    return INSTANCE;
  }

  @VisibleForTesting
  FileContentComparator comparator = new FileContentComparator();

  @VisibleForTesting
  Failures failures = Failures.instance();

  @VisibleForTesting
  Files() {
  }

  /**
   * Asserts that the actual {@link File} represents an existing file or directory.
   *
   * @param description the description of the actual {@code File}.
   * @param actual the actual {@code File}.
   * @throws AssertionError if the actual {@code File} is {@code null}.
   * @throws AssertionError if the actual {@link File} represents a file or directory that does not exist.
   */
  public void assertExists(Description description, File actual) {
    assertNotNull(description, actual);
    if (!actual.exists()) {
      String format = "expecting resource in path:<%s> to exist";
      throw failures.failure(description, new BasicErrorMessageFactory(format, actual));
    }
  }

  /**
   * Asserts that the actual {@link File} represents a file or directory that does not exist.
   *
   * @param description the description of the actual {@code File}.
   * @param actual the actual {@code File}.
   * @throws AssertionError if the actual {@code File} is {@code null}.
   * @throws AssertionError if the actual {@link File} represents an existing file or directory.
   */
  public void assertDoesNotExist(Description description, File actual) {
    assertNotNull(description, actual);
    if (actual.exists()) {
      String format = "expecting resource in path:<%s> not to exist";
      throw failures.failure(description, new BasicErrorMessageFactory(format, actual));
    }
  }

  /**
   * Asserts that the actual {@code File} represents an existing file.
   *
   * @param description the description of the actual {@code File}.
   * @param actual the actual {@code File}.
   * @throws AssertionError if the actual {@code File} is {@code null}.
   * @throws AssertionError if the actual {@code File} does not represent an existing file.
   */
  public void assertIsFile(Description description, File actual) {
    assertNotNull(description, actual);
    if (!actual.isFile()) {
      String format = "expecting path:<%s> to represent an existing file";
      throw failures.failure(description, new BasicErrorMessageFactory(format, actual));
    }
  }

  /**
   * Asserts that the actual {@code File} represents an existing directory.
   *
   * @param description the description of the actual {@code File}.
   * @param actual the actual {@code File}.
   * @throws AssertionError if the actual {@code File} is {@code null}.
   * @throws AssertionError if the actual {@code File} does not represent an existing directory.
   */
  public void assertIsDirectory(Description description, File actual) {
    assertNotNull(description, actual);
    if (!actual.isDirectory()) {
      String format = "expecting path:<%s> to represent an existing directory";
      throw failures.failure(description, new BasicErrorMessageFactory(format, actual));
    }
  }

  /**
   * Asserts that the given {@code File}s represent existing files with equal content. It is assumed that the content of
   * the files is text.
   *
   * @param description the description of the actual {@code File}.
   * @param actual the actual {@code File}.
   * @param expected the expected {@code File}.
   * @param charset the charset to use when reading the contents of the given {@code File}s.
   * @throws NullPointerException if the expected {@code File} is {@code null}.
   * @throws IllegalArgumentException if the expected {@code File} does not represent an existing file.
   * @throws NullPointerException if the given charset is {@code null}.
   * @throws AssertionError if the actual {@code File} is {@code null}.
   * @throws AssertionError if the actual {@code File} does not represent an existing file.
   * @throws IORuntimeException if an I/O error occurs.
   * @throws AssertionError if the given files do not have equal content.
   */
  public void assertEqualContent(Description description, File actual, File expected, Charset charset) {
    checkIsFile(expected);
    checkNotNull(charset);
    assertIsFile(description, actual);
    try {
      String lineSeparator = System.getProperty("line.separator");
      FileDiffs diffs = comparator.compareContents(actual, expected, charset);
      if (!diffs.isEmpty()) {
        String format = "files expected:<%s> and actual:<%s> do not have equal content:" + lineSeparator + "%s"
            + lineSeparator + "using charset:<%s>";
        throw failures.failure(description, new BasicErrorMessageFactory(format, expected, actual, diffs, charset));
      }
    } catch (IOException e) {
      String format = "Failed to compare contents of files:<%s> and:<%s> using charset:<%s>";
      throw new IORuntimeException(String.format(format, actual, expected, charset), e);
    }
  }

  private void checkIsFile(File expected) {
    checkNotNull(expected);
    if (!expected.isFile()) {
      throw new IllegalArgumentException();
    }
  }

  private static void assertNotNull(Description description, File actual) {
    Objects.instance().assertNotNull(description, actual);
  }
}


/*
 * Created on Mar 17, 2012
 *
 * 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 @2012 the original author or authors.
 */
package org.fest.assertions.error;

import org.fest.assertions.core.Matcher;

/**
 * Creates an error message indicating that an assertion that verifies elements of a group satisfies at least n times a
 * {@code Condition} A group of elements can be a collection, an array.

 *
 * @author Nicolas François
 * @author Mikhail Mazursky
 * @author Joel Costigliola
 */
public class ElementsShouldHaveAtLeast extends BasicErrorMessageFactory {

  /**
   * Creates a new {@link ElementsShouldHaveAtLeast}.
   * @param actual the actual value in the failed assertion.
   * @param times least time the condition should be verify.
   * @param condition the {@code Condition}.
   * @return the created {@code ErrorMessageFactory}.
   */
  public static ErrorMessageFactory elementsShouldHaveAtLeast(Object actual, int times, Matcher<?> condition) {
    return new ElementsShouldHaveAtLeast(actual, times, condition);
  }

  private ElementsShouldHaveAtLeast(Object actual, int times, Matcher<?> condition) {
    super("expecting elements:\n<%s>\n to have at least %s times <%s>", actual, times, condition);
  }
}


/*
 * Created on Feb 7, 2011
 *
 * 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 @2011 the original author or authors.
 */
package org.fest.assertions.condition;

import org.fest.assertions.core.Matcher;

/**
 * Returns {@code true} if all of the joined conditions is satisfied.
 * @param <T> the type of object this condition accepts.
 *
 * @author Yvonne Wang
 * @author Mikhail Mazursky
 */
public class AllOf<T> extends Join<T> {

  /**
   * Creates a new {@link AllOf}
   * @param <T> the type of object the given condition accept.
   * @param conditions the conditions to evaluate.
   * @return the created {@code AnyOf}.
   * @throws NullPointerException if the given array is {@code null}.
   * @throws NullPointerException if any of the elements in the given array is {@code null}.
   */
  public static <T> Matcher<T> allOf(Matcher<? super T>... conditions) {
    return new AllOf<T>(conditions);
  }

  /**
   * Creates a new {@link AllOf}
   * @param <T> the type of object the given condition accept.
   * @param conditions the conditions to evaluate.
   * @return the created {@code AnyOf}.
   * @throws NullPointerException if the given iterable is {@code null}.
   * @throws NullPointerException if any of the elements in the given iterable is {@code null}.
   */
  public static <T> Matcher<T> allOf(Iterable<? extends Matcher<? super T>> conditions) {
    return new AllOf<T>(conditions);
  }

  private AllOf(Matcher<? super T>... conditions) {
    super(conditions);
  }

  private AllOf(Iterable<? extends Matcher<? super T>> conditions) {
    super(conditions);
  }

  /** {@inheritDoc} */
  @Override
  public boolean matches(T value) {
    for (Matcher<? super T> condition : conditions)
      if (!condition.matches(value)) return false;
    return true;
  }

  @Override
  public String toString() {
    return String.format("all of:<%s>", conditions);
  }
}


/*
 * Created on Mar 5, 2012
 *
 * 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 @2012 the original author or authors.
 */
package org.fest.assertions.error;

import org.fest.assertions.core.Matcher;

/**
 * Creates an error message indicating that an assertion that verifies that each element of a group satisfies a {@code Condition}
 * A group of elements can be a collection, an array.

 *
 * @author Nicolas François
 * @author Mikhail Mazursky
 */
public class ElementsShouldBe extends BasicErrorMessageFactory {

  /**
   * Creates a new {@link ElementsShouldBe}.
   * @param actual the actual value in the failed assertion.
   * @param notSatisfies elements that not satisfies the condition
   * @param condition the {@code Condition}.
   * @return the created {@code ErrorMessageFactory}.
   */
  public static ErrorMessageFactory elementsShouldBe(Object actual, Object notSatisfies, Matcher<?> condition) {
    return new ElementsShouldBe(actual, notSatisfies, condition);
  }

  private ElementsShouldBe(Object actual, Object notSatisfies, Matcher<?> condition) {
    super("expecting elements:\n<%s>\n of \n<%s>\n to be <%s>", notSatisfies, actual, condition);
  }

}


/*
 * Created on Oct 18, 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-2011 the original author or authors.
 */
package org.fest.assertions.error;

/**
 * Creates an error message indicating that an assertion that verifies a group of elements contains a given set of values failed.
 * A group of elements can be a collection, an array or a {@code String}.

 * It also mention the {@link Comparison} used.
 *
 * @author Alex Ruiz
 * @author Joel Costigliola
 */
public class ShouldContain extends BasicErrorMessageFactory {

  /**
   * Creates a new {@link ShouldContain}.
   * @param actual the actual value in the failed assertion.
   * @param expected values expected to be in {@code actual}.
   * @param notFound the values in {@code expected} not found in {@code actual}.
   * @return the created {@code ErrorMessageFactory}.
   */
  public static ErrorMessageFactory shouldContain(Object actual, Object expected, Object notFound) {
    return new ShouldContain(actual, expected, notFound);
  }

  private ShouldContain(Object actual, Object expected, Object notFound) {
    super("expecting:\n<%s>\n to contain:\n<%s>\n but could not find:\n<%s>", actual, expected, notFound);
  }

}


/*
 * Created on Mar 17, 2012
 *
 * 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 @2012 the original author or authors.
 */
package org.fest.assertions.error;

import org.fest.assertions.core.Matcher;

/**
 * Creates an error message indicating that an assertion that verifies elements of a group satisfies at most n times a
 * {@code Condition} A group of elements can be a collection, an array.

 *
 * @author Nicolas François
 * @author Mikhail Mazursky
 * @author Joel Costigliola
 */
public class ElementsShouldBeAtMost extends BasicErrorMessageFactory {

  /**
   * Creates a new {@link ElementsShouldBeAtMost}.
   * @param actual the actual value in the failed assertion.
   * @param times least time the condition should be verify.
   * @param condition the {@code Condition}.
   * @return the created {@code ErrorMessageFactory}.
   */
  public static ErrorMessageFactory elementsShouldBeAtMost(Object actual, int times, Matcher<?> condition) {
    return new ElementsShouldBeAtMost(actual, times, condition);
  }

  private ElementsShouldBeAtMost(Object actual, int times, Matcher<?> condition) {
    super("expecting elements:\n<%s>\n to be at most %s times <%s>", actual, times, condition);
  }
}


/*
 * Created on Mar 17, 2012
 *
 * 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 @2012 the original author or authors.
 */
package org.fest.assertions.error;

import org.fest.assertions.core.Matcher;

/**
 * Creates an error message indicating that an assertion that not verifies elements of a group satisfies at least n times a
 * {@code Condition} A group of elements can be a collection, an array.

 *
 * @author Nicolas François
 * @author Mikhail Mazursky
 * @author Joel Costigliola
 */
public class ElementsShouldNotHaveAtLeast extends BasicErrorMessageFactory {

  /**
   * Creates a new {@link ElementsShouldNotHaveAtLeast}.
   * @param actual the actual value in the failed assertion.
   * @param times least time the condition should be verify.
   * @param condition the {@code Condition}.
   * @return the created {@code ErrorMessageFactory}.
   */
  public static ErrorMessageFactory elementsShouldNotHaveAtLeast(Object actual, int times, Matcher<?> condition) {
    return new ElementsShouldNotHaveAtLeast(actual, times, condition);
  }

  private ElementsShouldNotHaveAtLeast(Object actual, int times, Matcher<?> condition) {
    super("expecting elements:\n<%s>\n not to have at least %s times <%s>", actual, times, condition);
  }
}


/*
 * Created on Oct 17, 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-2011 the original author or authors.
 */
package org.fest.assertions.error;

import static org.fest.assertions.util.ArrayWrapperList.wrap;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * Creates an error message indicating that an assertion that verifies a group of elements is sorted failed.

 * A group of elements can be a collection or an array.
 *
 * @author Joel Costigliola
 */
public class ShouldBeSorted extends BasicErrorMessageFactory {

  /**
   * Creates a new {@link ShouldBeSorted}.
   * @param i the index of elements whose not naturally ordered with the next.
   * @param group the actual group in the failed assertion (either collection or an array).
   * @return an instance of {@code ErrorMessageFactory}.
   */
  public static ErrorMessageFactory shouldBeSorted(int i, Object group) {
    List<?> groupAsList = groupAsList(group);
    return new ShouldBeSorted("group is not sorted because element %s:<%s> is not less or equal than element %s:<%s>.\n"
        + "group was:\n" + "<%s>", i, groupAsList.get(i), i + 1, groupAsList.get(i + 1), groupAsList);
  }

  public static ErrorMessageFactory shouldHaveMutuallyComparableElements(Object actual) {
    return new ShouldBeSorted("some elements are not mutually comparable in group:<%s>", actual);
  }

  private ShouldBeSorted(String format, Object... arguments) {
    super(format, arguments);
  }

  /**
   * Convert the given group (which is either an array or a Collection) to a List.
   * @param group the group to convert
   * @return the corresponding List
   * @throws IllegalArgumentException if group can't be converted to a List
   */
  @SuppressWarnings("unchecked")
  private static List<?> groupAsList(Object group) {
    if (group.getClass().isArray()) {
      return wrap(group);
    } else if (group instanceof Collection<?>) {
      List<Object> asList = new ArrayList<Object>();
      asList.addAll(((Collection<Object>) group));
      return asList;
    }
    throw new IllegalArgumentException("Parameter should be an array or a collection but was " + group);
  }

}


/*
 * Created on Nov 26, 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-2012 the original author or authors.
 */
package org.fest.assertions.util;

import java.lang.reflect.Array;
import java.util.AbstractList;

import org.fest.util.VisibleForTesting;

/**
 * A list-like wrapper for arrays. This class does not provide type-safety in order to handle both arrays of objects
 * and arrays of primitives.
 *
 * @author Alex Ruiz
 * @author Yvonne Wang
 */
public class ArrayWrapperList extends AbstractList<Object> {

  /**
   * Wraps a given array with a <code>{@link ArrayWrapperList}</code>
   *
   * @param array the array to wrap.
   * @return the wrapped array or {@code null} if the given array was already {@code null}.
   * @throws IllegalArgumentException if the {@code array} is not an array.
   */
  public static ArrayWrapperList wrap(Object array) {
    if (array == null) {
      return null;
    }
    if (!array.getClass().isArray()) {
      throw new IllegalArgumentException("The object to wrap should be an array");
    }
    return new ArrayWrapperList(array);
  }

  @VisibleForTesting
  final Object array;

  @VisibleForTesting
  ArrayWrapperList(Object array) {
    this.array = array;
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public Object get(int index) {
    checkIsInRange(index);
    return Array.get(array, index);
  }

  private void checkIsInRange(int index) {
    int size = size();
    if (index >= 0 && index < size()) {
      return;
    }
    String message = String.format("Index should be between 0 and %d (inclusive,) but was %d", size - 1, index);
    throw new IndexOutOfBoundsException(message);
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public int size() {
    return Array.getLength(array);
  }

  /**
   * Returns the component type of the wrapped array.
   *
   * @return the component type of the wrapped array.
   */
  public Class<?> getComponentType() {
    return array.getClass().getComponentType();
  }
}


/*
 * Created on Oct 25, 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.api;

import org.fest.assertions.core.FloatingPointNumberAssert;
import org.fest.assertions.data.Offset;
import org.fest.assertions.description.Description;
import org.fest.assertions.internal.Doubles;
import org.fest.util.VisibleForTesting;

/**
 * Assertion methods for doubles.
 * <p>
 * To create an instance of this class, invoke {@link Assertions#assertThat(Double)} or
 * {@link Assertions#assertThat(double)}.
 * </p>
 *
 * @author Yvonne Wang
 * @author David DIDIER
 * @author Alex Ruiz
 * @author Ansgar Konermann
 */
public class DoubleAssert extends AbstractComparableAssert<DoubleAssert, Double> implements
  FloatingPointNumberAssert<DoubleAssert, Double> {

  @VisibleForTesting
  Doubles doubles = Doubles.instance();

  protected DoubleAssert(Double actual) {
    super(actual, DoubleAssert.class);
  }

  protected DoubleAssert(Double actual, Description description) {
    super(actual, DoubleAssert.class, description);
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public DoubleAssert isNaN() {
    doubles.assertIsNaN(description, actual);
    return this;
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public DoubleAssert isNotNaN() {
    doubles.assertIsNotNaN(description, actual);
    return this;
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public DoubleAssert isEqualTo(Double expected, Offset<Double> offset) {
    doubles.assertEqual(description, actual, expected, offset);
    return this;
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public DoubleAssert isNotEqualTo(Double expected) {
    doubles.assertNotEqual(description, actual, expected);
    return this;
  }

  /**
   * Verifies that the actual value is equal to the given one.
   *
   * @param expected the given value to compare the actual value to.
   * @return {@code this} assertion object.
   * @throws AssertionError if the actual value is {@code null}.
   * @throws AssertionError if the actual value is not equal to the given one.
   */
  public DoubleAssert isEqualTo(double expected) {
    doubles.assertEqual(description, actual, expected);
    return this;
  }

  /**
   * Verifies that the actual value is equal to the given one, within a positive offset.
   *
   * @param expected the given value to compare the actual value to.
   * @param offset   the given positive offset.
   * @return {@code this} assertion object.
   * @throws NullPointerException if the given offset is {@code null}.
   * @throws AssertionError       if the actual value is {@code null}.
   * @throws AssertionError       if the actual value is not equal to the given one.
   */
  public DoubleAssert isEqualTo(double expected, Offset<Double> offset) {
    doubles.assertEqual(description, actual, expected, offset);
    return this;
  }

  /**
   * Verifies that the actual value is not equal to the given one.
   *
   * @param other the given value to compare the actual value to.
   * @return {@code this} assertion object.
   * @throws AssertionError if the actual value is {@code null}.
   * @throws AssertionError if the actual value is equal to the given one.
   */
  public DoubleAssert isNotEqualTo(double other) {
    doubles.assertNotEqual(description, actual, other);
    return this;
  }

  /**
   * Verifies that the actual value is less than the given one.
   *
   * @param other the given value to compare the actual value to.
   * @return {@code this} assertion object.
   * @throws AssertionError if the actual value is {@code null}.
   * @throws AssertionError if the actual value is equal to or greater than the given one.
   */
  public DoubleAssert isLessThan(double other) {
    doubles.assertLessThan(description, actual, other);
    return this;
  }

  /**
   * Verifies that the actual value is less than or equal to the given one.
   *
   * @param other the given value to compare the actual value to.
   * @return {@code this} assertion object.
   * @throws AssertionError if the actual value is {@code null}.
   * @throws AssertionError if the actual value is greater than the given one.
   */
  public DoubleAssert isNotGreaterThan(double other) {
    doubles.assertNotGreaterThan(description, actual, other);
    return this;
  }

  /**
   * Verifies that the actual value is greater than the given one.
   *
   * @param other the given value to compare the actual value to.
   * @return {@code this} assertion object.
   * @throws AssertionError if the actual value is {@code null}.
   * @throws AssertionError if the actual value is equal to or less than the given one.
   */
  public DoubleAssert isGreaterThan(double other) {
    doubles.assertGreaterThan(description, actual, other);
    return this;
  }

  /**
   * Verifies that the actual value is greater than or equal to the given one.
   *
   * @param other the given value to compare the actual value to.
   * @return {@code this} assertion object.
   * @throws AssertionError if the actual value is {@code null}.
   * @throws AssertionError if the actual value is less than the given one.
   */
  public DoubleAssert isNotLessThan(double other) {
    doubles.assertNotLessThan(description, actual, other);
    return this;
  }
}