]> git.basschouten.com Git - openhab-addons.git/blob
bfcd098368cc3531b6d26c152c9a9c637127f49d
[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         if (!bridgeIndexToSerialNumber.containsKey(bridgeProductIndex.toInt())) {
90             return false;
91         }
92         return isRegistered(bridgeIndexToSerialNumber.get(bridgeProductIndex.toInt()));
93     }
94
95     public boolean register(VeluxProduct newProduct) {
96         logger.trace("register({}) called.", newProduct);
97         if (isRegistered(newProduct)) {
98             return false;
99         }
100         logger.trace("register() registering new product {}.", newProduct);
101
102         String uniqueIndex = newProduct.isV2() ? newProduct.getSerialNumber() : newProduct.getProductUniqueIndex();
103         logger.trace("register() registering by UniqueIndex {}", uniqueIndex);
104         existingProductsByUniqueIndex.put(uniqueIndex, newProduct);
105
106         logger.trace("register() registering by ProductBridgeIndex {}", newProduct.getBridgeProductIndex().toInt());
107         bridgeIndexToSerialNumber.put(newProduct.getBridgeProductIndex().toInt(), newProduct.getSerialNumber());
108
109         logger.trace("register() registering set of modifications by UniqueIndex {}", uniqueIndex);
110         modifiedProductsByUniqueIndex.put(uniqueIndex, newProduct);
111
112         memberCount++;
113         dirty = true;
114         return true;
115     }
116
117     public boolean update(ProductBridgeIndex bridgeProductIndex, int productState, int productPosition,
118             int productTarget) {
119         logger.debug("update(bridgeProductIndex={},productState={},productPosition={},productTarget={}) called.",
120                 bridgeProductIndex.toInt(), productState, productPosition, productTarget);
121         if (!isRegistered(bridgeProductIndex)) {
122             logger.warn("update() failed as actuator (with index {}) is not registered.", bridgeProductIndex.toInt());
123             return false;
124         }
125         VeluxProduct thisProduct = this.get(bridgeProductIndex);
126         if (thisProduct.setState(productState) || thisProduct.setCurrentPosition(productPosition)
127                 || thisProduct.setTarget(productTarget)) {
128             dirty = true;
129
130             String uniqueIndex = thisProduct.isV2() ? thisProduct.getSerialNumber()
131                     : thisProduct.getProductUniqueIndex();
132             logger.trace("update(): updating by UniqueIndex {}.", uniqueIndex);
133             existingProductsByUniqueIndex.replace(uniqueIndex, thisProduct);
134             modifiedProductsByUniqueIndex.put(uniqueIndex, thisProduct);
135         }
136         logger.trace("update() successfully finished (dirty={}).", dirty);
137         return true;
138     }
139
140     public boolean update(VeluxProduct currentProduct) {
141         logger.trace("update(currentProduct={}) called.", currentProduct);
142         return update(currentProduct.getBridgeProductIndex(), currentProduct.getState(),
143                 currentProduct.getCurrentPosition(), currentProduct.getTarget());
144     }
145
146     public VeluxProduct get(String productUniqueIndexOrSerialNumber) {
147         logger.trace("get({}) called.", productUniqueIndexOrSerialNumber);
148         if (!isRegistered(productUniqueIndexOrSerialNumber)) {
149             return VeluxProduct.UNKNOWN;
150         }
151         return existingProductsByUniqueIndex.get(productUniqueIndexOrSerialNumber);
152     }
153
154     public VeluxProduct get(ProductBridgeIndex bridgeProductIndex) {
155         logger.trace("get({}) called.", bridgeProductIndex);
156         if (!isRegistered(bridgeProductIndex)) {
157             return VeluxProduct.UNKNOWN;
158         }
159         return existingProductsByUniqueIndex.get(bridgeIndexToSerialNumber.get(bridgeProductIndex.toInt()));
160     }
161
162     public VeluxProduct[] values() {
163         return existingProductsByUniqueIndex.values().toArray(new VeluxProduct[0]);
164     }
165
166     public VeluxProduct[] valuesOfModified() {
167         return modifiedProductsByUniqueIndex.values().toArray(new VeluxProduct[0]);
168     }
169
170     public int getNoMembers() {
171         logger.trace("getNoMembers() returns {}.", memberCount);
172         return memberCount;
173     }
174
175     public boolean isDirty() {
176         logger.trace("isDirty() returns {}.", dirty);
177         return dirty;
178     }
179
180     public void resetDirtyFlag() {
181         logger.trace("resetDirtyFlag() called.");
182         modifiedProductsByUniqueIndex = new ConcurrentHashMap<>();
183         dirty = false;
184     }
185
186     public String toString(boolean showSummary, String delimiter) {
187         StringBuilder sb = new StringBuilder();
188
189         if (showSummary) {
190             sb.append(memberCount).append(" members: ");
191         }
192         for (VeluxProduct product : this.values()) {
193             sb.append(product).append(delimiter);
194         }
195         if (sb.lastIndexOf(delimiter) > 0) {
196             sb.deleteCharAt(sb.lastIndexOf(delimiter));
197         }
198         return sb.toString();
199     }
200
201     @Override
202     public String toString() {
203         return toString(true, VeluxBindingConstants.OUTPUT_VALUE_SEPARATOR);
204     }
205 }