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 }