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.binding.unifi.internal.api.cache;
15 import java.util.Collection;
16 import java.util.HashMap;
17 import java.util.Locale;
19 import java.util.stream.Collectors;
21 import org.eclipse.jdt.annotation.NonNullByDefault;
22 import org.eclipse.jdt.annotation.Nullable;
23 import org.openhab.binding.unifi.internal.api.dto.HasId;
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
28 * The {@link UniFiCache} is a specialised lookup table that stores objects using multiple keys in the form
29 * <code>prefix:suffix</code>. Each implementation is responsible for providing a list of supported prefixes and must
30 * implement {@link #getSuffix(Object, String)} to provide a value specific suffix derived from the prefix.
32 * Objects are then retrieved simply by using the <code>suffix</code> key component and all combinations of
33 * <code>prefix:suffix</code> are searched in the order of their priority.
35 * @author Matthew Bowman - Initial contribution
36 * @author Hilbrand Bouwkamp - Moved generic code into this class
39 abstract class UniFiCache<T extends @Nullable HasId> {
51 private static final String SEPARATOR = ":";
53 private final Logger logger = LoggerFactory.getLogger(getClass());
54 // Map of cid keys to the id.
55 private final Map<String, String> mapToId = new HashMap<>();
56 // Map of id to data object
57 private final Map<String, T> map = new HashMap<>();
58 private final Prefix[] prefixes;
60 protected UniFiCache(final Prefix... prefixes) {
61 this.prefixes = prefixes;
68 public final @Nullable T get(final @Nullable String cid) {
69 final @Nullable T value;
71 if (cid != null && !cid.isBlank()) {
73 final String id = getId(cid);
76 logger.debug("Could not find an entry in the cache for id: '{}'", cid);
88 public @Nullable String getId(final String cid) {
90 for (final Prefix prefix : prefixes) {
91 final String key = key(prefix, cid);
93 if (mapToId.containsKey(key)) {
94 value = mapToId.get(key);
95 logger.trace("Cache HIT : '{}' -> {}", key, value);
98 logger.trace("Cache MISS : '{}'", key);
104 public final void putAll(final T @Nullable [] values) {
105 if (values != null) {
106 logger.debug("Put #{} entries in {}: {}", values.length, getClass().getSimpleName(),
107 lazyFormatAsList(values));
108 for (final T value : values) {
110 put(value.getId(), value);
116 public final void put(final String id, final T value) {
117 for (final Prefix prefix : prefixes) {
118 final String suffix = getSuffix(value, prefix);
120 if (suffix != null && !suffix.isBlank()) {
121 mapToId.put(key(prefix, suffix), id);
127 private static String key(final Prefix prefix, final String suffix) {
128 return prefix.name() + SEPARATOR + suffix.replace(":", "").toLowerCase(Locale.ROOT);
131 public final Collection<T> values() {
132 return map.values().stream().distinct().collect(Collectors.toList());
135 protected abstract @Nullable String getSuffix(T value, Prefix prefix);
137 private static Object lazyFormatAsList(final Object[] arr) {
138 return new Object() {
141 public String toString() {
143 for (final Object o : arr) {
144 value += "\n - " + o.toString();