/** * Copyright (C) 2010 eXo Platform SAS. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.xcmis.spi; import org.xcmis.spi.model.Rendition; import org.xcmis.spi.utils.MimeType; import java.util.Collections; import java.util.HashSet; import java.util.Set; import java.util.regex.Pattern; /** * @author <a href="mailto:andrey.parfonov@exoplatform.com">Andrey Parfonov</a> * @version $Id: RenditionFilter.java 265 2010-03-04 11:10:52Z andrew00x $ */ public class RenditionFilter { /** None filter to include all renditions. */ public static final String ANY = CmisConstants.WILDCARD; /** None filter to exclude all renditions. */ public static final String NONE = "cmis:none"; /** None filter to accept only renditions with 'cmis:thumbnail' kind. */ public static final String THUMBNAIL = "cmis:thumbnail"; /** Filter instance with 'cmis:thumbnail' kind. */ public static final RenditionFilter THUMBNAIL_FILTER; /** Filter instance with all renditions included. */ public static final RenditionFilter ANY_FILTER; /** Filter instance with none renditions included. */ public static final RenditionFilter NONE_FILTER; static { THUMBNAIL_FILTER = new RenditionFilter(); Set<String> tmp = new HashSet<String>(); tmp.add(THUMBNAIL); THUMBNAIL_FILTER.kinds = Collections.unmodifiableSet(tmp); THUMBNAIL_FILTER.mediaTypes = Collections.emptySet(); ANY_FILTER = new RenditionFilter(); ANY_FILTER.anyRenditions = true; NONE_FILTER = new RenditionFilter(); NONE_FILTER.kinds = Collections.emptySet(); NONE_FILTER.mediaTypes = Collections.emptySet(); } /** Pattern for parsing source filter string. */ private static final Pattern SPLITTER = Pattern.compile("\\s*,\\s*"); /** Whether any renditions. */ private boolean anyRenditions = false; /** Kinds. */ private Set<String> kinds; /** Media types. */ private Set<MimeType> mediaTypes; /** * Construct new Rendition Filter. * * @param filterString string that contains either '*' or comma-separated * list of rendition's kind or mime-types. An arbitrary number of * space allowed before and after each comma. Each token will be * interpreted as rendition mime-type if it has form 'type/sub-type' * otherwise it will be interpreted as kind. * @throws FilterNotValidException if <code>filterString</code> is invalid */ public RenditionFilter(String filterString) throws FilterNotValidException { if (filterString == null || filterString.length() == 0 || NONE.equals(filterString.trim())) { // Filter will exclude all associated renditions. this.kinds = Collections.emptySet(); this.mediaTypes = Collections.emptySet(); } else if (ANY.equals(filterString.trim())) { this.anyRenditions = true; } else { filterString = filterString.trim(); this.kinds = new HashSet<String>(); this.mediaTypes = new HashSet<MimeType>(); for (String token : SPLITTER.split(filterString)) { if (token.length() > 0 && !token.equals(ANY)) { for (char ch : token.toCharArray()) { if (Character.isWhitespace(ch)) { String msg = "Invalid filter \"" + filterString + "\". Filter's tokens must not have whitespace."; throw new FilterNotValidException(msg); } } if (token.indexOf('/') > 0) this.mediaTypes.add(MimeType.fromString(token)); else this.kinds.add(token); } else { // String contains empty token or some tokens and special token '*' String msg = "Invalid filter \"" + filterString + "\". Filter must contains either '*' OR comma-separated list mime-types or kinds of renditions."; throw new FilterNotValidException(msg); } } } } protected RenditionFilter() { } /** * {@inheritDoc} */ public boolean accept(Rendition rendition) { if (anyRenditions) return true; if (kinds.contains(rendition.getKind())) return true; MimeType toCheck = MimeType.fromString(rendition.getMimeType()); for (MimeType mediaType : mediaTypes) { if (mediaType.match(toCheck)) return true; } return false; } // TODO : do smarter with filter. Temporary just avoid to do unnecessary work and skip results. public boolean isNone() { return !anyRenditions && mediaTypes.size() == 0 && kinds.size() == 0; } }