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        @Override
030        public boolean match(String name) {
031            return true;
032        }
033    };
034
035    static class ExactMatch extends EntryFilter {
036        protected String pattern;
037
038        public ExactMatch(String pattern) {
039            this.pattern = pattern;
040        }
041
042        @Override
043        public boolean match(String name) {
044            return name.equals(pattern);
045        }
046    }
047
048    static class Filter extends EntryFilter {
049        protected String[] parts;
050
051        protected boolean startAny;
052
053        protected boolean endAny;
054
055        public Filter(String[] parts, boolean startAny, boolean endAny) {
056            this.startAny = startAny;
057            this.endAny = endAny;
058            this.parts = parts;
059        }
060
061        @Override
062        public boolean match(String name) {
063            int len = name.length();
064            int i = 0;
065            int p = 0;
066            if (startAny) {
067                i = name.indexOf(parts[p]);
068                if (i == -1) {
069                    return false;
070                }
071                i += parts[p++].length();
072            } else if (!name.startsWith(parts[p])) {
073                return false;
074            } else {
075                i += parts[p++].length();
076            }
077            while (i < len && p < parts.length) {
078                i = name.indexOf(parts[p], i);
079                if (i == -1) {
080                    return false;
081                }
082                i += parts[p++].length();
083            }
084            if (p < parts.length) {
085                return p == parts.length - 1 && endAny;
086            } else if (i < len) {
087                return endAny;
088            }
089            return true;
090        }
091    }
092
093    public static EntryFilter newFilter(String pattern) {
094        if (pattern == null || pattern.equals("*")) {
095            return ANY;
096        }
097        ArrayList<String> parts = new ArrayList<>();
098        int s = 0;
099        boolean startAny = false;
100        boolean endAny = false;
101        if (pattern.startsWith("*")) {
102            s++;
103            startAny = true;
104        }
105        int i = pattern.indexOf('*', s);
106        while (i > -1) {
107            parts.add(pattern.substring(s, i));
108            s = i + 1;
109            i = pattern.indexOf('*', s);
110        }
111        if (s < pattern.length()) {
112            parts.add(pattern.substring(s));
113        }
114        if (s == pattern.length()) {
115            endAny = true;
116        }
117        if (parts.isEmpty()) {
118            return new ExactMatch(pattern);
119        }
120        return new Filter(parts.toArray(new String[parts.size()]), startAny, endAny);
121    }
122
123    public abstract boolean match(String name);
124
125}