]> git.basschouten.com Git - openhab-addons.git/blob
51c18f312541a373bff65a31cfe51bf6d4745ef7
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2020 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.velux.internal.things;
14
15 import java.util.Map;
16 import java.util.concurrent.ConcurrentHashMap;
17
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;
23
24 /**
25  * Combined set of product informations provided by the <B>Velux</B> bridge,
26  * which can be used for later interactions.
27  * <P>
28  * The following class access methods exist:
29  * <UL>
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>
37  * </UL>
38  *
39  * @see VeluxProduct
40  *
41  * @author Guenther Schreiner - initial contribution.
42  */
43 @NonNullByDefault
44 public class VeluxExistingProducts {
45     private final Logger logger = LoggerFactory.getLogger(VeluxExistingProducts.class);
46
47     // Type definitions, class-internal variables
48
49     private Map<String, VeluxProduct> existingProductsByUniqueIndex;
50     private Map<Integer, String> bridgeIndexToSerialNumber;
51     private Map<String, VeluxProduct> modifiedProductsByUniqueIndex;
52     private int memberCount;
53
54     /*
55      * Value to flag any changes towards the getter.
56      */
57     private boolean dirty;
58
59     // Constructor methods
60
61     public VeluxExistingProducts() {
62         logger.trace("VeluxExistingProducts(constructor) called.");
63         existingProductsByUniqueIndex = new ConcurrentHashMap<>();
64         bridgeIndexToSerialNumber = new ConcurrentHashMap<>();
65         modifiedProductsByUniqueIndex = new ConcurrentHashMap<>();
66         memberCount = 0;
67         dirty = true;
68         logger.trace("VeluxExistingProducts(constructor) done.");
69     }
70
71     // Class access methods
72
73     public boolean isRegistered(String productUniqueIndexOrSerialNumber) {
74         logger.trace("isRegistered(String {}) returns {}.", productUniqueIndexOrSerialNumber,
75                 existingProductsByUniqueIndex.containsKey(productUniqueIndexOrSerialNumber) ? "true" : "false");
76         return existingProductsByUniqueIndex.containsKey(productUniqueIndexOrSerialNumber);
77     }
78
79     public boolean isRegistered(VeluxProduct product) {
80         logger.trace("isRegistered(VeluxProduct {}) called.", product.toString());
81         if (product.isV2()) {
82             return isRegistered(product.getSerialNumber());
83         }
84         return isRegistered(product.getProductUniqueIndex());
85     }
86
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);
91     }
92
93     public boolean register(VeluxProduct newProduct) {
94         logger.trace("register({}) called.", newProduct);
95         if (isRegistered(newProduct)) {
96             return false;
97         }
98         logger.trace("register() registering new product {}.", newProduct);
99
100         String uniqueIndex = newProduct.isV2() ? newProduct.getSerialNumber() : newProduct.getProductUniqueIndex();
101         logger.trace("register() registering by UniqueIndex {}", uniqueIndex);
102         existingProductsByUniqueIndex.put(uniqueIndex, newProduct);
103
104         logger.trace("register() registering by ProductBridgeIndex {}", newProduct.getBridgeProductIndex().toInt());
105         bridgeIndexToSerialNumber.put(newProduct.getBridgeProductIndex().toInt(), newProduct.getSerialNumber());
106
107         logger.trace("register() registering set of modifications by UniqueIndex {}", uniqueIndex);
108         modifiedProductsByUniqueIndex.put(uniqueIndex, newProduct);
109
110         memberCount++;
111         dirty = true;
112         return true;
113     }
114
115     public boolean update(ProductBridgeIndex bridgeProductIndex, int productState, int productPosition,
116             int productTarget) {
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());
121             return false;
122         }
123         VeluxProduct thisProduct = this.get(bridgeProductIndex);
124         dirty |= thisProduct.setState(productState);
125         dirty |= thisProduct.setCurrentPosition(productPosition);
126         dirty |= thisProduct.setTarget(productTarget);
127         if (dirty) {
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);
133         }
134         logger.trace("update() successfully finished (dirty={}).", dirty);
135         return true;
136     }
137
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());
142     }
143
144     public VeluxProduct get(String productUniqueIndexOrSerialNumber) {
145         logger.trace("get({}) called.", productUniqueIndexOrSerialNumber);
146         if (!isRegistered(productUniqueIndexOrSerialNumber)) {
147             return VeluxProduct.UNKNOWN;
148         }
149         return existingProductsByUniqueIndex.getOrDefault(productUniqueIndexOrSerialNumber, VeluxProduct.UNKNOWN);
150     }
151
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;
157         }
158         return existingProductsByUniqueIndex.getOrDefault(serialNumber, VeluxProduct.UNKNOWN);
159     }
160
161     public VeluxProduct[] values() {
162         return existingProductsByUniqueIndex.values().toArray(new VeluxProduct[0]);
163     }
164
165     public VeluxProduct[] valuesOfModified() {
166         return modifiedProductsByUniqueIndex.values().toArray(new VeluxProduct[0]);
167     }
168
169     public int getNoMembers() {
170         logger.trace("getNoMembers() returns {}.", memberCount);
171         return memberCount;
172     }
173
174     public boolean isDirty() {
175         logger.trace("isDirty() returns {}.", dirty);
176         return dirty;
177     }
178
179     public void resetDirtyFlag() {
180         logger.trace("resetDirtyFlag() called.");
181         modifiedProductsByUniqueIndex = new ConcurrentHashMap<>();
182         dirty = false;
183     }
184
185     public String toString(boolean showSummary, String delimiter) {
186         StringBuilder sb = new StringBuilder();
187
188         if (showSummary) {
189             sb.append(memberCount).append(" members: ");
190         }
191         for (VeluxProduct product : this.values()) {
192             sb.append(product).append(delimiter);
193         }
194         if (sb.lastIndexOf(delimiter) > 0) {
195             sb.deleteCharAt(sb.lastIndexOf(delimiter));
196         }
197         return sb.toString();
198     }
199
200     @Override
201     public String toString() {
202         return toString(true, VeluxBindingConstants.OUTPUT_VALUE_SEPARATOR);
203     }
204 }