/*
* 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.classes;
import ch.njol.skript.classes.data.DefaultComparators;
import ch.njol.skript.registrations.Comparators;
/**
* Used to compare two objects of a different or the same type.
*
* @author Peter Güttinger
* @param <T1> ,
* @param <T2> the types to compare
* @see Comparators#registerComparator(Class, Class, Comparator)
* @see DefaultComparators
*/
public interface Comparator<T1, T2> {
/**
* represents a relation between two objects.
*/
public static enum Relation {
EQUAL, NOT_EQUAL, GREATER, GREATER_OR_EQUAL, SMALLER, SMALLER_OR_EQUAL;
/**
* Returns EQUAL for true or NOT_EQUAL for false
*
* @param b
* @return <tt>b ? Relation.EQUAL : Relation.NOT_EQUAL</tt>
*/
public static Relation get(final boolean b) {
return b ? Relation.EQUAL : Relation.NOT_EQUAL;
}
/**
* Gets a Relation from a difference: If i is 0, EQUAL is returned, if i is greater than 0, GREATER is returned, otherwise SMALLER.
*
* @param i
* @return <tt>i == 0 ? Relation.EQUAL : i > 0 ? Relation.GREATER : Relation.SMALLER</tt>
*/
public static Relation get(final int i) {
return i == 0 ? Relation.EQUAL : i > 0 ? Relation.GREATER : Relation.SMALLER;
}
/**
* Gets a Relation from a difference: If d is 0, EQUAL is returned, if d is greater than 0, GREATER is returned, otherwise SMALLER.
*
* @param d
* @return <tt>d == 0 ? Relation.EQUAL : d > 0 ? Relation.GREATER : Relation.SMALLER</tt>
*/
public static Relation get(final double d) {
return d == 0 ? Relation.EQUAL : d > 0 ? Relation.GREATER : Relation.SMALLER;
}
/**
* Test whether this relation is fulfilled if another is, i.e. if the parameter relation fulfils <code>X rel Y</code>, then this relation fulfils <code>X rel Y</code> as
* well.
*
* @param other
* @return Whether this relation is part of the given relation, e.g. <code>GREATER_OR_EQUAL.is(EQUAL)</code> returns true.
*/
public boolean is(final Relation other) {
if (other == this)
return true;
switch (this) {
case EQUAL:
return false;
case NOT_EQUAL:
return other == SMALLER || other == GREATER;
case GREATER:
return false;
case GREATER_OR_EQUAL:
return other == GREATER || other == EQUAL;
case SMALLER:
return false;
case SMALLER_OR_EQUAL:
return other == SMALLER || other == EQUAL;
}
assert false;
return false;
}
/**
* Returns this relation's string representation, which is similar to "equal to" or "greater than".
*/
@Override
public String toString() {
switch (this) {
case EQUAL:
return "equal to";
case NOT_EQUAL:
return "not equal to";
case GREATER:
return "greater than";
case GREATER_OR_EQUAL:
return "greater than or equal to";
case SMALLER:
return "smaller than";
case SMALLER_OR_EQUAL:
return "smaller than or equal to";
}
assert false;
return "";
}
/**
* Gets the inverse of this relation, i.e if this relation fulfils <code>X rel Y</code>, then the returned relation fulfils <code>!(X rel Y)</code>.
*
* @return !this
*/
public Relation getInverse() {
switch (this) {
case EQUAL:
return NOT_EQUAL;
case NOT_EQUAL:
return EQUAL;
case GREATER:
return SMALLER_OR_EQUAL;
case GREATER_OR_EQUAL:
return SMALLER;
case SMALLER:
return GREATER_OR_EQUAL;
case SMALLER_OR_EQUAL:
return GREATER;
}
assert false;
return NOT_EQUAL;
}
/**
* Gets the relation which has switched arguments, i.e. if this relation fulfils <code>X rel Y</code>, then the returned relation fulfils <code>Y rel X</code>.
*
* @return siht
*/
public Relation getSwitched() {
switch (this) {
case EQUAL:
return EQUAL;
case NOT_EQUAL:
return NOT_EQUAL;
case GREATER:
return SMALLER;
case GREATER_OR_EQUAL:
return SMALLER_OR_EQUAL;
case SMALLER:
return GREATER;
case SMALLER_OR_EQUAL:
return GREATER_OR_EQUAL;
}
assert false;
return NOT_EQUAL;
}
public boolean isEqualOrInverse() {
return this == Relation.EQUAL || this == Relation.NOT_EQUAL;
}
public int getRelation() {
switch (this) {
case EQUAL:
case NOT_EQUAL:
return 0;
case GREATER:
case GREATER_OR_EQUAL:
return 1;
case SMALLER:
case SMALLER_OR_EQUAL:
return -1;
}
assert false;
return 0;
}
}
/**
* holds information about a comparator.
*
* @param <T1> see {@link Comparator}
* @param <T2> dito
*/
public static class ComparatorInfo<T1, T2> {
public Class<T1> c1;
public Class<T2> c2;
public Comparator<T1, T2> c;
public ComparatorInfo(final Class<T1> c1, final Class<T2> c2, final Comparator<T1, T2> c) {
this.c1 = c1;
this.c2 = c2;
this.c = c;
}
public Class<?> getType(final boolean first) {
return first ? c1 : c2;
}
}
Comparator<?, ?> equalsComparator = new Comparator<Object, Object>() {
@Override
public Relation compare(final Object o1, final Object o2) {
return Relation.get(o1.equals(o2));
}
@Override
public boolean supportsOrdering() {
return false;
}
};
/**
* Compares the given objects which may not be null. Returning GREATER/SMALLER means that the first parameter is greater/smaller.
*
* @param o1 Non-null object
* @param o2 Non-null object
* @return the relation of the objects. Should neither return GREATER_OR_EQUAL nor SMALLER_OR_EQUAL.
*/
public Relation compare(T1 o1, T2 o2);
/**
* @return whether this comparator supports ordering of elements or not.
*/
public boolean supportsOrdering();
}