package fr.openwide.core.wicket.more.util.visit; import java.io.Serializable; import java.util.Arrays; import java.util.List; import org.apache.wicket.Component; import org.apache.wicket.util.visit.IVisitFilter; import com.google.common.base.Predicate; import com.google.common.base.Predicates; import com.google.common.collect.Lists; public class VisitFilters { private VisitFilters() { } private static final class TypeSafePredicate<T> implements Predicate<Object>, Serializable { private static final long serialVersionUID = 1L; private final Class<T> clazz; private final Predicate<? super T> delegate; public TypeSafePredicate(Class<T> clazz, Predicate<? super T> delegate) { super(); this.clazz = clazz; this.delegate = delegate; } @Override @SuppressWarnings("unchecked") public boolean apply(Object input) { return clazz.isInstance(input) && delegate.apply((T)input); } } private static final class PredicateVisitFilter implements IVisitFilter, Serializable { private static final long serialVersionUID = 1L; private final Predicate<Object> objectVisitPredicate; private final Predicate<Object> compositeVisitPredicate; public PredicateVisitFilter(Predicate<Object> objectVisitPredicate, Predicate<Object> compositeVisitPredicate) { super(); this.objectVisitPredicate = objectVisitPredicate; this.compositeVisitPredicate = compositeVisitPredicate; } @Override public final boolean visitObject(Object object) { return objectVisitPredicate.apply(object); } @Override public final boolean visitChildren(Object object) { return compositeVisitPredicate.apply(object); } } public static <T> IVisitFilter downToExcluding(Class<T> clazz, Predicate<? super T> predicate) { Predicate<Object> objectPredicate = Predicates.not(new TypeSafePredicate<>(clazz, predicate)); return new PredicateVisitFilter(objectPredicate, objectPredicate); } public static <T> IVisitFilter including(Class<T> clazz, Predicate<? super T> predicate) { Predicate<Object> objectPredicate = new TypeSafePredicate<>(clazz, predicate); return new PredicateVisitFilter(objectPredicate, Predicates.alwaysTrue()); } public static <T> IVisitFilter excluding(Class<T> clazz, Predicate<? super T> predicate) { Predicate<Object> objectPredicate = Predicates.not(new TypeSafePredicate<>(clazz, predicate)); return new PredicateVisitFilter(objectPredicate, Predicates.alwaysTrue()); } public static <T> IVisitFilter downToIncluding(Class<T> clazz, Predicate<? super T> predicate) { Predicate<Object> objectPredicate = Predicates.not(new TypeSafePredicate<>(clazz, predicate)); return new PredicateVisitFilter(Predicates.alwaysTrue(), objectPredicate); } public static IVisitFilter downToExcluding(Class<?> clazz) { return downToExcluding(clazz, Predicates.alwaysTrue()); } public static IVisitFilter including(Class<?> clazz) { return including(clazz, Predicates.alwaysTrue()); } public static <T> IVisitFilter excluding(Class<?> clazz) { return excluding(clazz, Predicates.alwaysTrue()); } public static IVisitFilter downToIncluding(Class<?> clazz) { return downToIncluding(clazz, Predicates.alwaysTrue()); } public static IVisitFilter including(Class<?> first, Class<?> ... others) { List<IVisitFilter> filters = Lists.newArrayList(); for (Class<?> clazz : Lists.asList(first, others)) { filters.add(including(clazz)); } return any(filters); } public static IVisitFilter downToExcluding(Object object) { return downToExcluding(Object.class, Predicates.equalTo(object)); } public static IVisitFilter excluding(Object object) { return excluding(Object.class, Predicates.equalTo(object)); } public static IVisitFilter downToIncluding(Object object) { return downToIncluding(Object.class, Predicates.equalTo(object)); } public static IVisitFilter every(IVisitFilter ... operands) { return new EveryVisitFilter(Arrays.asList(operands)); } public static IVisitFilter every(Iterable<? extends IVisitFilter> operands) { return new EveryVisitFilter(operands); } private static final class EveryVisitFilter implements IVisitFilter, Serializable { private static final long serialVersionUID = 1L; private final Iterable<? extends IVisitFilter> operands; public EveryVisitFilter(Iterable<? extends IVisitFilter> operands) { super(); this.operands = operands; } @Override public boolean visitObject(Object object) { for (IVisitFilter filter : operands) { if (!filter.visitObject(object)) { return false; } } return true; } @Override public boolean visitChildren(Object object) { for (IVisitFilter filter : operands) { if (!filter.visitChildren(object)) { return false; } } return true; } } public static IVisitFilter any(IVisitFilter ... operands) { return new AnyVisitFilter(Arrays.asList(operands)); } public static IVisitFilter any(Iterable<? extends IVisitFilter> operands) { return new AnyVisitFilter(operands); } private static final class AnyVisitFilter implements IVisitFilter, Serializable { private static final long serialVersionUID = 1L; private final Iterable<? extends IVisitFilter> operands; public AnyVisitFilter(Iterable<? extends IVisitFilter> operands) { super(); this.operands = operands; } @Override public boolean visitObject(Object object) { for (IVisitFilter filter : operands) { if (filter.visitObject(object)) { return true; } } return false; } @Override public boolean visitChildren(Object object) { for (IVisitFilter filter : operands) { if (filter.visitChildren(object)) { return true; } } return false; } } public static IVisitFilter renderedComponents() { return RenderedComponentsVisitFilter.INSTANCE; } private enum RenderedComponentsVisitFilter implements IVisitFilter { INSTANCE; @Override public boolean visitObject(Object object) { return hasRenderedMarkup(object); } private boolean hasRenderedMarkup(Object object) { if (!(object instanceof Component)) { return false; } Component component = (Component) object; if (!component.hasBeenRendered() && !component.getOutputMarkupPlaceholderTag()) { return false; } Component parent = component.getParent(); return component.isVisibleInHierarchy() || (parent == null || parent.isVisibleInHierarchy()) && component.getOutputMarkupPlaceholderTag(); } @Override public boolean visitChildren(Object object) { return hasRenderedMarkup(object); } } }