001// ***************************************************************************************************************************
002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
003// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
005// * with the License.  You may obtain a copy of the License at                                                              *
006// *                                                                                                                         *
007// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
008// *                                                                                                                         *
009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
011// * specific language governing permissions and limitations under the License.                                              *
012// ***************************************************************************************************************************
013package org.apache.juneau.internal;
014
015import static java.util.Collections.*;
016import static java.util.stream.Collectors.*;
017
018import java.util.*;
019
020import org.apache.juneau.utils.*;
021
022/**
023 * A linked hashmap with reverse key lookup by value.
024 *
025 * @param <K> The key type.
026 * @param <V> The value type.
027 */
028public class BiMap<K,V> implements Map<K,V> {
029
030   //-----------------------------------------------------------------------------------------------------------------
031   // Static
032   //-----------------------------------------------------------------------------------------------------------------
033
034   /**
035    * Create a new builder for this class.
036    *
037    * @param <K> The key type.
038    * @param <V> The value type.
039    * @return A new builder.
040    */
041   public static <K,V> Builder<K,V> create() {
042      return new Builder<>();
043   }
044
045   //-----------------------------------------------------------------------------------------------------------------
046   // Builder
047   //-----------------------------------------------------------------------------------------------------------------
048
049   /**
050    * Builder class.
051    *
052    * @param <K> The key type.
053    * @param <V> The value type.
054    */
055   public static class Builder<K,V> {
056      final HashMap<K,V> map = new LinkedHashMap<>();
057      boolean unmodifiable;
058
059      /**
060       * Adds a value to this map.
061       *
062       * @param key The key.
063       * @param value The value.
064       * @return This object.
065       */
066      public Builder<K,V> add(K key, V value) {
067         map.put(key, value);
068         return this;
069      }
070
071      /**
072       * Makes this map unmodifiable.
073       *
074       * @return This object.
075       */
076      public Builder<K,V> unmodifiable() {
077         unmodifiable = true;
078         return this;
079      }
080
081      /**
082       * Build the differences.
083       *
084       * @return A new {@link BeanDiff} object.
085       */
086      public BiMap<K,V> build() {
087         return new BiMap<>(this);
088      }
089
090   }
091
092   //-----------------------------------------------------------------------------------------------------------------
093   // Instance
094   //-----------------------------------------------------------------------------------------------------------------
095
096   private final Map<K,V> forward;
097   private final Map<V,K> reverse;
098
099   /**
100    * Constructor.
101    *
102    * @param builder The builder for this object.
103    */
104   public BiMap(Builder<K,V> builder) {
105      Map<K,V> forward = builder.map.entrySet().stream().filter(x -> x.getKey() != null && x.getValue() != null).collect(toMap(Map.Entry::getKey, Map.Entry::getValue));
106      Map<V,K> reverse = builder.map.entrySet().stream().filter(x -> x.getKey() != null && x.getValue() != null).collect(toMap(Map.Entry::getValue, Map.Entry::getKey));
107      this.forward = builder.unmodifiable ? unmodifiableMap(forward) : forward;
108      this.reverse = builder.unmodifiable ? unmodifiableMap(reverse) : reverse;
109   }
110
111   /**
112    * Gets the key that is currently mapped to the specified value.
113    *
114    * @param value The value to return.
115    * @return The key matching the value.
116    */
117   public K getKey(V value) {
118      return reverse.get(value);
119   }
120
121
122   @Override /* Map */
123   public int size() {
124      return forward.size();
125   }
126
127   @Override /* Map */
128   public boolean isEmpty() {
129      return forward.isEmpty();
130   }
131
132   @Override /* Map */
133   public boolean containsKey(Object key) {
134      return forward.containsKey(key);
135   }
136
137   @Override /* Map */
138   public boolean containsValue(Object value) {
139      return reverse.containsKey(value);
140   }
141
142   @Override /* Map */
143   public V get(Object key) {
144      return forward.get(key);
145   }
146
147   @Override /* Map */
148   public V put(K key, V value) {
149      reverse.put(value, key);
150      return forward.put(key, value);
151   }
152
153   @Override /* Map */
154   public V remove(Object key) {
155      V value = forward.remove(key);
156      reverse.remove(value);
157      return value;
158   }
159
160   @Override /* Map */
161   public void putAll(Map<? extends K,? extends V> m) {
162      forward.putAll(m);
163      m.entrySet().forEach(x -> reverse.put(x.getValue(), x.getKey()));
164   }
165
166   @Override /* Map */
167   public void clear() {
168      forward.clear();
169      reverse.clear();
170   }
171
172   @Override /* Map */
173   public Set<K> keySet() {
174      return forward.keySet();
175   }
176
177   @Override /* Map */
178   public Collection<V> values() {
179      return forward.values();
180   }
181
182   @Override /* Map */
183   public Set<Entry<K,V>> entrySet() {
184      return forward.entrySet();
185   }
186}