/* * Copyright (c) 2006-2011 Nuxeo SA (http://nuxeo.com/) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Georges Racinet * Florent Guillaume */ package org.eclipse.ecr.core.api.impl; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import org.eclipse.ecr.core.api.DocumentModel; import org.eclipse.ecr.core.api.Filter; /** * A filter based on facets. * * @author Georges Racinet * @author Florent Guillaume */ public class FacetFilter implements Filter { private static final long serialVersionUID = 1L; public static final FacetFilter ALLOW = new FacetFilter((List<String>) null, (List<String>) null); /** Set of required facets. Never {@code null}. */ public final Set<String> required; /** Set of excluded facets. Never {@code null}. */ public final Set<String> excluded; public final Boolean shortcut; /** * Generic constructor. * * @param required list of facets the models must have to pass the filter * @param excluded list of facets the models must not have to pass the * filter */ public FacetFilter(List<String> required, List<String> excluded) { if (required == null) { this.required = Collections.emptySet(); } else { this.required = new HashSet<String>(required); } if (excluded == null) { this.excluded = Collections.emptySet(); } else { this.excluded = new HashSet<String>(excluded); } shortcut = findShortcut(); } /** * Simpler constructor to filter on a single facet. * * @param facet the facet to filter on * @param isRequired if true, accepted models must have the facet; if false, * accepted models must not have the facet */ public FacetFilter(String facet, boolean isRequired) { if (isRequired) { required = Collections.singleton(facet); excluded = Collections.emptySet(); } else { required = Collections.emptySet(); excluded = Collections.singleton(facet); } shortcut = null; } /** * Constructor that ANDs two filters. * * @param filter1 the first filter * @param filter2 the second filter */ public FacetFilter(FacetFilter filter1, FacetFilter filter2) { if (filter1.required.isEmpty() && filter2.required.isEmpty()) { required = Collections.emptySet(); } else { required = new HashSet<String>(filter1.required); required.addAll(filter2.required); } if (filter1.excluded.isEmpty() && filter2.excluded.isEmpty()) { excluded = Collections.emptySet(); } else { excluded = new HashSet<String>(filter1.excluded); excluded.addAll(filter2.excluded); } shortcut = findShortcut(); } protected Boolean findShortcut() { if (required.isEmpty() && excluded.isEmpty()) { // no condition, always matches return Boolean.TRUE; } Collection<String> intersection = new HashSet<String>(required); intersection.retainAll(excluded); if (!intersection.isEmpty()) { // non-empty intersection, filter can never match return Boolean.FALSE; } return null; } @Override public boolean accept(DocumentModel docModel) { if (shortcut != null) { return shortcut; } for (String exc : excluded) { if (docModel.hasFacet(exc)) { return false; } } for (String req : required) { if (!docModel.hasFacet(req)) { return false; } } return true; } }