]> git.basschouten.com Git - openhab-addons.git/blob
50a468ee232aab9bdf0075d4430b9de0c8d5bbd1
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2022 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
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
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.unifi.internal.api.cache;
14
15 import java.util.Collection;
16 import java.util.HashMap;
17 import java.util.Locale;
18 import java.util.Map;
19 import java.util.stream.Collectors;
20
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;
26
27 /**
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.
31  *
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.
34  *
35  * @author Matthew Bowman - Initial contribution
36  * @author Hilbrand Bouwkamp - Moved generic code into this class
37  */
38 @NonNullByDefault
39 abstract class UniFiCache<T extends @Nullable HasId> {
40
41     public enum Prefix {
42         ALIAS,
43         DESC,
44         HOSTNAME,
45         ID,
46         IP,
47         MAC,
48         NAME;
49     }
50
51     private static final String SEPARATOR = ":";
52
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;
59
60     protected UniFiCache(final Prefix... prefixes) {
61         this.prefixes = prefixes;
62     }
63
64     public void clear() {
65         map.clear();
66     }
67
68     public final @Nullable T get(final @Nullable String cid) {
69         final @Nullable T value;
70
71         if (cid != null && !cid.isBlank()) {
72             synchronized (this) {
73                 final String id = getId(cid);
74
75                 if (id == null) {
76                     logger.debug("Could not find an entry in the cache for id: '{}'", cid);
77                     value = null;
78                 } else {
79                     value = map.get(id);
80                 }
81             }
82         } else {
83             value = null;
84         }
85         return value;
86     }
87
88     public @Nullable String getId(final String cid) {
89         String value = null;
90         for (final Prefix prefix : prefixes) {
91             final String key = key(prefix, cid);
92
93             if (mapToId.containsKey(key)) {
94                 value = mapToId.get(key);
95                 logger.trace("Cache HIT : '{}' -> {}", key, value);
96                 break;
97             } else {
98                 logger.trace("Cache MISS : '{}'", key);
99             }
100         }
101         return value;
102     }
103
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) {
109                 if (value != null) {
110                     put(value.getId(), value);
111                 }
112             }
113         }
114     }
115
116     public final void put(final String id, final T value) {
117         for (final Prefix prefix : prefixes) {
118             final String suffix = getSuffix(value, prefix);
119
120             if (suffix != null && !suffix.isBlank()) {
121                 mapToId.put(key(prefix, suffix), id);
122             }
123         }
124         map.put(id, value);
125     }
126
127     private static String key(final Prefix prefix, final String suffix) {
128         return prefix.name() + SEPARATOR + suffix.replace(":", "").toLowerCase(Locale.ROOT);
129     }
130
131     public final Collection<T> values() {
132         return map.values().stream().distinct().collect(Collectors.toList());
133     }
134
135     protected abstract @Nullable String getSuffix(T value, Prefix prefix);
136
137     private static Object lazyFormatAsList(final Object[] arr) {
138         return new Object() {
139
140             @Override
141             public String toString() {
142                 String value = "";
143                 for (final Object o : arr) {
144                     value += "\n - " + o.toString();
145                 }
146                 return value;
147             }
148         };
149     }
150 }