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.nest.internal.wwn.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.NonNull;
24 import org.eclipse.jdt.annotation.NonNullByDefault;
25 import org.eclipse.jdt.annotation.Nullable;
26 import org.openhab.binding.nest.internal.wwn.dto.WWNIdentifiable;
27 import org.openhab.binding.nest.internal.wwn.dto.WWNTopLevelData;
28 import org.openhab.binding.nest.internal.wwn.listener.WWNThingDataListener;
31 * Handles all Nest data updates through delegation to the {@link WWNUpdateHandler} for the respective data type.
33 * @author Wouter Born - Initial contribution
36 public class WWNCompositeUpdateHandler {
38 private final Supplier<Set<String>> presentNestIdsSupplier;
39 private final Map<Class<?>, WWNUpdateHandler<?>> updateHandlersMap = new ConcurrentHashMap<>();
41 public WWNCompositeUpdateHandler(Supplier<Set<String>> presentNestIdsSupplier) {
42 this.presentNestIdsSupplier = presentNestIdsSupplier;
45 public <T> boolean addListener(Class<T> dataClass, WWNThingDataListener<T> listener) {
46 return getOrCreateUpdateHandler(dataClass).addListener(listener);
49 public <T> boolean addListener(Class<T> dataClass, String nestId, WWNThingDataListener<T> listener) {
50 return getOrCreateUpdateHandler(dataClass).addListener(nestId, listener);
53 private Set<String> findMissingNestIds(Set<WWNIdentifiable> updates) {
54 Set<String> nestIds = updates.stream().map(u -> u.getId()).collect(Collectors.toSet());
55 Set<String> missingNestIds = presentNestIdsSupplier.get();
56 missingNestIds.removeAll(nestIds);
57 return missingNestIds;
60 public @Nullable <T> T getLastUpdate(Class<T> dataClass, String nestId) {
61 return getOrCreateUpdateHandler(dataClass).getLastUpdate(nestId);
64 public <T> List<T> getLastUpdates(Class<T> dataClass) {
65 return getOrCreateUpdateHandler(dataClass).getLastUpdates();
68 private Set<WWNIdentifiable> getNestUpdates(WWNTopLevelData data) {
69 Set<WWNIdentifiable> updates = new HashSet<>();
70 if (data.getDevices() != null) {
71 if (data.getDevices().getCameras() != null) {
72 updates.addAll(data.getDevices().getCameras().values());
74 if (data.getDevices().getSmokeCoAlarms() != null) {
75 updates.addAll(data.getDevices().getSmokeCoAlarms().values());
77 if (data.getDevices().getThermostats() != null) {
78 updates.addAll(data.getDevices().getThermostats().values());
81 if (data.getStructures() != null) {
82 updates.addAll(data.getStructures().values());
87 @SuppressWarnings("unchecked")
88 private <@NonNull T> WWNUpdateHandler<T> getOrCreateUpdateHandler(Class<T> dataClass) {
89 WWNUpdateHandler<T> handler = (WWNUpdateHandler<T>) updateHandlersMap.get(dataClass);
90 if (handler == null) {
91 handler = new WWNUpdateHandler<>();
92 updateHandlersMap.put(dataClass, handler);
97 @SuppressWarnings("unchecked")
98 public void handleUpdate(WWNTopLevelData data) {
99 Set<WWNIdentifiable> updates = getNestUpdates(data);
100 updates.forEach(update -> {
101 Class<WWNIdentifiable> updateClass = (Class<WWNIdentifiable>) update.getClass();
102 getOrCreateUpdateHandler(updateClass).handleUpdate(updateClass, update.getId(), update);
105 Set<String> missingNestIds = findMissingNestIds(updates);
106 if (!missingNestIds.isEmpty()) {
107 updateHandlersMap.values().forEach(handler -> {
108 handler.handleMissingNestIds(missingNestIds);
113 public <T> boolean removeListener(Class<T> dataClass, WWNThingDataListener<T> listener) {
114 return getOrCreateUpdateHandler(dataClass).removeListener(listener);
117 public <T> boolean removeListener(Class<T> dataClass, String nestId, WWNThingDataListener<T> listener) {
118 return getOrCreateUpdateHandler(dataClass).removeListener(nestId, listener);
121 public void resendLastUpdates() {
122 updateHandlersMap.values().forEach(handler -> {
123 handler.resendLastUpdates();