2 * Copyright (c) 2010-2023 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.automation.jrubyscripting.internal.watch;
15 import java.util.Collections;
16 import java.util.HashMap;
17 import java.util.HashSet;
20 import java.util.concurrent.locks.ReentrantReadWriteLock;
22 import org.eclipse.jdt.annotation.NonNullByDefault;
24 // Copy of org.openhab.core.automation.module.script.rulesupport.internal.loader.collection.BidiSetBag
27 * Bidirectional bag of unique elements. A map allowing multiple, unique values to be stored against a single key.
28 * Provides optimized lookup of values for a key, as well as keys referencing a value.
30 * @author Jonathan Gilbert - Initial contribution
31 * @author Jan N. Klug - Make implementation thread-safe
32 * @param <K> Type of Key
33 * @param <V> Type of Value
36 public class BidiSetBag<K, V> {
38 private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
39 private final Map<K, Set<V>> keyToValues = new HashMap<>();
40 private final Map<V, Set<K>> valueToKeys = new HashMap<>();
42 public void put(K key, V value) {
43 lock.writeLock().lock();
45 keyToValues.computeIfAbsent(key, k -> new HashSet<>()).add(value);
46 valueToKeys.computeIfAbsent(value, v -> new HashSet<>()).add(key);
48 lock.writeLock().unlock();
52 public Set<V> getValues(K key) {
53 lock.readLock().lock();
55 Set<V> values = keyToValues.getOrDefault(key, Set.of());
56 return Collections.unmodifiableSet(values);
58 lock.readLock().unlock();
62 public Set<K> getKeys(V value) {
63 lock.readLock().lock();
65 Set<K> keys = valueToKeys.getOrDefault(value, Set.of());
66 return Collections.unmodifiableSet(keys);
68 lock.readLock().unlock();
72 public Set<V> removeKey(K key) {
73 lock.writeLock().lock();
75 Set<V> values = keyToValues.remove(key);
77 for (V value : values) {
78 valueToKeys.computeIfPresent(value, (k, v) -> {
88 lock.writeLock().unlock();
92 public Set<K> removeValue(V value) {
93 lock.writeLock().lock();
95 Set<K> keys = valueToKeys.remove(value);
98 keyToValues.computeIfPresent(key, (k, v) -> {
108 lock.writeLock().unlock();