Package ch.njol.skript.registrations

Source Code of ch.njol.skript.registrations.Comparators$ConvertedComparator

/*
*   This file is part of Skript.
*
*  Skript is free software: you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation, either version 3 of the License, or
*  (at your option) any later version.
*
*  Skript is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with Skript.  If not, see <http://www.gnu.org/licenses/>.
*
*
* Copyright 2011-2014 Peter Güttinger
*
*/

package ch.njol.skript.registrations;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import org.eclipse.jdt.annotation.Nullable;

import ch.njol.skript.Skript;
import ch.njol.skript.classes.Comparator;
import ch.njol.skript.classes.Comparator.ComparatorInfo;
import ch.njol.skript.classes.Comparator.Relation;
import ch.njol.skript.classes.Converter;
import ch.njol.skript.classes.InverseComparator;
import ch.njol.util.Pair;

/**
* @author Peter Güttinger
*/
public class Comparators {
 
  private Comparators() {}
 
  public final static Collection<ComparatorInfo<?, ?>> comparators = new ArrayList<ComparatorInfo<?, ?>>();
 
  /**
   * Registers a {@link Comparator}.
   *
   * @param t1
   * @param t2
   * @param c
   * @throws IllegalArgumentException if any given class is equal to <code>Object.class</code>
   */
  public static <T1, T2> void registerComparator(final Class<T1> t1, final Class<T2> t2, final Comparator<T1, T2> c) {
    Skript.checkAcceptRegistrations();
    if (t1 == Object.class && t2 == Object.class)
      throw new IllegalArgumentException("You must not add a comparator for Objects");
    comparators.add(new ComparatorInfo<T1, T2>(t1, t2, c));
  }
 
  @SuppressWarnings({"rawtypes", "unchecked"})
  public final static Relation compare(final @Nullable Object o1, final @Nullable Object o2) {
    if (o1 == null || o2 == null)
      return Relation.NOT_EQUAL;
    @SuppressWarnings("null")
    final Comparator c = getComparator(o1.getClass(), o2.getClass());
    if (c == null)
      return Relation.NOT_EQUAL;
    return c.compare(o1, o2);
  }
 
  private final static java.util.Comparator<Object> javaComparator = new java.util.Comparator<Object>() {
    @Override
    public int compare(final Object o1, final Object o2) {
      return Comparators.compare(o1, o2).getRelation();
    }
  };
 
  public final static java.util.Comparator<Object> getJavaComparator() {
    return javaComparator;
  }
 
  private final static Map<Pair<Class<?>, Class<?>>, Comparator<?, ?>> comparatorsQuickAccess = new HashMap<Pair<Class<?>, Class<?>>, Comparator<?, ?>>();
 
  @SuppressWarnings("unchecked")
  @Nullable
  public final static <F, S> Comparator<? super F, ? super S> getComparator(final Class<F> f, final Class<S> s) {
    final Pair<Class<?>, Class<?>> p = new Pair<Class<?>, Class<?>>(f, s);
    if (comparatorsQuickAccess.containsKey(p))
      return (Comparator<? super F, ? super S>) comparatorsQuickAccess.get(p);
    final Comparator<?, ?> comp = getComparator_i(f, s);
    comparatorsQuickAccess.put(p, comp);
    return (Comparator<? super F, ? super S>) comp;
  }
 
  @SuppressWarnings("unchecked")
  @Nullable
  private final static <F, S> Comparator<?, ?> getComparator_i(final Class<F> f, final Class<S> s) {
   
    // perfect match
    for (final ComparatorInfo<?, ?> info : comparators) {
      if (info.c1.isAssignableFrom(f) && info.c2.isAssignableFrom(s)) {
        return info.c;
      } else if (info.c1.isAssignableFrom(s) && info.c2.isAssignableFrom(f)) {
        return new InverseComparator<F, S>((Comparator<? super S, ? super F>) info.c);
      }
    }
   
    // same class but no comparator
    if (s == f && f != Object.class && s != Object.class) {
      return Comparator.equalsComparator;
    }
   
    final boolean[] trueFalse = {true, false};
    Converter<? super F, ?> c1;
    Converter<? super S, ?> c2;
   
    // single conversion
    for (final ComparatorInfo<?, ?> info : comparators) {
      for (final boolean first : trueFalse) {
        if (info.getType(first).isAssignableFrom(f)) {
          c2 = Converters.getConverter(s, info.getType(!first));
          if (c2 != null) {
            return first ? new ConvertedComparator<F, S>(info.c, c2) : new InverseComparator<F, S>(new ConvertedComparator<S, F>(c2, info.c));
          }
        }
        if (info.getType(first).isAssignableFrom(s)) {
          c1 = Converters.getConverter(f, info.getType(!first));
          if (c1 != null) {
            return !first ? new ConvertedComparator<F, S>(c1, info.c) : new InverseComparator<F, S>(new ConvertedComparator<S, F>(info.c, c1));
          }
        }
      }
    }
   
    // double conversion
    for (final ComparatorInfo<?, ?> info : comparators) {
      for (final boolean first : trueFalse) {
        c1 = Converters.getConverter(f, info.getType(first));
        c2 = Converters.getConverter(s, info.getType(!first));
        if (c1 != null && c2 != null) {
          return first ? new ConvertedComparator<F, S>(c1, info.c, c2) : new InverseComparator<F, S>(new ConvertedComparator<S, F>(c2, info.c, c1));
        }
      }
    }
   
    return null;
  }
 
  private final static class ConvertedComparator<T1, T2> implements Comparator<T1, T2> {
   
    @SuppressWarnings("rawtypes")
    private final Comparator c;
    @SuppressWarnings("rawtypes")
    @Nullable
    private final Converter c1, c2;
   
    public ConvertedComparator(final Converter<? super T1, ?> c1, final Comparator<?, ?> c) {
      this.c1 = c1;
      this.c = c;
      this.c2 = null;
    }
   
    public ConvertedComparator(final Comparator<?, ?> c, final Converter<? super T2, ?> c2) {
      this.c1 = null;
      this.c = c;
      this.c2 = c2;
    }
   
    public ConvertedComparator(final Converter<? super T1, ?> c1, final Comparator<?, ?> c, final Converter<? super T2, ?> c2) {
      this.c1 = c1;
      this.c = c;
      this.c2 = c2;
    }
   
    @SuppressWarnings({"rawtypes", "unchecked"})
    @Override
    public Relation compare(final T1 o1, final T2 o2) {
      final Converter c1 = this.c1;
      final Object t1 = c1 == null ? o1 : c1.convert(o1);
      if (t1 == null)
        return Relation.NOT_EQUAL;
      final Converter c2 = this.c2;
      final Object t2 = c2 == null ? o2 : c2.convert(o2);
      if (t2 == null)
        return Relation.NOT_EQUAL;
      return c.compare(t1, t2);
    }
   
    @Override
    public boolean supportsOrdering() {
      return c.supportsOrdering();
    }
   
    @Override
    public String toString() {
      return "ConvertedComparator(" + c1 + "," + c + "," + c2 + ")";
    }
   
  }
 
}
TOP

Related Classes of ch.njol.skript.registrations.Comparators$ConvertedComparator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.