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 }