/**
  * Assert that the given object is lenient equals by ignoring fields.
  *
  * @param info contains information about the assertion.
  * @param actual the given object.
  * @param other the object to compare {@code actual} to.
  * @param fields the fields to ignore in comparison
  * @throws NullPointerException if the actual type is {@code null}.
  * @throws NullPointerException if the other type is {@code null}.
  * @throws AssertionError if the actual and the given object are not lenient equals.
  * @throws AssertionError if the other object is not an instance of the actual type.
  */
 public <A> void assertIsLenientEqualsToByIgnoringFields(
     AssertionInfo info, A actual, A other, String... fields) {
   assertIsInstanceOf(info, other, actual.getClass());
   List<String> fieldsNames = new LinkedList<String>();
   List<Object> expectedValues = new LinkedList<Object>();
   Set<String> ignoredFields = set(fields);
   for (Field field : actual.getClass().getDeclaredFields()) {
     try {
       if (!ignoredFields.contains(field.getName())) {
         String fieldName = field.getName();
         Object actualFieldValue = propertySupport.propertyValue(fieldName, Object.class, actual);
         Object otherFieldValue = propertySupport.propertyValue(fieldName, Object.class, other);
         if (!org.fest.util.Objects.areEqual(actualFieldValue, otherFieldValue)) {
           fieldsNames.add(fieldName);
           expectedValues.add(otherFieldValue);
         }
       }
     } catch (IntrospectionError e) {
       // Not readeable field, skip.
     }
   }
   if (fieldsNames.isEmpty()) return;
   throw failures.failure(
       info, shouldBeLenientEqualByIgnoring(actual, fieldsNames, expectedValues, list(fields)));
 }
 /**
  * Assert that the given object is lenient equals by ignoring null fields value on other object.
  *
  * @param info contains information about the assertion.
  * @param actual the given object.
  * @param other the object to compare {@code actual} to.
  * @throws NullPointerException if the actual type is {@code null}.
  * @throws NullPointerException if the other type is {@code null}.
  * @throws AssertionError if the actual and the given object are not lenient equals.
  * @throws AssertionError if the other object is not an instance of the actual type.
  */
 public <A> void assertIsLenientEqualsToByIgnoringNullFields(
     AssertionInfo info, A actual, A other) {
   assertIsInstanceOf(info, other, actual.getClass());
   List<String> fieldsNames = new LinkedList<String>();
   List<Object> values = new LinkedList<Object>();
   List<String> nullFields = new LinkedList<String>();
   for (Field field : actual.getClass().getDeclaredFields()) {
     try {
       Object otherFieldValue =
           propertySupport.propertyValue(field.getName(), field.getType(), other);
       if (otherFieldValue != null) {
         Object actualFieldValue =
             propertySupport.propertyValue(field.getName(), field.getType(), actual);
         if (!otherFieldValue.equals(actualFieldValue)) {
           fieldsNames.add(field.getName());
           values.add(otherFieldValue);
         }
       } else {
         nullFields.add(field.getName());
       }
     } catch (IntrospectionError e) {
       // Not readeable field, skip.
     }
   }
   if (fieldsNames.isEmpty()) return;
   throw failures.failure(
       info, shouldBeLenientEqualByIgnoring(actual, fieldsNames, values, nullFields));
 }
 /**
  * Assert that the given object is lenient equals to other object by comparing given fields value
  * only.
  *
  * @param info contains information about the assertion.
  * @param actual the given object.
  * @param other the object to compare {@code actual} to.
  * @param fields accepted fields
  * @throws NullPointerException if the actual type is {@code null}.
  * @throws NullPointerException if the other type is {@code null}.
  * @throws AssertionError if the actual and the given object are not lenient equals.
  * @throws AssertionError if the other object is not an instance of the actual type.
  * @throws IntrospectionError if a field does not exist in actual.
  */
 public <A> void assertIsLenientEqualsToByAcceptingFields(
     AssertionInfo info, A actual, A other, String... fields) {
   assertIsInstanceOf(info, other, actual.getClass());
   List<String> rejectedFieldsNames = new LinkedList<String>();
   List<Object> expectedValues = new LinkedList<Object>();
   for (String fieldName : fields) {
     Object actualFieldValue = propertySupport.propertyValue(fieldName, Object.class, actual);
     Object otherFieldValue = propertySupport.propertyValue(fieldName, Object.class, other);
     if (!(actualFieldValue == otherFieldValue
         || (actualFieldValue != null && actualFieldValue.equals(otherFieldValue)))) {
       rejectedFieldsNames.add(fieldName);
       expectedValues.add(otherFieldValue);
     }
   }
   if (rejectedFieldsNames.isEmpty()) return;
   throw failures.failure(
       info,
       shouldBeLenientEqualByAccepting(actual, rejectedFieldsNames, expectedValues, list(fields)));
 }