package com.breeze.query; import java.util.ArrayList; import java.util.List; import java.util.Map; import com.breeze.metadata.IEntityType; import com.breeze.util.TypeFns; /** * Represents a single where clause. * @author IdeaBlade * */ public abstract class Predicate { public static List<Predicate> predicatesFromMap(Map map) { List<Predicate> preds = new ArrayList<Predicate>(); for (Object key : map.keySet()) { String skey = (String) key; Predicate pred =predicateFromKeyValue(skey, map.get(skey)); preds.add(pred); } return preds; } public static Predicate predicateFromMap(Map sourceMap) { if (sourceMap == null) return null; List<Predicate> preds = predicatesFromMap(sourceMap); return createCompoundPredicate(preds); } public abstract Operator getOperator(); public abstract void validate(IEntityType entityType); private static Predicate predicateFromKeyValue(String key, Object value) { Operator op = Operator.fromString(key); if (op != null) { if (op.getType() == OperatorType.AndOr) { List<Predicate> preds = predicatesFromObject(value); return new AndOrPredicate(op, preds); } else if (op.getType() == OperatorType.Unary) { Predicate pred = predicateFromObject(value); return new UnaryPredicate(op, pred); } else { throw new RuntimeException("Invalid operator in context: " + key); } } if (value == null || TypeFns.isPrimitiveOrString(value)) { return new BinaryPredicate(BinaryOperator.Equals, key, value); } else if (value instanceof Map && ((Map) value).containsKey("value")) { return new BinaryPredicate(BinaryOperator.Equals, key, value); } if (!(value instanceof Map)) { throw new RuntimeException("Unable to resolve value associated with key:" + key); } List<Predicate> preds = new ArrayList<Predicate>(); Map map = (Map) value; for (Object oKey : map.keySet()) { String subKey = (String) oKey; Operator subOp = Operator.fromString(subKey); Object subVal = map.get(subKey); Predicate pred; if (subOp != null) { if (subOp.getType() == OperatorType.AnyAll) { Predicate subPred = predicateFromObject(subVal); pred = new AnyAllPredicate(subOp, key, subPred); } else if (subOp.getType() == OperatorType.Binary) { pred = new BinaryPredicate(subOp, key, subVal); } else { throw new RuntimeException("Unable to resolve OperatorType for key: " + subKey); } } else if (subVal instanceof Map && ((Map) subVal).get("value") != null) { pred = new BinaryPredicate(BinaryOperator.Equals, key, subVal ); } else { throw new RuntimeException("Unable to resolve predicate after: " + key); } preds.add(pred); } return createCompoundPredicate(preds); } private static Predicate predicateFromObject(Object source) { List<Predicate> preds = predicatesFromObject(source); return createCompoundPredicate(preds); // if (preds.size() > 1) { // throw new RuntimeException("predicateFromObject: should only contain a single item"); // } else { // return preds.get(0); // } } private static List<Predicate> predicatesFromObject(Object source) { List<Predicate> preds = new ArrayList<Predicate>(); if (source instanceof Map) { preds = predicatesFromMap((Map) source); } else if (source instanceof List) { for (Object item: (List) source) { Predicate pred = predicateFromObject(item); preds.add(pred); } } return preds; } private static Predicate createCompoundPredicate(List<Predicate> preds) { if (preds.size() > 1) { return new AndOrPredicate(Operator.And, preds); } else { return preds.get(0); } } }