2 * Copyright (c) 2010-2021 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.nest.internal.update;
15 import java.util.HashSet;
16 import java.util.List;
19 import java.util.concurrent.ConcurrentHashMap;
20 import java.util.function.Supplier;
21 import java.util.stream.Collectors;
23 import org.eclipse.jdt.annotation.NonNullByDefault;
24 import org.eclipse.jdt.annotation.Nullable;
25 import org.openhab.binding.nest.internal.data.NestIdentifiable;
26 import org.openhab.binding.nest.internal.data.TopLevelData;
27 import org.openhab.binding.nest.internal.listener.NestThingDataListener;
30 * Handles all Nest data updates through delegation to the {@link NestUpdateHandler} for the respective data type.
32 * @author Wouter Born - Initial contribution
35 public class NestCompositeUpdateHandler {
37 private final Supplier<Set<String>> presentNestIdsSupplier;
38 private final Map<Class<?>, NestUpdateHandler<?>> updateHandlersMap = new ConcurrentHashMap<>();
40 public NestCompositeUpdateHandler(Supplier<Set<String>> presentNestIdsSupplier) {
41 this.presentNestIdsSupplier = presentNestIdsSupplier;
44 public <T> boolean addListener(Class<T> dataClass, NestThingDataListener<T> listener) {
45 return getOrCreateUpdateHandler(dataClass).addListener(listener);
48 public <T> boolean addListener(Class<T> dataClass, String nestId, NestThingDataListener<T> listener) {
49 return getOrCreateUpdateHandler(dataClass).addListener(nestId, listener);
52 private Set<String> findMissingNestIds(Set<NestIdentifiable> updates) {
53 Set<String> nestIds = updates.stream().map(u -> u.getId()).collect(Collectors.toSet());
54 Set<String> missingNestIds = presentNestIdsSupplier.get();
55 missingNestIds.removeAll(nestIds);
56 return missingNestIds;
59 public @Nullable <T> T getLastUpdate(Class<T> dataClass, String nestId) {
60 return getOrCreateUpdateHandler(dataClass).getLastUpdate(nestId);
63 public <T> List<T> getLastUpdates(Class<T> dataClass) {
64 return getOrCreateUpdateHandler(dataClass).getLastUpdates();
67 private Set<NestIdentifiable> getNestUpdates(TopLevelData data) {
68 Set<NestIdentifiable> updates = new HashSet<>();
69 if (data.getDevices() != null) {
70 if (data.getDevices().getCameras() != null) {
71 updates.addAll(data.getDevices().getCameras().values());
73 if (data.getDevices().getSmokeCoAlarms() != null) {
74 updates.addAll(data.getDevices().getSmokeCoAlarms().values());
76 if (data.getDevices().getThermostats() != null) {
77 updates.addAll(data.getDevices().getThermostats().values());
80 if (data.getStructures() != null) {
81 updates.addAll(data.getStructures().values());
86 @SuppressWarnings("unchecked")
87 private <T> NestUpdateHandler<T> getOrCreateUpdateHandler(Class<T> dataClass) {
88 NestUpdateHandler<T> handler = (NestUpdateHandler<T>) updateHandlersMap.get(dataClass);
89 if (handler == null) {
90 handler = new NestUpdateHandler<>();
91 updateHandlersMap.put(dataClass, handler);
96 @SuppressWarnings("unchecked")
97 public void handleUpdate(TopLevelData data) {
98 Set<NestIdentifiable> updates = getNestUpdates(data);
99 updates.forEach(update -> {
100 Class<NestIdentifiable> updateClass = (Class<NestIdentifiable>) update.getClass();
101 getOrCreateUpdateHandler(updateClass).handleUpdate(updateClass, update.getId(), update);
104 Set<String> missingNestIds = findMissingNestIds(updates);
105 if (!missingNestIds.isEmpty()) {
106 updateHandlersMap.values().forEach(handler -> {
107 handler.handleMissingNestIds(missingNestIds);
112 public <T> boolean removeListener(Class<T> dataClass, NestThingDataListener<T> listener) {
113 return getOrCreateUpdateHandler(dataClass).removeListener(listener);
116 public <T> boolean removeListener(Class<T> dataClass, String nestId, NestThingDataListener<T> listener) {
117 return getOrCreateUpdateHandler(dataClass).removeListener(nestId, listener);
120 public void resendLastUpdates() {
121 updateHandlersMap.values().forEach(handler -> {
122 handler.resendLastUpdates();