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.Objects;
20 import java.util.stream.Collectors;
21 import java.util.stream.Stream;
23 import org.eclipse.jdt.annotation.NonNullByDefault;
24 import org.eclipse.jdt.annotation.Nullable;
25 import org.openhab.binding.unifi.internal.api.dto.HasId;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
30 * The {@link UniFiCache} is a specialised lookup table that stores objects using multiple keys in the form
31 * <code>prefix:suffix</code>. Each implementation is responsible for providing a list of supported prefixes and must
32 * implement {@link #getSuffix(Object, String)} to provide a value specific suffix derived from the prefix.
34 * Objects are then retrieved simply by using the <code>suffix</code> key component and all combinations of
35 * <code>prefix:suffix</code> are searched in the order of their priority.
37 * @author Matthew Bowman - Initial contribution
38 * @author Hilbrand Bouwkamp - Moved generic code into this class
41 abstract class UniFiCache<T extends @Nullable HasId> {
52 private static final String SEPARATOR = ":";
54 private final Logger logger = LoggerFactory.getLogger(getClass());
55 // Map of cid keys to the id.
56 private final Map<String, String> mapToId = new HashMap<>();
57 // Map of id to data object
58 private final Map<String, T> map = new HashMap<>();
59 private final Prefix[] prefixes;
61 protected UniFiCache(final Prefix... prefixes) {
62 this.prefixes = prefixes;
69 public final @Nullable T get(final @Nullable String cid) {
70 final @Nullable T value;
72 if (cid != null && !cid.isBlank()) {
74 final String id = getId(cid);
77 logger.debug("Could not find an entry in the cache for id: '{}'", cid);
89 public @Nullable String getId(final String cid) {
91 for (final Prefix prefix : prefixes) {
92 final String key = key(prefix, cid);
94 if (mapToId.containsKey(key)) {
95 value = mapToId.get(key);
96 logger.trace("Cache HIT : '{}' -> {}", key, value);
99 logger.trace("Cache MISS : '{}'", key);
105 public final void putAll(final T @Nullable [] values) {
106 if (values != null) {
107 if (logger.isDebugEnabled()) {
108 logger.debug("Put #{} entries in {}: {}", values.length, getClass().getSimpleName(),
109 Stream.of(values).filter(Objects::nonNull).map(Object::toString)
110 .collect(Collectors.joining(System.lineSeparator() + " - ")));
112 Stream.of(values).filter(Objects::nonNull).forEach(value -> 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);