001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.chain.web; 018 019import java.util.Enumeration; 020import java.util.Map; 021import java.util.Set; 022import java.util.function.BiConsumer; 023import java.util.function.Consumer; 024import java.util.function.Function; 025import java.util.function.Supplier; 026 027/** 028 * Implementation of {@code Map} for mutable parameters with a 029 * parameter-provider. 030 * 031 * @param <P> the type of the parameter-provider 032 * @param <T> the type of results supplied by this parameters 033 * 034 * @author Graff Stefan 035 * @since Chain 1.3 036 */ 037public class MutableParameterMap<P, T> extends ParameterMap<P, T> { 038 039 /** 040 * Consumer which removes the given public or private parameter. 041 * All values associated with the name are removed. 042 */ 043 private final Consumer<String> removeConsumer; 044 045 /** 046 * BiConsumer which stores an {@link Object} in this parameter. 047 */ 048 private final BiConsumer<String, T> setConsumer; 049 050 /** 051 * The constructor for an mutable parameter-map. 052 * 053 * @param parameter the parameter-provider 054 * @param valueFunction Function to return the value of a parameter 055 * @param namesSupplier Supplier to return all names of the parameter 056 * @param removeConsumer Consumer to remove a value of the parameter 057 * @param setConsumer BiConsumer to stores a value of the parameter 058 */ 059 public MutableParameterMap(final P parameter, final Function<String, T> valueFunction, 060 final Supplier<Enumeration<String>> namesSupplier, final Consumer<String> removeConsumer, 061 final BiConsumer<String, T> setConsumer) { 062 063 super(parameter, valueFunction, namesSupplier); 064 this.removeConsumer = removeConsumer; 065 this.setConsumer = setConsumer; 066 } 067 068 /** 069 * Removes all of the mappings from this parameter-map. 070 * The parameter-map will be empty after this call returns. 071 */ 072 @Override 073 public void clear() { 074 for (String key : keySet()) { 075 removeConsumer.accept(key); 076 } 077 } 078 079 /** 080 * Returns {@code true} if this parameter-map maps one or more keys 081 * to the specified value. 082 * 083 * @param value value whose presence in this parameter-map is to be 084 * tested 085 * 086 * @return {@code true} if this parameter-map maps one or more keys 087 * to the specified value 088 */ 089 @Override 090 public boolean containsValue(Object value) { 091 return value != null && super.containsValue(value); 092 } 093 094 /** 095 * Returns a {@link Set} view of the mappings contained in this 096 * parameter-map. The set is not backed by the parameter-map, so 097 * changes to the parameter-map are not reflected in the set, 098 * and vice-versa. 099 * 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}