View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2016 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.Objects;
23  import java.util.Set;
24  import java.util.function.Predicate;
25  
26  
27  /** Utility class to maintain a set of inclusions and exclusions.
28   * <p>Maintains a set of included and excluded elements.  The method {@link #matches(Object)}
29   * will return true IFF the passed object is not in the excluded set AND ( either the 
30   * included set is empty OR the object is in the included set) 
31   * <p>The type of the underlying {@link Set} used may be passed into the 
32   * constructor, so special sets like Servlet PathMap may be used.
33   * <p>
34   * @param <P> The type of element of the set (often a pattern)
35   * @param <T> The type of the instance passed to the predicate 
36   */
37  public class IncludeExcludeSet<P,T> implements Predicate<T>
38  {
39      private final Set<P> _includes;
40      private final Predicate<T> _includePredicate;
41      private final Set<P> _excludes;
42      private final Predicate<T> _excludePredicate;
43      
44      private static class SetContainsPredicate<T> implements Predicate<T>
45      {
46          private final Set<T> set;
47          
48          public SetContainsPredicate(Set<T> set)
49          {
50              this.set = set;
51          }
52          
53          @Override
54          public boolean test(T item)
55          {
56              return set.contains(item);
57          }
58      }
59      
60      /**
61       * Default constructor over {@link HashSet}
62       */
63      public IncludeExcludeSet()
64      {
65          this(HashSet.class);
66      }
67      
68      /**
69       * Construct an IncludeExclude.
70       * @param setClass The type of {@link Set} to using internally to hold patterns. Two instances will be created.
71       * one for include patterns and one for exclude patters.  If the class is also a {@link Predicate},
72       * then it is also used as the item test for the set, otherwise a {@link SetContainsPredicate} instance
73       * is created.
74       * @param <SET> The type of a set to use as the backing store
75       */
76      public <SET extends Set<P>> IncludeExcludeSet(Class<SET> setClass)
77      {
78          try
79          {
80              _includes = setClass.newInstance();
81              _excludes = setClass.newInstance();
82              
83              if(_includes instanceof Predicate) 
84              {
85                  _includePredicate = (Predicate<T>)_includes;
86              } 
87              else 
88              {
89                  _includePredicate = new SetContainsPredicate(_includes);
90              }
91              
92              if(_excludes instanceof Predicate) 
93              {
94                  _excludePredicate = (Predicate<T>)_excludes;
95              } 
96              else 
97              {
98                  _excludePredicate = new SetContainsPredicate(_excludes);
99              }
100         }
101         catch (InstantiationException | IllegalAccessException e)
102         {
103             throw new RuntimeException(e);
104         }
105     }
106     
107     /**
108      * Construct an IncludeExclude
109      * 
110      * @param includeSet the Set of items that represent the included space 
111      * @param includePredicate the Predicate for included item testing (null for simple {@link Set#contains(Object)} test)
112      * @param excludeSet the Set of items that represent the excluded space
113      * @param excludePredicate the Predicate for excluded item testing (null for simple {@link Set#contains(Object)} test)
114      * @param <SET> The type of a set to use as the backing store
115      */
116     public <SET extends Set<P>> IncludeExcludeSet(Set<P> includeSet, Predicate<T> includePredicate, Set<P> excludeSet, Predicate<T> excludePredicate)
117     {
118         Objects.requireNonNull(includeSet,"Include Set");
119         Objects.requireNonNull(includePredicate,"Include Predicate");
120         Objects.requireNonNull(excludeSet,"Exclude Set");
121         Objects.requireNonNull(excludePredicate,"Exclude Predicate");
122         
123         _includes = includeSet;
124         _includePredicate = includePredicate;
125         _excludes = excludeSet;
126         _excludePredicate = excludePredicate;
127     }
128     
129     public void include(P element)
130     {
131         _includes.add(element);
132     }
133     
134     public void include(P... element)
135     {
136         for (P e: element)
137             _includes.add(e);
138     }
139 
140     public void exclude(P element)
141     {
142         _excludes.add(element);
143     }
144     
145     public void exclude(P... element)
146     {
147         for (P e: element)
148             _excludes.add(e);
149     }
150 
151     public boolean matches(T t)
152     {
153         return test(t);
154     }
155     
156     public boolean test(T t)
157     {
158         if (!_includes.isEmpty() && !_includePredicate.test(t))
159             return false;
160         return !_excludePredicate.test(t);
161     }
162     
163     public int size()
164     {
165         return _includes.size()+_excludes.size();
166     }
167     
168     public Set<P> getIncluded()
169     {
170         return _includes;
171     }
172     
173     public Set<P> getExcluded()
174     {
175         return _excludes;
176     }
177 
178     public void clear()
179     {
180         _includes.clear();
181         _excludes.clear();
182     }
183 
184     @Override
185     public String toString()
186     {
187         return String.format("%s@%x{i=%s,ip=%s,e=%s,ep=%s}",this.getClass().getSimpleName(),hashCode(),_includes,_includePredicate,_excludes,_excludePredicate);
188     }
189 
190     public boolean isEmpty()
191     {
192         return _includes.isEmpty() && _excludes.isEmpty();
193     }
194 }