View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.chain.web;
18  
19  import java.util.Enumeration;
20  import java.util.Map;
21  import java.util.Set;
22  import java.util.function.BiConsumer;
23  import java.util.function.Consumer;
24  import java.util.function.Function;
25  import java.util.function.Supplier;
26  
27  /**
28   * Implementation of {@code Map} for mutable parameters with a
29   * parameter-provider.
30   *
31   * @param <P> the type of the parameter-provider
32   * @param <T> the type of results supplied by this parameters
33   *
34   * @author Graff Stefan
35   * @since Chain 1.3
36   */
37  public class MutableParameterMap<P, T> extends ParameterMap<P, T> {
38  
39      /**
40       * Consumer which removes the given public or private parameter.
41       * All values associated with the name are removed.
42       */
43      private final Consumer<String> removeConsumer;
44  
45      /**
46       * BiConsumer which stores an {@link Object} in this parameter.
47       */
48      private final BiConsumer<String, T> setConsumer;
49  
50      /**
51       * The constructor for an mutable parameter-map.
52       *
53       * @param parameter the parameter-provider
54       * @param valueFunction Function to return the value of a parameter
55       * @param namesSupplier Supplier to return all names of the parameter
56       * @param removeConsumer Consumer to remove a value of the parameter
57       * @param setConsumer BiConsumer to stores a value of the parameter
58       */
59      public MutableParameterMap(final P parameter, final Function<String, T> valueFunction,
60              final Supplier<Enumeration<String>> namesSupplier, final Consumer<String> removeConsumer,
61              final BiConsumer<String, T> setConsumer) {
62  
63          super(parameter, valueFunction, namesSupplier);
64          this.removeConsumer = removeConsumer;
65          this.setConsumer = setConsumer;
66      }
67  
68      /**
69       * Removes all of the mappings from this parameter-map.
70       * The parameter-map will be empty after this call returns.
71       */
72      @Override
73      public void clear() {
74          for (String key : keySet()) {
75              removeConsumer.accept(key);
76          }
77      }
78  
79      /**
80       * Returns {@code true} if this parameter-map maps one or more keys
81       * to the specified value.
82       *
83       * @param value value whose presence in this parameter-map is to be
84       *        tested
85       *
86       * @return {@code true} if this parameter-map maps one or more keys
87       *         to the specified value
88       */
89      @Override
90      public boolean containsValue(Object value) {
91          return value != null && super.containsValue(value);
92      }
93  
94      /**
95       * Returns a {@link Set} view of the mappings contained in this
96       * parameter-map. The set is not backed by the parameter-map, so
97       * changes to the parameter-map are not reflected in the set,
98       * and vice-versa.
99       *
100      * @return a set view of the mappings contained in this
101      *         parameter-map
102      */
103     @Override
104     public Set<Map.Entry<String, T>> entrySet() {
105         return entrySet(true);
106     }
107 
108     /**
109      * Associates the specified value with the specified key in this
110      * parameter-map. If the parameter-map previously contained a
111      * mapping for the key, the old value is replaced.
112      *
113      * @param key key with which the specified value is to be associated
114      * @param value value to be associated with the specified key
115      *
116      * @return the previous value associated with {@code key}, or
117      *         {@code null} if there was no mapping for {@code key}.
118      *         (A {@code null} return can also indicate that the
119      *         parameter-map previously associated {@code null} with
120      *         {@code key}.)
121      */
122     @Override
123     public T put(String key, T value) {
124         if (value == null) {
125             return remove(key);
126         }
127         final T previous = getValueFunction().apply(key);
128         setConsumer.accept(key, value);
129         return previous;
130     }
131 
132     /**
133      * Copies all of the mappings from the specified map to this
134      * parameter-map. These mappings will replace any mappings that
135      * this parameter-map had for any of the keys currently in the
136      * specified map.
137      *
138      * @param map mappings to be stored in this parameter-map
139      *
140      * @throws NullPointerException if the specified map is null
141      */
142     @Override
143     public void putAll(Map<? extends String, ? extends T> map) {
144         map.forEach(this::put);
145     }
146 
147     /**
148      * Removes the mapping for the specified key from this
149      * parameter-map if present.
150      *
151      * @param key key whose mapping is to be removed from the
152      *        parameter-map
153      *
154      * @return the previous value associated with {@code key}, or
155      *         {@code null} if there was no mapping for {@code key}.
156      *         (A {@code null} return can also indicate that the
157      *         parameter-map previously associated {@code null} with
158      *         {@code key}.)
159      */
160     @Override
161     public T remove(Object key) {
162         final String skey = key(key);
163         final T previous = getValueFunction().apply(skey);
164         removeConsumer.accept(skey);
165         return previous;
166     }
167 
168     /**
169      * Returns the hash code value for this parameter-map. The
170      * hash code of a parameter-map is defined to be the sum of
171      * the hash codes of each entry in the parameter-map's
172      * {@code entrySet()} view. This ensures that {@code m1.equals(m2)}
173      * implies that {@code m1.hashCode()==m2.hashCode()} for any two
174      * parameter-maps {@code m1} and {@code m2}, as required by the
175      * general contract of {@link Object#hashCode}.
176      *
177      * @implSpec
178      * This implementation calls the {@code hashCode()} from the
179      * parameter-provider.
180      *
181      * @return the hash code value for this parameter-map
182      */
183     @Override
184     public int hashCode() {
185         return super.hashCode();
186     }
187 
188     /**
189      * Compares the specified object with this parameter-map for equality.
190      * Returns {@code true} if the given object is also a parameter-map
191      * and the two parameter-maps represent the same mappings. More formally,
192      * two parameter-maps {@code m1} and {@code m2} represent the same
193      * mappings if {@code m1.entrySet().equals(m2.entrySet())}.
194      *
195      * @implSpec
196      * This implementation first checks if the specified object is this
197      * parameter-map; if so it returns {@code true}. Then, it checks if
198      * the specified object is the identical class this parameter-map; if
199      * not, it returns {@code false}. If so, it calls the {@code equals()}
200      * from the parameter-provider and returns its return-code.
201      *
202      * @param obj object to be compared for equality with this
203      *        parameter-map
204      *
205      * @return {@code true} if the specified object is equal to this
206      *         parameter-map
207      */
208     @Override
209     public boolean equals(Object obj) {
210         return super.equals(obj);
211     }
212 }