/** * Copyright (c) 2014-2017 by the respective copyright holders. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html */ package org.eclipse.smarthome.binding.digitalstrom.internal.lib.manager.impl; import java.util.Collections; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import org.eclipse.smarthome.binding.digitalstrom.internal.lib.manager.ConnectionManager; import org.eclipse.smarthome.binding.digitalstrom.internal.lib.manager.StructureManager; import org.eclipse.smarthome.binding.digitalstrom.internal.lib.serverConnection.impl.JSONResponseHandler; import org.eclipse.smarthome.binding.digitalstrom.internal.lib.structure.devices.Device; import org.eclipse.smarthome.binding.digitalstrom.internal.lib.structure.devices.deviceParameters.DSID; import com.google.gson.JsonArray; import com.google.gson.JsonObject; /** * The {@link StructureManagerImpl} is the implementation of the {@link StructureManager}. * * @author Michael Ochel - Initial contribution * @author Matthias Siegele - Initial contribution * */ public class StructureManagerImpl implements StructureManager { private Map<Integer, HashMap<Short, List<Device>>> zoneGroupDeviceMap; private Map<DSID, Device> deviceMap; private Map<String, DSID> dSUIDToDSIDMap; private Map<Integer, Object[]> zoneGroupIdNameMap = null; private Map<String, Object[]> zoneGroupNameIdMap = null; /** * Creates a new {@link StructureManagerImpl} with the {@link Device}s of the given referenceDeviceList. * * @param referenceDeviceList */ public StructureManagerImpl(List<Device> referenceDeviceList) { handleStructure(referenceDeviceList); } /** * Creates a new {@link StructureManagerImpl} without {@link Device}s. */ public StructureManagerImpl() { } private final String ZONE_GROUP_NAMES = "/json/property/query?query=/apartment/zones/*(ZoneID,name)/groups/*(group,name)"; @Override public boolean generateZoneGroupNames(ConnectionManager connectionManager) { if (connectionManager.checkConnection()) { String response = connectionManager.getHttpTransport() .execute(this.ZONE_GROUP_NAMES + "&token=" + connectionManager.getSessionToken()); if (response == null) { return false; } else { JsonObject responsJsonObj = JSONResponseHandler.toJsonObject(response); if (JSONResponseHandler.checkResponse(responsJsonObj)) { JsonObject resultJsonObj = JSONResponseHandler.getResultJsonObject(responsJsonObj); if (resultJsonObj.get("zones") instanceof JsonArray) { JsonArray zones = (JsonArray) resultJsonObj.get("zones"); if (this.zoneGroupIdNameMap == null) { this.zoneGroupIdNameMap = new HashMap<Integer, Object[]>(zones.size()); this.zoneGroupNameIdMap = new HashMap<String, Object[]>(zones.size()); } if (zones != null) { for (int i = 0; i < zones.size(); i++) { if (((JsonObject) zones.get(i)).get("groups") instanceof JsonArray) { JsonArray groups = (JsonArray) ((JsonObject) zones.get(i)).get("groups"); if (groups.size() != 0) { Object[] zoneIdNameGroups = new Object[2]; Object[] zoneNameIdGroups = new Object[2]; int zoneID = ((JsonObject) zones.get(i)).get("ZoneID").getAsInt(); String zoneName = ((JsonObject) zones.get(i)).get("name").getAsString(); zoneIdNameGroups[0] = zoneName; zoneNameIdGroups[0] = zoneID; HashMap<Short, String> groupIdNames = new HashMap<Short, String>(); HashMap<String, Short> groupNameIds = new HashMap<String, Short>(); for (int k = 0; k < groups.size(); k++) { short groupID = ((JsonObject) groups.get(k)).get("group").getAsShort(); String groupName = ((JsonObject) groups.get(k)).get("name").getAsString(); groupIdNames.put(groupID, groupName); groupNameIds.put(groupName, groupID); } zoneIdNameGroups[1] = groupIdNames; zoneNameIdGroups[1] = groupNameIds; this.zoneGroupIdNameMap.put(zoneID, zoneIdNameGroups); this.zoneGroupNameIdMap.put(zoneName, zoneNameIdGroups); } } } } } } } } return true; } @Override public String getZoneName(int zoneID) { if (this.zoneGroupIdNameMap == null) { return null; } return this.zoneGroupIdNameMap.get(zoneID) != null ? (String) this.zoneGroupIdNameMap.get(zoneID)[0] : null; } @Override @SuppressWarnings("unchecked") public String getZoneGroupName(int zoneID, short groupID) { if (this.zoneGroupIdNameMap == null) { return null; } if (this.zoneGroupIdNameMap.get(zoneID) != null) { if (this.zoneGroupIdNameMap.get(zoneID)[1] != null) { if (((HashMap<Short, String>) this.zoneGroupIdNameMap.get(zoneID)[1]).get(groupID) != null) { return ((HashMap<Short, String>) this.zoneGroupIdNameMap.get(zoneID)[1]).get(groupID); } } } return null; } @Override public int getZoneId(String zoneName) { if (this.zoneGroupNameIdMap == null) { return -1; } return this.zoneGroupNameIdMap.get(zoneName) != null ? (int) this.zoneGroupNameIdMap.get(zoneName)[0] : -1; } @Override public boolean checkZoneID(int zoneID) { return this.getGroupsFromZoneX(zoneID) != null; } @Override public boolean checkZoneGroupID(int zoneID, short groupID) { return this.getGroupsFromZoneX(zoneID) != null ? (this.getGroupsFromZoneX(zoneID).get(groupID) != null) : false; } @Override @SuppressWarnings("unchecked") public short getZoneGroupId(String zoneName, String groupName) { if (this.zoneGroupNameIdMap == null) { return -1; } if (this.zoneGroupNameIdMap.get(zoneName) != null) { if (this.zoneGroupNameIdMap.get(zoneName)[1] != null) { if (((HashMap<Short, String>) this.zoneGroupNameIdMap.get(zoneName)[1]).get(groupName) != null) { return ((HashMap<String, Short>) this.zoneGroupNameIdMap.get(zoneName)[1]).get(groupName); } } } return -1; } @Override public Map<DSID, Device> getDeviceMap() { return this.deviceMap != null ? new HashMap<DSID, Device>(this.deviceMap) : new HashMap<DSID, Device>(); } private void putDeviceToHashMap(Device device) { if (deviceMap == null) { deviceMap = Collections.synchronizedMap(new HashMap<DSID, Device>()); // deviceList.size() } if (dSUIDToDSIDMap == null) { dSUIDToDSIDMap = Collections.synchronizedMap(new HashMap<String, DSID>()); // deviceList.size() } if (device.getDSID() != null) { deviceMap.put(device.getDSID(), device); dSUIDToDSIDMap.put(device.getDSUID(), device.getDSID()); } } /** * This method build the digitalSTROM structure as an {@link HashMap} with the zone id as key * and an {@link HashMap} as value. This {@link HashMap} has the group id as key and a {@link List} * with all digitalSTROM {@link Device}s.<br> * <br> * <b>Note:</b> the zone id 0 is the broadcast address and the group id 0 too. */ private void handleStructure(List<Device> deviceList) { HashMap<Short, List<Device>> groupXHashMap = new HashMap<Short, List<Device>>(); groupXHashMap = new HashMap<Short, List<Device>>(); groupXHashMap.put((short) 0, deviceList); if (this.zoneGroupDeviceMap == null) { zoneGroupDeviceMap = Collections.synchronizedMap(new HashMap<Integer, HashMap<Short, List<Device>>>()); } this.zoneGroupDeviceMap.put(0, groupXHashMap); for (Device device : deviceList) { addDeviceToStructure(device); } } @Override public Map<DSID, Device> getDeviceHashMapReference() { return this.deviceMap; } @Override public Map<Integer, HashMap<Short, List<Device>>> getStructureReference() { return this.zoneGroupDeviceMap; } @Override public HashMap<Short, List<Device>> getGroupsFromZoneX(int zoneID) { return this.zoneGroupDeviceMap == null ? null : this.zoneGroupDeviceMap.get(zoneID); } @Override public List<Device> getReferenceDeviceListFromZoneXGroupX(int zoneID, short groupID) { return getGroupsFromZoneX(zoneID) == null ? null : this.zoneGroupDeviceMap.get(zoneID).get(groupID); } @Override public Device getDeviceByDSID(String dSID) { return getDeviceByDSID(new DSID(dSID)); } @Override public Device getDeviceByDSID(DSID dSID) { return this.zoneGroupDeviceMap == null ? null : this.deviceMap.get(dSID); } @Override public Device getDeviceByDSUID(String dSUID) { if (this.deviceMap != null && this.dSUIDToDSIDMap != null) { return this.dSUIDToDSIDMap.get(dSUID) == null ? null : this.getDeviceByDSID(this.dSUIDToDSIDMap.get(dSUID)); } return null; } @Override public void updateDevice(int oldZone, List<Short> oldGroups, Device device) { if (oldZone == -1) { oldZone = device.getZoneId(); } deleteDevice(oldZone, oldGroups, device); addDeviceToStructure(device); } @Override public void updateDevice(Device device) { if (device != null) { int oldZoneID = -1; List<Short> oldGroups = null; Device internalDevice = this.getDeviceByDSID(device.getDSID()); if (internalDevice != null) { if (device.getZoneId() != internalDevice.getZoneId()) { oldZoneID = internalDevice.getZoneId(); internalDevice.setZoneId(device.getZoneId()); } if (!internalDevice.getGroups().equals(device.getGroups())) { oldGroups = internalDevice.getGroups(); internalDevice.setGroups(device.getGroups()); } if (deleteDevice(oldZoneID, oldGroups, internalDevice)) { addDeviceToStructure(internalDevice); } } } } @Override public void deleteDevice(Device device) { dSUIDToDSIDMap.remove(device.getDSUID()); deviceMap.remove(device.getDSID()); deleteDevice(device.getZoneId(), device.getGroups(), device); } private boolean deleteDevice(int zoneID, List<Short> groups, Device device) { if (groups != null || zoneID >= 0) { if (groups == null) { groups = device.getGroups(); } if (zoneID == -1) { zoneID = device.getZoneId(); } for (Short groupID : groups) { List<Device> deviceList = getReferenceDeviceListFromZoneXGroupX(zoneID, groupID); if (deviceList != null) { deviceList.remove(device); } deviceList = getReferenceDeviceListFromZoneXGroupX(0, groupID); if (deviceList != null) { deviceList.remove(device); } } return true; } return false; } @Override public void addDeviceToStructure(Device device) { putDeviceToHashMap(device); addDevicetoZoneXGroupX(0, (short) 0, device); int zoneID = device.getZoneId(); addDevicetoZoneXGroupX(zoneID, (short) 0, device); for (Short groupID : device.getGroups()) { addDevicetoZoneXGroupX(zoneID, groupID, device); if (groupID <= 16) { addDevicetoZoneXGroupX(0, groupID, device); } } } private void addDevicetoZoneXGroupX(int zoneID, short groupID, Device device) { if (zoneGroupDeviceMap == null) { zoneGroupDeviceMap = Collections.synchronizedMap(new HashMap<Integer, HashMap<Short, List<Device>>>()); } HashMap<Short, List<Device>> groupXHashMap = this.zoneGroupDeviceMap.get(zoneID); if (groupXHashMap == null) { groupXHashMap = new HashMap<Short, List<Device>>(); this.zoneGroupDeviceMap.put(zoneID, groupXHashMap); } List<Device> groupDeviceList = groupXHashMap.get(groupID); if (groupDeviceList == null) { groupDeviceList = new LinkedList<Device>(); groupDeviceList.add(device); groupXHashMap.put(groupID, groupDeviceList); } else { if (!groupDeviceList.contains(device)) { groupDeviceList.add(device); } } } @Override public Set<Integer> getZoneIDs() { return this.zoneGroupDeviceMap != null ? this.zoneGroupDeviceMap.keySet() : null; } }