All Downloads are FREE. Search and download functionalities are using the official Maven repository.

xdean.jex.extra.RelativeComparator Maven / Gradle / Ivy

The newest version!
package xdean.jex.extra;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;

import com.google.common.annotations.Beta;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;

import xdean.jex.extra.collection.Tree;

/**
 *
 *
 * @author XDean
 *
 * @param 
 */
@Beta
public class RelativeComparator {
  public static > RelativeComparator create() {
    return new RelativeComparator(Comparator.naturalOrder());
  }

  public static  RelativeComparator create(Comparator defaultComparator) {
    return new RelativeComparator<>(defaultComparator);
  }

  @SafeVarargs
  public static > Comparator of(T... ts) {
    return new RelativeComparator(Comparator.naturalOrder()).addOrder(ts).toComparator();
  }

  @SafeVarargs
  public static  Comparator of(Comparator defaultComparator, T... ts) {
    return new RelativeComparator(defaultComparator).addOrder(ts).toComparator();
  }

  Comparator defaultComparator;
  Tree root;

  public RelativeComparator(Comparator defaultComparator) {
    this.defaultComparator = defaultComparator;
    this.root = new Tree<>(null);
  }

  @SuppressWarnings("unchecked")
  public RelativeComparator addOrder(T... ts) {
    for (int i = 0; i < ts.length - 1; i++) {
      addOrder(ts[i], ts[i + 1]);
    }
    return this;
  }

  public RelativeComparator addOrder(T small, T big) {
    Optional> oSmallNode = root.deepChild(small);
    Tree smallNode;
    if (oSmallNode.isPresent()) {
      smallNode = oSmallNode.get();
    } else {
      smallNode = root.add(small);
    }

    Optional> oBigNode = root.deepChild(big);
    if (oBigNode.isPresent()) {
      Tree bigNode = oBigNode.get();
      Tree commonParent = smallNode.commonParent(bigNode).get();
      if (commonParent == smallNode) {
        return this;
      } else if (commonParent == bigNode) {
        throw new IllegalArgumentException(String.format(
            "%s is already bigger than %s, can't setter it as the smaller.", small, big));
      } else if (commonParent == bigNode.getParent()) {
        smallNode.add(bigNode);
      } else if (commonParent == smallNode.getParent()) {
        throw new UnsupportedOperationException();
      } else {
        throw new UnsupportedOperationException();
      }
    } else {
      smallNode.add(big);
    }
    return this;
  }

  public Comparator toComparator() {
    return root.breadthFirstTraversal()
        .skip(1)
        .map(Tree::getValue)
        .toList()
        .> map(orderList -> {
          List target = new ArrayList<>(orderList);
          target.sort(defaultComparator);
          Builder builder = ImmutableMap.builder();
          for (int i = 0; i < orderList.size(); i++) {
            builder.put(orderList.get(i), target.get(i));
          }
          ImmutableMap map = builder.build();
          return (a, b) -> {
            int ia = orderList.indexOf(a);
            int ib = orderList.indexOf(b);
            if (ia != -1 && ib != -1) {
              return ia - ib;
            }
            return defaultComparator.compare(map.getOrDefault(a, a), map.getOrDefault(b, b));
          };
        })
        .blockingGet();
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy