alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (RelationshipTester.java)

This example Java source code file (RelationshipTester.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

assertionfailederror, equivalence, gwtcompatible, hash, immutablelist, item, itemreporter, other, override, relationshiptester, string, stringbuilder, util

The RelationshipTester.java Java example source code

/*
 * Copyright (C) 2011 The Guava Authors
 *
 * 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.
 */

package com.google.common.testing;

import static com.google.common.base.Preconditions.checkNotNull;

import com.google.common.annotations.GwtCompatible;
import com.google.common.base.Equivalence;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;

import junit.framework.AssertionFailedError;

import java.util.List;

/**
 * Implementation helper for {@link EqualsTester} and {@link EquivalenceTester} that tests for
 * equivalence classes.
 *
 * @author Gregory Kick
 */
@GwtCompatible
final class RelationshipTester<T> {

  static class ItemReporter {
    String reportItem(Item<?> item) {
      return item.toString();
    }
  }

  /**
   * A word about using {@link Equivalence}, which automatically checks for {@code null} and
   * identical inputs: This sounds like it ought to be a problem here, since the goals of this class
   * include testing that {@code equals()} is reflexive and is tolerant of {@code null}. However,
   * there's no problem. The reason: {@link EqualsTester} tests {@code null} and identical inputs
   * directly against {@code equals()} rather than through the {@code Equivalence}.
   */
  private final Equivalence<? super T> equivalence;
  private final String relationshipName;
  private final String hashName;
  private final ItemReporter itemReporter;
  private final List<ImmutableList groups = Lists.newArrayList();

  RelationshipTester(Equivalence<? super T> equivalence, String relationshipName, String hashName,
      ItemReporter itemReporter) {
    this.equivalence = checkNotNull(equivalence);
    this.relationshipName = checkNotNull(relationshipName);
    this.hashName = checkNotNull(hashName);
    this.itemReporter = checkNotNull(itemReporter);
  }

  // TODO(cpovirk): should we reject null items, since the tests already check null automatically?
  public RelationshipTester<T> addRelatedGroup(Iterable group) {
    groups.add(ImmutableList.copyOf(group));
    return this;
  }

  public void test() {
    for (int groupNumber = 0; groupNumber < groups.size(); groupNumber++) {
      ImmutableList<T> group = groups.get(groupNumber);
      for (int itemNumber = 0; itemNumber < group.size(); itemNumber++) {
        // check related items in same group
        for (int relatedItemNumber = 0; relatedItemNumber < group.size(); relatedItemNumber++) {
          if (itemNumber != relatedItemNumber) {
            assertRelated(groupNumber, itemNumber, relatedItemNumber);
          }
        }
        // check unrelated items in all other groups
        for (int unrelatedGroupNumber = 0; unrelatedGroupNumber < groups.size();
            unrelatedGroupNumber++) {
          if (groupNumber != unrelatedGroupNumber) {
            ImmutableList<T> unrelatedGroup = groups.get(unrelatedGroupNumber);
            for (int unrelatedItemNumber = 0; unrelatedItemNumber < unrelatedGroup.size();
                unrelatedItemNumber++) {
              assertUnrelated(groupNumber, itemNumber, unrelatedGroupNumber, unrelatedItemNumber);
            }
          }
        }
      }
    }
  }

  private void assertRelated(int groupNumber, int itemNumber, int relatedItemNumber) {
    Item<T> itemInfo = getItem(groupNumber, itemNumber);
    Item<T> relatedInfo = getItem(groupNumber, relatedItemNumber);

    T item = itemInfo.value;
    T related = relatedInfo.value;
    assertWithTemplate("$ITEM must be $RELATIONSHIP to $OTHER", itemInfo, relatedInfo,
        equivalence.equivalent(item, related));

    int itemHash = equivalence.hash(item);
    int relatedHash = equivalence.hash(related);
    assertWithTemplate("the $HASH (" + itemHash + ") of $ITEM must be equal to the $HASH ("
        + relatedHash + ") of $OTHER", itemInfo, relatedInfo, itemHash == relatedHash);
  }

  private void assertUnrelated(int groupNumber, int itemNumber, int unrelatedGroupNumber,
      int unrelatedItemNumber) {
    Item<T> itemInfo = getItem(groupNumber, itemNumber);
    Item<T> unrelatedInfo = getItem(unrelatedGroupNumber, unrelatedItemNumber);

    assertWithTemplate("$ITEM must not be $RELATIONSHIP to $OTHER", itemInfo, unrelatedInfo,
        !equivalence.equivalent(itemInfo.value, unrelatedInfo.value));
  }

  private void assertWithTemplate(String template, Item<T> item, Item other, boolean condition) {
    if (!condition) {
      throw new AssertionFailedError(template
          .replace("$RELATIONSHIP", relationshipName)
          .replace("$HASH", hashName)
          .replace("$ITEM", itemReporter.reportItem(item))
          .replace("$OTHER", itemReporter.reportItem(other)));
    }
  }

  private Item<T> getItem(int groupNumber, int itemNumber) {
    return new Item<T>(groups.get(groupNumber).get(itemNumber), groupNumber, itemNumber);
  }

  static final class Item<T> {
    final T value;
    final int groupNumber;
    final int itemNumber;

    Item(T value, int groupNumber, int itemNumber) {
      this.value = value;
      this.groupNumber = groupNumber;
      this.itemNumber = itemNumber;
    }

    @Override public String toString() {
      return new StringBuilder()
          .append(value)
          .append(" [group ")
          .append(groupNumber + 1)
          .append(", item ")
          .append(itemNumber + 1)
          .append(']')
          .toString();
    }
  }
}

Other Java examples (source code examples)

Here is a short list of links related to this Java RelationshipTester.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.