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 }