1 //
2 // ========================================================================
3 // Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
4 // ------------------------------------------------------------------------
5 // All rights reserved. This program and the accompanying materials
6 // are made available under the terms of the Eclipse Public License v1.0
7 // and Apache License v2.0 which accompanies this distribution.
8 //
9 // The Eclipse Public License is available at
10 // http://www.eclipse.org/legal/epl-v10.html
11 //
12 // The Apache License v2.0 is available at
13 // http://www.opensource.org/licenses/apache2.0.php
14 //
15 // You may elect to redistribute this code under either of these licenses.
16 // ========================================================================
17 //
18
19 package org.eclipse.jetty.util;
20
21 import java.util.HashSet;
22 import java.util.Set;
23
24
25 /** Utility class to maintain a set of inclusions and exclusions.
26 * <p>Maintains a set of included and excluded elements. The method {@link #matches(Object)}
27 * will return true IFF the passed object is not in the excluded set AND ( either the
28 * included set is empty OR the object is in the included set)
29 * <p>The type of the underlying {@link Set} used may be passed into the
30 * constructor, so special sets like Servlet PathMap may be used.
31 * <p>
32 * @param <P> The type of element of the set (often a pattern)
33 * @param <T> The type of the instance passed to the predicate
34 */
35 public class IncludeExcludeSet<P,T> implements Predicate<T>
36 {
37 private final Set<P> _includes;
38 private final Predicate<T> _includePredicate;
39 private final Set<P> _excludes;
40 private final Predicate<T> _excludePredicate;
41
42 private static class SetContainsPredicate<T> implements Predicate<T>
43 {
44 private final Set<T> set;
45
46 public SetContainsPredicate(Set<T> set)
47 {
48 this.set = set;
49 }
50
51 @Override
52 public boolean test(T item)
53 {
54 return set.contains(item);
55 }
56 }
57
58 /**
59 * Default constructor over {@link HashSet}
60 */
61 public IncludeExcludeSet()
62 {
63 this(HashSet.class);
64 }
65
66 /**
67 * Construct an IncludeExclude
68 * @param setClass The type of {@link Set} to using internally to hold patterns. Two instances will be created.
69 * one for include patterns and one for exclude patters. If the class is also a {@link Predicate},
70 * then it is also used as the item test for the set, otherwise a {@link SetContainsPredicate} instance
71 * is created.
72 * @param <SET> The type of a set to use as the backing store
73 */
74 public <SET extends Set<P>> IncludeExcludeSet(Class<SET> setClass)
75 {
76 try
77 {
78 _includes = setClass.newInstance();
79 _excludes = setClass.newInstance();
80
81 if(_includes instanceof Predicate)
82 {
83 _includePredicate = (Predicate<T>)_includes;
84 }
85 else
86 {
87 _includePredicate = new SetContainsPredicate(_includes);
88 }
89
90 if(_excludes instanceof Predicate)
91 {
92 _excludePredicate = (Predicate<T>)_excludes;
93 }
94 else
95 {
96 _excludePredicate = new SetContainsPredicate(_excludes);
97 }
98 }
99 catch (InstantiationException | IllegalAccessException e)
100 {
101 throw new RuntimeException(e);
102 }
103 }
104
105 /**
106 * Construct an IncludeExclude
107 *
108 * @param includeSet the Set of items that represent the included space
109 * @param includePredicate the Predicate for included item testing (null for simple {@link Set#contains(Object)} test)
110 * @param excludeSet the Set of items that represent the excluded space
111 * @param excludePredicate the Predicate for excluded item testing (null for simple {@link Set#contains(Object)} test)
112 * @param <SET> The type of a set to use as the backing store
113 */
114 public <SET extends Set<P>> IncludeExcludeSet(Set<P> includeSet, Predicate<T> includePredicate, Set<P> excludeSet, Predicate<T> excludePredicate)
115 {
116 _includes = includeSet;
117 _includePredicate = includePredicate;
118 _excludes = excludeSet;
119 _excludePredicate = excludePredicate;
120 }
121
122 public void include(P element)
123 {
124 _includes.add(element);
125 }
126
127 public void include(P... element)
128 {
129 for (P e: element)
130 _includes.add(e);
131 }
132
133 public void exclude(P element)
134 {
135 _excludes.add(element);
136 }
137
138 public void exclude(P... element)
139 {
140 for (P e: element)
141 _excludes.add(e);
142 }
143
144 public boolean matches(T t)
145 {
146 return test(t);
147 }
148
149 public boolean test(T t)
150 {
151 if (!_includes.isEmpty() && !_includePredicate.test(t))
152 return false;
153 return !_excludePredicate.test(t);
154 }
155
156 public int size()
157 {
158 return _includes.size()+_excludes.size();
159 }
160
161 public Set<P> getIncluded()
162 {
163 return _includes;
164 }
165
166 public Set<P> getExcluded()
167 {
168 return _excludes;
169 }
170
171 public void clear()
172 {
173 _includes.clear();
174 _excludes.clear();
175 }
176
177 @Override
178 public String toString()
179 {
180 return String.format("%s@%x{i=%s,ip=%s,e=%s,ep=%s}",this.getClass().getSimpleName(),hashCode(),_includes,_includePredicate,_excludes,_excludePredicate);
181 }
182 }