2 * Copyright (c) 2010-2020 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.velux.internal.things;
16 import java.util.concurrent.ConcurrentHashMap;
18 import org.eclipse.jdt.annotation.NonNullByDefault;
19 import org.openhab.binding.velux.internal.VeluxBindingConstants;
20 import org.openhab.binding.velux.internal.things.VeluxProduct.ProductBridgeIndex;
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
25 * Combined set of product informations provided by the <B>Velux</B> bridge,
26 * which can be used for later interactions.
28 * The following class access methods exist:
30 * <LI>{@link VeluxExistingProducts#isRegistered} for querying existence of a {@link VeluxProduct},</LI>
31 * <LI>{@link VeluxExistingProducts#register} for storing a {@link VeluxProduct},</LI>
32 * <LI>{@link VeluxExistingProducts#update} for updating/storing of a {@link VeluxProduct},</LI>
33 * <LI>{@link VeluxExistingProducts#get} for retrieval of a {@link VeluxProduct},</LI>
34 * <LI>{@link VeluxExistingProducts#values} for retrieval of all {@link VeluxProduct}s,</LI>
35 * <LI>{@link VeluxExistingProducts#getNoMembers} for retrieval of the number of all {@link VeluxProduct}s,</LI>
36 * <LI>{@link VeluxExistingProducts#toString} for a descriptive string representation.</LI>
41 * @author Guenther Schreiner - initial contribution.
44 public class VeluxExistingProducts {
45 private final Logger logger = LoggerFactory.getLogger(VeluxExistingProducts.class);
47 // Type definitions, class-internal variables
49 private Map<String, VeluxProduct> existingProductsByUniqueIndex;
50 private Map<Integer, String> bridgeIndexToSerialNumber;
51 private Map<String, VeluxProduct> modifiedProductsByUniqueIndex;
52 private int memberCount;
55 * Value to flag any changes towards the getter.
57 private boolean dirty;
59 // Constructor methods
61 public VeluxExistingProducts() {
62 logger.trace("VeluxExistingProducts(constructor) called.");
63 existingProductsByUniqueIndex = new ConcurrentHashMap<>();
64 bridgeIndexToSerialNumber = new ConcurrentHashMap<>();
65 modifiedProductsByUniqueIndex = new ConcurrentHashMap<>();
68 logger.trace("VeluxExistingProducts(constructor) done.");
71 // Class access methods
73 public boolean isRegistered(String productUniqueIndexOrSerialNumber) {
74 logger.trace("isRegistered(String {}) returns {}.", productUniqueIndexOrSerialNumber,
75 existingProductsByUniqueIndex.containsKey(productUniqueIndexOrSerialNumber) ? "true" : "false");
76 return existingProductsByUniqueIndex.containsKey(productUniqueIndexOrSerialNumber);
79 public boolean isRegistered(VeluxProduct product) {
80 logger.trace("isRegistered(VeluxProduct {}) called.", product.toString());
82 return isRegistered(product.getSerialNumber());
84 return isRegistered(product.getProductUniqueIndex());
87 public boolean isRegistered(ProductBridgeIndex bridgeProductIndex) {
88 logger.trace("isRegisteredProductBridgeIndex {}) called.", bridgeProductIndex.toString());
89 String serialNumber = bridgeIndexToSerialNumber.get(bridgeProductIndex.toInt());
90 return serialNumber != null && isRegistered(serialNumber);
93 public boolean register(VeluxProduct newProduct) {
94 logger.trace("register({}) called.", newProduct);
95 if (isRegistered(newProduct)) {
98 logger.trace("register() registering new product {}.", newProduct);
100 String uniqueIndex = newProduct.isV2() ? newProduct.getSerialNumber() : newProduct.getProductUniqueIndex();
101 logger.trace("register() registering by UniqueIndex {}", uniqueIndex);
102 existingProductsByUniqueIndex.put(uniqueIndex, newProduct);
104 logger.trace("register() registering by ProductBridgeIndex {}", newProduct.getBridgeProductIndex().toInt());
105 bridgeIndexToSerialNumber.put(newProduct.getBridgeProductIndex().toInt(), newProduct.getSerialNumber());
107 logger.trace("register() registering set of modifications by UniqueIndex {}", uniqueIndex);
108 modifiedProductsByUniqueIndex.put(uniqueIndex, newProduct);
115 public boolean update(ProductBridgeIndex bridgeProductIndex, int productState, int productPosition,
117 logger.debug("update(bridgeProductIndex={},productState={},productPosition={},productTarget={}) called.",
118 bridgeProductIndex.toInt(), productState, productPosition, productTarget);
119 if (!isRegistered(bridgeProductIndex)) {
120 logger.warn("update() failed as actuator (with index {}) is not registered.", bridgeProductIndex.toInt());
123 VeluxProduct thisProduct = this.get(bridgeProductIndex);
124 dirty |= thisProduct.setState(productState);
125 dirty |= thisProduct.setCurrentPosition(productPosition);
126 dirty |= thisProduct.setTarget(productTarget);
128 String uniqueIndex = thisProduct.isV2() ? thisProduct.getSerialNumber()
129 : thisProduct.getProductUniqueIndex();
130 logger.trace("update(): updating by UniqueIndex {}.", uniqueIndex);
131 existingProductsByUniqueIndex.replace(uniqueIndex, thisProduct);
132 modifiedProductsByUniqueIndex.put(uniqueIndex, thisProduct);
134 logger.trace("update() successfully finished (dirty={}).", dirty);
138 public boolean update(VeluxProduct currentProduct) {
139 logger.trace("update(currentProduct={}) called.", currentProduct);
140 return update(currentProduct.getBridgeProductIndex(), currentProduct.getState(),
141 currentProduct.getCurrentPosition(), currentProduct.getTarget());
144 public VeluxProduct get(String productUniqueIndexOrSerialNumber) {
145 logger.trace("get({}) called.", productUniqueIndexOrSerialNumber);
146 if (!isRegistered(productUniqueIndexOrSerialNumber)) {
147 return VeluxProduct.UNKNOWN;
149 return existingProductsByUniqueIndex.getOrDefault(productUniqueIndexOrSerialNumber, VeluxProduct.UNKNOWN);
152 public VeluxProduct get(ProductBridgeIndex bridgeProductIndex) {
153 logger.trace("get({}) called.", bridgeProductIndex);
154 String serialNumber = bridgeIndexToSerialNumber.get(bridgeProductIndex.toInt());
155 if (!isRegistered(bridgeProductIndex) || serialNumber == null) {
156 return VeluxProduct.UNKNOWN;
158 return existingProductsByUniqueIndex.getOrDefault(serialNumber, VeluxProduct.UNKNOWN);
161 public VeluxProduct[] values() {
162 return existingProductsByUniqueIndex.values().toArray(new VeluxProduct[0]);
165 public VeluxProduct[] valuesOfModified() {
166 return modifiedProductsByUniqueIndex.values().toArray(new VeluxProduct[0]);
169 public int getNoMembers() {
170 logger.trace("getNoMembers() returns {}.", memberCount);
174 public boolean isDirty() {
175 logger.trace("isDirty() returns {}.", dirty);
179 public void resetDirtyFlag() {
180 logger.trace("resetDirtyFlag() called.");
181 modifiedProductsByUniqueIndex = new ConcurrentHashMap<>();
185 public String toString(boolean showSummary, String delimiter) {
186 StringBuilder sb = new StringBuilder();
189 sb.append(memberCount).append(" members: ");
191 for (VeluxProduct product : this.values()) {
192 sb.append(product).append(delimiter);
194 if (sb.lastIndexOf(delimiter) > 0) {
195 sb.deleteCharAt(sb.lastIndexOf(delimiter));
197 return sb.toString();
201 public String toString() {
202 return toString(true, VeluxBindingConstants.OUTPUT_VALUE_SEPARATOR);