package net.ion.craken.node.convert;
import java.io.Serializable;
import java.lang.reflect.Array;
import java.util.List;
import java.util.Set;
import net.ion.craken.expression.Expression;
import net.ion.craken.expression.ExpressionParser;
import net.ion.craken.expression.TerminalParser;
import net.ion.craken.node.NodeCommon;
import net.ion.craken.node.ReadNode;
import net.ion.craken.node.crud.tree.Fqn;
import net.ion.craken.node.crud.tree.impl.PropertyId;
import net.ion.framework.util.ArrayUtil;
import net.ion.framework.util.ListUtil;
import net.ion.framework.util.ObjectUtil;
import net.ion.rosetta.Parser;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
public class Predicates {
public final static Predicate<PropertyId> onlyNormal(){
return onlyPropertyType(PropertyId.PType.NORMAL) ;
}
public final static Predicate<PropertyId> onlyPropertyType(final PropertyId.PType ptype){
return new Predicate<PropertyId>(){
@Override
public boolean apply(PropertyId pid) {
return pid.type() == ptype;
}
} ;
}
// Comparison
public final static <T extends NodeCommon> Predicate<T> hasRelation(final String refName, final Fqn target) {
return new Predicate<T>() {
@Override
public boolean apply(T node) {
return node.hasRef(refName, target);
}
};
}
public final static <T extends NodeCommon> Predicate<T> equalValue(final String propId, final Object value) {
return new Predicate<T>() {
@Override
public boolean apply(T node) {
if (node.property(propId).value() == null || value == null) return false ;
return value.equals(node.property(propId).value());
}
};
}
public final static <T extends NodeCommon> Predicate<T> anyValue(final String propId, final Object value) {
return new Predicate<T>() {
@Override
public boolean apply(T node) {
if (node.property(propId).value() == null || value == null) return false ;
return ArrayUtil.contains(node.property(propId).asSet().toArray(), value);
}
};
}
public final static <T extends NodeCommon> Predicate<T> inValue(final String propId, final Object... values) {
return new Predicate<T>() {
@Override
public boolean apply(T node) {
if (node.property(propId).value() == null || values == null) return false ;
return ArrayUtil.contains(values, node.property(propId).value());
}
};
}
public static <T extends NodeCommon> Predicate<T> containsValue(final String propId, final String value) {
return new Predicate<T>() {
@Override
public boolean apply(T node) {
if (node.property(propId).value() == null || value == null) return false ;
for(Object eleValue : node.property(propId).asSet()){
if (ObjectUtil.toString(eleValue).contains(value)) return true ;
}
return false;
}
};
}
public static <T extends NodeCommon> Predicate<T> allValue(final String propId, final Object value) {
return new Predicate<T>() {
@Override
public boolean apply(T node) {
if (node.property(propId).value() == null || value == null) return false ;
if (value.getClass().isArray()){
Set saved = node.property(propId).asSet();
int size = Array.getLength(value);
int ii = 0 ;
for (Object object : saved) {
if (! ObjectUtil.equals(object, Array.get(value, ii++))){
return false ;
}
}
return saved.size() == size ;
} else {
return ArrayUtil.isEquals(node.property(propId).asSet().toArray(), value) ;
}
}
} ;
}
public static <T extends NodeCommon> Predicate<T> gtValue(final String propId, final Object value) {
return new Predicate<T>() {
@Override
public boolean apply(T node) {
if (node.property(propId).value() == null || value == null) return false ;
return ((Comparable)node.property(propId).value()).compareTo(value) > 0 ;
}
} ;
}
public static <T extends NodeCommon> Predicate<T> gteValue(final String propId, final Object value) {
return new Predicate<T>() {
@Override
public boolean apply(T node) {
if (node.property(propId).value() == null || value == null) return false ;
return ((Comparable)node.property(propId).value()).compareTo(value) >= 0 ;
}
} ;
}
public static <T extends NodeCommon> Predicate<T> ltValue(final String propId, final Object value) {
return new Predicate<T>() {
@Override
public boolean apply(T node) {
if (node.property(propId).value() == null || value == null) return false ;
return ((Comparable)node.property(propId).value()).compareTo(value) < 0 ;
}
} ;
}
public static <T extends NodeCommon> Predicate<T> lteValue(final String propId, final Object value) {
return new Predicate<T>() {
@Override
public boolean apply(T node) {
if (node.property(propId).value() == null || value == null) return false ;
return ((Comparable)node.property(propId).value()).compareTo(value) <= 0 ;
}
} ;
}
public static <T extends NodeCommon> Predicate<T> neValue(final String propId, final Object value) {
return new Predicate<T>() {
@Override
public boolean apply(T node) {
if (node.property(propId).value() == null || value == null) return false ;
return ! value.equals(node.property(propId).value());
}
};
}
public static <T extends NodeCommon> Predicate<T> notAllValue(final String propId, final Object value) {
return new Predicate<T>() {
@Override
public boolean apply(T node) {
if (node.property(propId).value() == null || value == null) return false ;
return ! ArrayUtil.contains(node.property(propId).asSet().toArray(), value);
}
};
}
public static <T extends NodeCommon> Predicate<T> startsWith(final String propId, final String value) {
return new Predicate<T>() {
@Override
public boolean apply(T node) {
if (node.property(propId).value() == null || value == null) return false ;
return node.property(propId).asString().startsWith(value) ;
}
};
}
public static <T extends NodeCommon> Predicate<T> endsWith(final String propId, final String value) {
return new Predicate<T>() {
@Override
public boolean apply(T node) {
if (node.property(propId).value() == null || value == null) return false ;
return node.property(propId).asString().endsWith(value) ;
}
};
}
// Element
public static <T extends NodeCommon> Predicate<T> exists(final String propId) {
return new Predicate<T>() {
@Override
public boolean apply(T node) {
return node.hasPropertyId(PropertyId.normal(propId)) ;
}
} ;
}
public static <T extends NodeCommon> Predicate<T> type(final String propId, final Class clz) {
return new Predicate<T>() {
@Override
public boolean apply(T node) {
if (node.property(propId).value() == null ) return false ;
return clz.isInstance(node.property(propId).value()) ;
}
} ;
}
public static <T extends NodeCommon> Predicate<T> size(final String propId, final int size) {
return new Predicate<T>() {
@Override
public boolean apply(T node) {
return node.property(propId).asSet().size() == size ;
}
} ;
}
public static <T extends NodeCommon> Predicate<T> where(String expression) {
Parser<Expression> parser = ExpressionParser.expression();
final Expression result = TerminalParser.parse(parser, expression);
return new Predicate<T>(){
@Override
public boolean apply(T node) {
return Boolean.TRUE.equals(result.value(node));
}
} ;
}
// Logical
public final static <T extends NodeCommon> Predicate<T> and(Predicate<T>... components) {
return new AndPredicate(ListUtil.toList(components)) ;
}
public final static <T extends NodeCommon> Predicate<T> or(Predicate<T>... components) {
return new OrPredicate(ListUtil.toList(components)) ;
}
public final static <T extends NodeCommon> Predicate<T> nor(final Predicate<T> left, final Predicate<T> right) {
return new Predicate<T>() {
@Override
public boolean apply(T node) {
return left.apply(node) ^ right.apply(node) ;
}
} ;
}
public final static <T extends NodeCommon> Predicate<T> not(final Predicate<T> component) {
return new Predicate<T>() {
@Override
public boolean apply(T node) {
return ! component.apply(node) ;
}
} ;
}
private static class OrPredicate<T> implements Predicate<T>, Serializable {
private final List<Predicate> components;
private static final long serialVersionUID = 0L;
private OrPredicate(List<Predicate> components) {
this.components = components;
}
public boolean apply(Object t) {
for (int i = 0; i < components.size(); i++)
if (((Predicate) components.get(i)).apply(t))
return true;
return false;
}
public int hashCode() {
return components.hashCode() + 87855567;
}
public boolean equals(Object obj) {
if (obj instanceof OrPredicate) {
OrPredicate that = (OrPredicate) obj;
return components.equals(that.components);
} else {
return false;
}
}
}
private static class AndPredicate<T> implements Predicate<T>, Serializable {
private final List<Predicate> components;
private static final long serialVersionUID = 0L;
private AndPredicate(List<Predicate> components) {
this.components = components;
}
public boolean apply(Object t) {
for (int i = 0; i < components.size(); i++)
if (!((Predicate) components.get(i)).apply(t))
return false;
return true;
}
public int hashCode() {
return components.hashCode() + 306654252;
}
public boolean equals(Object obj) {
if (obj instanceof AndPredicate) {
AndPredicate that = (AndPredicate) obj;
return components.equals(that.components);
} else {
return false;
}
}
}
private static class NotPredicate<T> implements Predicate<T>, Serializable {
final Predicate predicate;
private static final long serialVersionUID = 0L;
NotPredicate(Predicate predicate) {
this.predicate = (Predicate) Preconditions.checkNotNull(predicate);
}
public boolean apply(Object t) {
return !predicate.apply(t);
}
public int hashCode() {
return ~predicate.hashCode();
}
public boolean equals(Object obj) {
if (obj instanceof NotPredicate) {
NotPredicate that = (NotPredicate) obj;
return predicate.equals(that.predicate);
} else {
return false;
}
}
public String toString() {
return (new StringBuilder()).append("Not(").append(predicate.toString()).append(")").toString();
}
}
public static Predicate<ReadNode> and(List<Predicate<ReadNode>> filters) {
return com.google.common.base.Predicates.and(filters);
}
}