001/*
002 * (C) Copyright 2006-2010 Nuxeo SAS (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     bstefanescu
016 */
017package org.nuxeo.osgi.util;
018
019import java.util.ArrayList;
020
021/**
022 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
023 */
024public abstract class EntryFilter {
025
026    public static final EntryFilter ANY = new EntryFilter() {
027        public boolean match(String name) {
028            return true;
029        }
030    };
031
032    static class ExactMatch extends EntryFilter {
033        protected String pattern;
034
035        public ExactMatch(String pattern) {
036            this.pattern = pattern;
037        }
038
039        @Override
040        public boolean match(String name) {
041            return name.equals(pattern);
042        }
043    }
044
045    static class Filter extends EntryFilter {
046        protected String[] parts;
047
048        protected boolean startAny;
049
050        protected boolean endAny;
051
052        public Filter(String[] parts, boolean startAny, boolean endAny) {
053            this.startAny = startAny;
054            this.endAny = endAny;
055            this.parts = parts;
056        }
057
058        @Override
059        public boolean match(String name) {
060            int len = name.length();
061            int i = 0;
062            int p = 0;
063            if (startAny) {
064                i = name.indexOf(parts[p]);
065                if (i == -1) {
066                    return false;
067                }
068                i += parts[p++].length();
069            } else if (!name.startsWith(parts[p])) {
070                return false;
071            } else {
072                i += parts[p++].length();
073            }
074            while (i < len && p < parts.length) {
075                i = name.indexOf(parts[p], i);
076                if (i == -1) {
077                    return false;
078                }
079                i += parts[p++].length();
080            }
081            if (p < parts.length) {
082                return p == parts.length - 1 && endAny;
083            } else if (i < len) {
084                return endAny;
085            }
086            return true;
087        }
088    }
089
090    public static EntryFilter newFilter(String pattern) {
091        if (pattern == null || pattern.equals("*")) {
092            return ANY;
093        }
094        ArrayList<String> parts = new ArrayList<String>();
095        int s = 0;
096        boolean startAny = false;
097        boolean endAny = false;
098        if (pattern.startsWith("*")) {
099            s++;
100            startAny = true;
101        }
102        int i = pattern.indexOf('*', s);
103        while (i > -1) {
104            parts.add(pattern.substring(s, i));
105            s = i + 1;
106            i = pattern.indexOf('*', s);
107        }
108        if (s < pattern.length()) {
109            parts.add(pattern.substring(s));
110        }
111        if (s == pattern.length()) {
112            endAny = true;
113        }
114        if (parts.isEmpty()) {
115            return new ExactMatch(pattern);
116        }
117        return new Filter(parts.toArray(new String[parts.size()]), startAny, endAny);
118    }
119
120    public abstract boolean match(String name);
121
122}