001/*
002 * (C) Copyright 2006-2010 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     bstefanescu
018 */
019package org.nuxeo.osgi.util;
020
021import java.util.ArrayList;
022
023/**
024 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
025 */
026public abstract class EntryFilter {
027
028    public static final EntryFilter ANY = new EntryFilter() {
029        public boolean match(String name) {
030            return true;
031        }
032    };
033
034    static class ExactMatch extends EntryFilter {
035        protected String pattern;
036
037        public ExactMatch(String pattern) {
038            this.pattern = pattern;
039        }
040
041        @Override
042        public boolean match(String name) {
043            return name.equals(pattern);
044        }
045    }
046
047    static class Filter extends EntryFilter {
048        protected String[] parts;
049
050        protected boolean startAny;
051
052        protected boolean endAny;
053
054        public Filter(String[] parts, boolean startAny, boolean endAny) {
055            this.startAny = startAny;
056            this.endAny = endAny;
057            this.parts = parts;
058        }
059
060        @Override
061        public boolean match(String name) {
062            int len = name.length();
063            int i = 0;
064            int p = 0;
065            if (startAny) {
066                i = name.indexOf(parts[p]);
067                if (i == -1) {
068                    return false;
069                }
070                i += parts[p++].length();
071            } else if (!name.startsWith(parts[p])) {
072                return false;
073            } else {
074                i += parts[p++].length();
075            }
076            while (i < len && p < parts.length) {
077                i = name.indexOf(parts[p], i);
078                if (i == -1) {
079                    return false;
080                }
081                i += parts[p++].length();
082            }
083            if (p < parts.length) {
084                return p == parts.length - 1 && endAny;
085            } else if (i < len) {
086                return endAny;
087            }
088            return true;
089        }
090    }
091
092    public static EntryFilter newFilter(String pattern) {
093        if (pattern == null || pattern.equals("*")) {
094            return ANY;
095        }
096        ArrayList<String> parts = new ArrayList<String>();
097        int s = 0;
098        boolean startAny = false;
099        boolean endAny = false;
100        if (pattern.startsWith("*")) {
101            s++;
102            startAny = true;
103        }
104        int i = pattern.indexOf('*', s);
105        while (i > -1) {
106            parts.add(pattern.substring(s, i));
107            s = i + 1;
108            i = pattern.indexOf('*', s);
109        }
110        if (s < pattern.length()) {
111            parts.add(pattern.substring(s));
112        }
113        if (s == pattern.length()) {
114            endAny = true;
115        }
116        if (parts.isEmpty()) {
117            return new ExactMatch(pattern);
118        }
119        return new Filter(parts.toArray(new String[parts.size()]), startAny, endAny);
120    }
121
122    public abstract boolean match(String name);
123
124}