001    /**
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *     http://www.apache.org/licenses/LICENSE-2.0
010     *
011     *  Unless required by applicable law or agreed to in writing, software
012     *  distributed under the License is distributed on an "AS IS" BASIS,
013     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     *  See the License for the specific language governing permissions and
015     *  limitations under the License.
016     */
017    package org.apache.xbean.finder.filter;
018    
019    import java.util.ArrayList;
020    import java.util.Arrays;
021    import java.util.Iterator;
022    import java.util.LinkedHashSet;
023    import java.util.List;
024    import java.util.Set;
025    
026    /**
027     * @version $Rev$ $Date$
028     */
029    public class Filters {
030        private static final Filter NONE = new Filter() {
031            @Override
032            public boolean accept(String name) {
033                return false;
034            }
035        };
036    
037        public static Filter packages(String... packages) {
038            List<Filter> filters = new ArrayList<Filter>();
039            for (String s : packages) {
040                filters.add(new PackageFilter(s));
041            }
042    
043            return optimize(filters);
044        }
045    
046        public static Filter classes(String... classes) {
047            List<Filter> filters = new ArrayList<Filter>();
048            for (String s : classes) {
049                filters.add(new ClassFilter(s));
050            }
051    
052            return optimize(filters);
053        }
054    
055        public static Filter prefixes(String... prefixes) {
056            List<Filter> filters = new ArrayList<Filter>();
057            for (String s : prefixes) {
058                filters.add(new PrefixFilter(s));
059            }
060    
061            return optimize(filters);
062        }
063    
064        public static Filter tokens(String... tokens) {
065            List<Filter> filters = new ArrayList<Filter>();
066            for (String s : tokens) {
067                filters.add(new ContainsFilter(s));
068            }
069    
070            return optimize(filters);
071        }
072    
073        public static Filter suffixes(String... suffixes) {
074            List<Filter> filters = new ArrayList<Filter>();
075            for (String s : suffixes) {
076                filters.add(new SuffixFilter(s));
077            }
078    
079            return optimize(filters);
080        }
081    
082        public static Filter patterns(String... patterns) {
083            List<Filter> filters = new ArrayList<Filter>();
084            for (String s : patterns) {
085                filters.add(new PatternFilter(s));
086            }
087    
088            return optimize(filters);
089        }
090    
091    
092        public static Filter optimize(Filter... filters) {
093            return optimize(Arrays.asList(filters));
094        }
095    
096        public static Filter optimize(List<Filter>... filterss) {
097            Set<Filter> unwrapped = new LinkedHashSet<Filter>();
098    
099            for (List<Filter> filters : filterss) {
100                unwrap(filters, unwrapped);
101            }
102    
103            if (unwrapped.size() > 1) {
104                Iterator<Filter> iterator = unwrapped.iterator();
105                while (iterator.hasNext()) {
106                    Filter filter = iterator.next();
107                    if (filter == NONE) iterator.remove();
108                }
109            }
110    
111            if (unwrapped.size() == 0) return NONE;
112            if (unwrapped.size() == 1) return unwrapped.iterator().next();
113            return new FilterList(unwrapped);
114        }
115    
116        /**
117         * Will invert the meaning of this filter by wrapping it with
118         * a filter that negates the return of the accept method.
119         *
120         * If the passed in filter is already wrapped, it will be
121         * unwrapped and returned.  This is to prevent endless wrapping
122         * if the invert method is called many times.
123         * 
124         * @param filter
125         * @return
126         */
127        public static Filter invert(Filter filter) {
128            if (filter instanceof NegativeFilter) {
129                NegativeFilter negativeFilter = (NegativeFilter) filter;
130                return negativeFilter.getFilter();
131            }
132    
133            return new NegativeFilter(filter);
134        }
135    
136        private static void unwrap(List<Filter> filters, Set<Filter> unwrapped) {
137            for (Filter filter : filters) {
138                if (filter instanceof FilterList) {
139                    FilterList filterList = (FilterList) filter;
140                    unwrap(filterList.getFilters(), unwrapped);
141                } else {
142                    unwrapped.add(filter);
143                }
144            }
145        }
146    
147        private static final class NegativeFilter implements Filter {
148            private final Filter filter;
149    
150            public NegativeFilter(Filter filter) {
151                this.filter = filter;
152            }
153    
154            @Override
155            public boolean accept(String name) {
156                return !filter.accept(name);
157            }
158    
159            public Filter getFilter() {
160                return filter;
161            }
162        }
163    
164    }