import groovy.lang.Closure; import groovy.lang.GroovyObjectSupport; import org.springframework.ldap.filter.Filter; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.codehaus.groovy.runtime.DefaultGroovyMethods; import java.util.ArrayList; import java.util.List; import java.util.Stack; public class FilterBuilder extends GroovyObjectSupport { protected Stack> stack = new Stack>(); protected Filter result; private Log log = LogFactory.getLog(FilterBuilder.class); public FilterBuilder(Closure closure) { push("root"); call(closure); result = FilterUtil.and(pop("root")); } public void push(String debugLabel) { log.debug("Entering " + debugLabel); stack.push(new ArrayList()); } public List pop(String debugLabel) { log.debug("Leafing " + debugLabel); return stack.pop(); } public void call(Closure c) { c.setDelegate(this); c.call(); } private Integer add(Filter f) { log.debug("Adding Filter to current result: " + DefaultGroovyMethods.inspect(f)); stack.peek().add(f); return stack.peek().size() - 1; } public Object invokeMethod(String s, Object o) { if(o instanceof Object[]) { return invokeMethod(s, (Object[])o); } else if(o == null) { return invokeMethod(s, new Object[0]); } else { return invokeMethod(s, new Object[]{ o }); } } public Object invokeMethod(String name, Object[] args) { if(log.isDebugEnabled()) log.debug("["+hashCode()+"Invoked " + name + " (" + DefaultGroovyMethods.inspect(args) + ")"); if ("and".equals(name)) { if (args.length == 1 && args[0] instanceof Closure) { Closure c = (Closure) args[0]; push("and"); call(c); return add(FilterUtil.and(pop("and"))); } else { throw new IllegalArgumentException("FilterBuilder AND Call is invalid!"); } } else if ("or".equals(name)) { if (args.length == 1 && args[0] instanceof Closure) { Closure c = (Closure) args[0]; push("and"); call(c); return add(FilterUtil.or(pop("and"))); } else { throw new IllegalArgumentException("FilterBuilder OR Call is invalid!"); } } else if ("eq".equals(name)) { if (args.length == 2 && args[0] instanceof String && args[1] instanceof String) { return add(FilterUtil.eq((String) args[0], (String) args[1])); } else { throw new IllegalArgumentException("FilterBuilder EQ Call must have two arguments of type String"); } } else if ("like".equals(name)) { if (args.length == 2 && args[0] instanceof String && args[1] instanceof String) { return add(FilterUtil.like((String) args[0], (String) args[1])); } else { throw new IllegalArgumentException("FilterBuilder EQ Call must have two arguments of type String"); } } else if ("gte".equals(name)) { if (args.length == 2 && args[0] instanceof String && args[1] instanceof String) { return add(FilterUtil.gte((String) args[0], (String) args[1])); } else { throw new IllegalArgumentException("FilterBuilder EQ Call must have two arguments of type String"); } } else if ("lte".equals(name)) { if (args.length == 2 && args[0] instanceof String && args[1] instanceof String) { return add(FilterUtil.lte((String) args[0], (String) args[1])); } else { throw new IllegalArgumentException("FilterBuilder EQ Call must have two arguments of type String"); } } else if ("not".equals(name)) { if (args.length == 1 && args[0] instanceof Closure) { pop("not"); call((Closure) args[0]); return add(FilterUtil.not(FilterUtil.and(pop("not")))); } else if (args.length == 1 && args[0] instanceof Integer) { int idx = (Integer) args[0]; stack.peek().set(idx, FilterUtil.not(stack.peek().get(idx))); return idx; } else { throw new IllegalArgumentException("FilterBuilder NOT Call is invalid!"); } } else throw new IllegalAccessError("FilterBuilder invalid call: " + name); } public Filter getFilter() { return result; } }