View Javadoc
1   /*
2    * Copyright 2012-2025 CodeLibs Project and the Others.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13   * either express or implied. See the License for the specific language
14   * governing permissions and limitations under the License.
15   */
16  package org.codelibs.fess.entity;
17  
18  import java.util.Collection;
19  import java.util.Map;
20  import java.util.Set;
21  import java.util.function.BiConsumer;
22  import java.util.function.BiFunction;
23  import java.util.function.Function;
24  
25  import org.apache.commons.lang3.StringUtils;
26  
27  import com.google.common.base.CaseFormat;
28  
29  /**
30   * Parameter map that converts between camelCase and snake_case.
31   *
32   * @param <K> the key type
33   * @param <V> the value type
34   */
35  public class ParamMap<K, V> implements Map<K, V> {
36  
37      private final Map<K, V> parent;
38  
39      /**
40       * Creates a new parameter map.
41       *
42       * @param parent the parent map
43       */
44      public ParamMap(final Map<K, V> parent) {
45          this.parent = parent;
46      }
47  
48      /**
49       * Gets the parent map.
50       *
51       * @return the parent map
52       */
53      public Map<K, V> getParent() {
54          return parent;
55      }
56  
57      /**
58       * Converts a key to camelCase.
59       *
60       * @param key the key to convert
61       * @return the converted key
62       */
63      protected Object toCamelCase(final Object key) {
64          if (key == null) {
65              return key;
66          }
67          String keyStr = key.toString();
68          if (keyStr.indexOf('_') < 0) {
69              keyStr = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, StringUtils.uncapitalize(keyStr));
70          } else {
71              keyStr = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, keyStr);
72          }
73          return keyStr;
74      }
75  
76      @Override
77      public int size() {
78          return parent.size();
79      }
80  
81      @Override
82      public boolean isEmpty() {
83          return parent.isEmpty();
84      }
85  
86      @Override
87      public boolean containsKey(final Object key) {
88          if (parent.containsKey(key)) {
89              return true;
90          }
91          return parent.containsKey(toCamelCase(key));
92      }
93  
94      @Override
95      public boolean containsValue(final Object value) {
96          return parent.containsValue(value);
97      }
98  
99      @Override
100     public V get(final Object key) {
101         final V value = parent.get(key);
102         if (value != null) {
103             return value;
104         }
105         return parent.get(toCamelCase(key));
106     }
107 
108     @Override
109     public V put(final K key, final V value) {
110         return parent.put(key, value);
111     }
112 
113     @Override
114     public V remove(final Object key) {
115         final V value = parent.remove(key);
116         if (value != null) {
117             return value;
118         }
119         return parent.remove(key);
120     }
121 
122     @Override
123     public void putAll(final Map<? extends K, ? extends V> m) {
124         parent.putAll(m);
125     }
126 
127     @Override
128     public void clear() {
129         parent.clear();
130     }
131 
132     @Override
133     public Set<K> keySet() {
134         // return original keys
135         return parent.keySet();
136     }
137 
138     @Override
139     public Collection<V> values() {
140         return parent.values();
141     }
142 
143     @Override
144     public Set<Entry<K, V>> entrySet() {
145         // return original keys
146         return parent.entrySet();
147     }
148 
149     @Override
150     public boolean equals(final Object o) {
151         return parent.equals(o);
152     }
153 
154     @Override
155     public int hashCode() {
156         return parent.hashCode();
157     }
158 
159     @Override
160     public V getOrDefault(final Object key, final V defaultValue) {
161         final V value = parent.get(key);
162         if (value != null) {
163             return value;
164         }
165         return parent.getOrDefault(toCamelCase(key), defaultValue);
166     }
167 
168     @Override
169     public void forEach(final BiConsumer<? super K, ? super V> action) {
170         parent.forEach(action);
171     }
172 
173     @Override
174     public void replaceAll(final BiFunction<? super K, ? super V, ? extends V> function) {
175         parent.replaceAll(function);
176     }
177 
178     @Override
179     public V putIfAbsent(final K key, final V value) {
180         return parent.putIfAbsent(key, value);
181     }
182 
183     @Override
184     public boolean remove(final Object key, final Object value) {
185         if (parent.remove(key, value)) {
186             return true;
187         }
188         return parent.remove(toCamelCase(key), value);
189     }
190 
191     @Override
192     public boolean replace(final K key, final V oldValue, final V newValue) {
193         if (parent.replace(key, oldValue, newValue)) {
194             return true;
195         }
196         return parent.replace(key, oldValue, newValue);
197     }
198 
199     @Override
200     public V replace(final K key, final V value) {
201         // use original key
202         return parent.replace(key, value);
203     }
204 
205     @Override
206     public V computeIfAbsent(final K key, final Function<? super K, ? extends V> mappingFunction) {
207         // use original key
208         return parent.computeIfAbsent(key, mappingFunction);
209     }
210 
211     @Override
212     public V computeIfPresent(final K key, final BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
213         // use original key
214         return parent.computeIfPresent(key, remappingFunction);
215     }
216 
217     @Override
218     public V compute(final K key, final BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
219         // use original key
220         return parent.compute(key, remappingFunction);
221     }
222 
223     @Override
224     public V merge(final K key, final V value, final BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
225         // use original key
226         return parent.merge(key, value, remappingFunction);
227     }
228 }