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

com.netflix.infix.NumericValuePredicate Maven / Gradle / Ivy

package com.netflix.infix;

import com.google.common.base.Preconditions;
import com.google.common.collect.Maps;
import com.google.common.primitives.Doubles;

import java.util.Map;
import java.util.Set;

public class NumericValuePredicate implements ValuePredicate {

	private Number value;
	private Operator op;

	public NumericValuePredicate(Number value, String fnName) {
		
		Preconditions.checkNotNull(value, "A null number doesn't make sense. ");

		this.value = value;
		this.op = Operator.lookup(fnName);
	}

	public Number getValue() {
		return value;
	}
	
	public String getOpName () {
		return this.op.getOpName();
	}
	
	@Override
	public boolean apply(Number input) {
		Preconditions.checkNotNull(input, "A null number doesn't make sense.");
		return op.compare(input, value);
	}

	private static enum Operator {
		GREATER_THAN(">") {
			@Override
			public boolean compare(Number left, Number right) {
				return doComparison(left, right) > 0;
			}
		},
		GREATER_THAN_OR_EQUAL(">=") {
			@Override
			public boolean compare(Number left, Number right) {
				return doComparison(left, right) >= 0;
			}
		},
		LESS_THAN("<") {
			@Override
			public boolean compare(Number left, Number right) {
				return doComparison(left, right) < 0;
			}
		},
		LESS_THAN_OR_EQUAL("<=") {
			@Override
			public boolean compare(Number left, Number right) {
				return doComparison(left, right) <= 0;
			}
		},
		EQUAL("=") {
			@Override
			public boolean compare(Number left, Number right) {
				return doComparison(left, right) == 0;
			}
		},
		NOT_EQUAL("!=") {
			@Override
			public boolean compare(Number left, Number right) {
				return doComparison(left, right) != 0;
			}
		}
		;
		
		private String name;

		private Operator(String name) {
			this.name = name;
		}

		public String getOpName() {
			return this.name;
		}

		public static Operator lookup(String opName) {
			Operator op = LOOKUP_TABLE.get(opName);
			
			if(op == null){
				throw new IllegalArgumentException(
					String.format("The operator '%s' is not supported. Supported operations: %s", 
							opName,
							getOperatorNames()
					));
			}
			
			return op;
		}
		
		public static Set getOperatorNames() {
			return LOOKUP_TABLE.keySet();
		}
		
		private static int doComparison(Number a, Number b) {
			return Doubles.compare(a.doubleValue(), b.doubleValue());
		}

		public abstract boolean compare(Number left, Number right);

		// According to JSR-133's FAQ (http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#finalRight), 
		// " In addition, the visible values for any other object or array referenced by those final 
		// fields will be at least as up-to-date as the final fields.". Therefore, no need to use sync'd map
		// here as this lookup table will be read-only. 
		private static final Map LOOKUP_TABLE = Maps.newHashMap();
		static {
			for (Operator op : Operator.values()) {
				LOOKUP_TABLE.put(op.getOpName(), op);
			}
		}
	}

	@Override
    public String toString() {
	    StringBuilder builder = new StringBuilder();
	    builder.append("NumericValuePredicate [value=");
	    builder.append(value);
	    builder.append(", op=");
	    builder.append(op);
	    builder.append("]");
	    return builder.toString();
    }

	@Override
    public int hashCode() {
	    final int prime = 31;
	    int result = 1;
	    result = prime * result + ((op == null) ? 0 : op.hashCode());
	    result = prime * result + ((value == null) ? 0 : value.hashCode());
	    return result;
    }

	@Override
    public boolean equals(Object obj) {
	    if (this == obj) {
		    return true;
	    }
	    if (obj == null) {
		    return false;
	    }
	    if (getClass() != obj.getClass()) {
		    return false;
	    }
	    NumericValuePredicate other = (NumericValuePredicate) obj;
	    if (op != other.op) {
		    return false;
	    }
	    if (value == null) {
		    if (other.value != null) {
			    return false;
		    }
	    } else if (!value.equals(other.value)) {
		    return false;
	    }
	    return true;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy