/**
* Copyright (c) 2010-2016 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.openhab.binding.zwave.internal.config;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Collections;
import java.util.List;
import org.osgi.framework.FrameworkUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.annotations.XStreamImplicit;
import com.thoughtworks.xstream.io.xml.StaxDriver;
/**
* Implements the top level functions for the XML product database This class
* includes helper functions to manipulate the database and facilitate access to
* the database.
*
* @author Chris Jackson
* @since 1.4.0
*
*/
public class ZWaveProductDatabase {
private static final Logger logger = LoggerFactory.getLogger(ZWaveProductDatabase.class);
ZWaveDbRoot database = null;
Languages language = Languages.ENGLISH;
ZWaveDbManufacturer selManufacturer = null;
ZWaveDbProduct selProduct = null;
ZWaveDbProductFile productFile = null;
String productVersion;
public ZWaveProductDatabase() {
loadDatabase();
}
/**
* Constructor for the product database
*
* @param Language
* defines the language in which all labels will be returned
*/
public ZWaveProductDatabase(Languages Language) {
language = Language;
loadDatabase();
}
/**
* Constructor for the product database
*
* @param Language
* defines the language in which all labels will be returned
*/
public ZWaveProductDatabase(String Language) {
language = Languages.fromString(Language);
loadDatabase();
}
private void loadDatabase() {
URL entry = FrameworkUtil.getBundle(ZWaveProductDatabase.class).getEntry("database/products.xml");
if (entry == null) {
database = null;
logger.error("Unable to load ZWave product database!");
return;
}
XStream xstream = new XStream(new StaxDriver());
xstream.alias("Manufacturers", ZWaveDbRoot.class);
xstream.alias("Manufacturer", ZWaveDbManufacturer.class);
xstream.alias("Product", ZWaveDbProduct.class);
xstream.alias("Reference", ZWaveDbProductReference.class);
xstream.processAnnotations(ZWaveDbRoot.class);
try {
// this.Manufacturer = (ZWaveDbManufacturer)
InputStream x = entry.openStream();
database = (ZWaveDbRoot) xstream.fromXML(x);
if (database == null) {
return;
}
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Loads the product file relating to the requested version.
*
* @param version the required device version
* @return filename of the product file
*/
private ZWaveDbProductFile LoadProductFile() {
// If the file is already loaded, then just return the class
if (productFile != null) {
return productFile;
}
// Have we selected a product?
if (selProduct == null) {
return null;
}
String cfgFile = selProduct.getConfigFile(productVersion);
if (cfgFile == null || cfgFile.isEmpty()) {
return null;
}
URL entry = FrameworkUtil.getBundle(ZWaveProductDatabase.class).getEntry("database/" + cfgFile);
if (entry == null) {
database = null;
logger.error("Unable to load ZWave product file: '{}'", cfgFile);
return null;
}
XStream xstream = new XStream(new StaxDriver());
xstream.alias("Product", ZWaveDbProductFile.class);
xstream.alias("Configuration", ZWaveDbProductFile.ZWaveDbConfiguration.class);
xstream.alias("Parameter", ZWaveDbConfigurationParameter.class);
xstream.alias("Item", ZWaveDbConfigurationListItem.class);
xstream.alias("Associations", ZWaveDbProductFile.ZWaveDbAssociation.class);
xstream.alias("Group", ZWaveDbAssociationGroup.class);
xstream.alias("CommandClass", ZWaveDbProductFile.ZWaveDbCommandClassList.class);
xstream.alias("Class", ZWaveDbCommandClass.class);
xstream.processAnnotations(ZWaveDbProductFile.class);
try {
// this.Manufacturer = (ZWaveDbManufacturer)
InputStream x = entry.openStream();
productFile = (ZWaveDbProductFile) xstream.fromXML(x);
} catch (IOException e) {
logger.error("Unable to load ZWave product file '{}' : {}", cfgFile, e.toString());
}
return productFile;
}
public List<ZWaveDbManufacturer> GetManufacturers() {
if (database == null || database.Manufacturer == null) {
return Collections.emptyList();
}
return database.Manufacturer;
}
public List<ZWaveDbProduct> GetProducts() {
if (selManufacturer == null) {
return Collections.emptyList();
}
return selManufacturer.Product;
}
/**
* Finds the manufacturer in the database.
*
* @param manufacturerId
* @return true if the manufacturer was found
*/
public boolean FindManufacturer(int manufacturerId) {
if (database == null || database.Manufacturer == null) {
return false;
}
selManufacturer = null;
selProduct = null;
productFile = null;
for (ZWaveDbManufacturer manufacturer : database.Manufacturer) {
if (manufacturer.Id == manufacturerId) {
selManufacturer = manufacturer;
return true;
}
}
return false;
}
/**
* Finds a product in the database
*
* @param manufacturerId
* The manufacturer ID
* @param productType
* The product type
* @param productId
* The product ID
* @return true if the product was found
*/
public boolean FindProduct(int manufacturerId, int productType, int productId, String version) {
if (FindManufacturer(manufacturerId) == false) {
return false;
}
return FindProduct(productType, productId, version);
}
/**
* Finds a product in the database. FindManufacturer must be called before
* this function.
*
* @param productType
* The product type
* @param productId
* The product ID
* @return true if the product was found
*/
public boolean FindProduct(int productType, int productId, String version) {
if (selManufacturer == null) {
return false;
}
productVersion = version;
for (ZWaveDbProduct product : selManufacturer.Product) {
for (ZWaveDbProductReference reference : product.Reference) {
if (reference.Type == productType && reference.Id == productId) {
selProduct = product;
return true;
}
}
}
return false;
}
/**
* Returns the manufacturer name. FindManufacturer or FindProduct must be
* called before this method.
*
* @return String with the manufacturer name, or null if not found.
*/
public String getManufacturerName() {
if (selManufacturer == null) {
return "";
} else {
return selManufacturer.Name;
}
}
/**
* Returns the manufacturer ID. FindManufacturer or FindProduct must be
* called before this method.
*
* @return Integer with the manufacturer ID, or null if not found.
*/
public Integer getManufacturerId() {
if (selManufacturer == null) {
return null;
} else {
return selManufacturer.Id;
}
}
/**
* Returns the product name. FindProduct must be called before this method.
*
* @return String with the product name, or null if not found.
*/
public String getProductName() {
if (selProduct == null) {
return "";
} else {
return selProduct.Model + " " + getLabel(selProduct.Label);
}
}
/**
* Returns the product model. FindProduct must be called before this method.
*
* @return String with the product model, or null if not found.
*/
public String getProductModel() {
if (selProduct == null) {
return null;
}
return selProduct.Model;
}
/**
* Returns the number of endpoints from the database. FindProduct must be
* called before this method.
*
* @return number of endpoints
*/
public Integer getProductEndpoints() {
if (selProduct == null) {
return null;
}
return 0;
}
/**
* Checks if a specific command class is implemented by the device.
* FindProduct must be called before this method.
*
* @param classNumber
* the class number to check
* @return true if the class is supported
*/
public boolean doesProductImplementCommandClass(Integer classNumber) {
if (LoadProductFile() == null) {
return false;
}
if (productFile.CommandClasses == null || productFile.CommandClasses.Class == null) {
return false;
}
for (ZWaveDbCommandClass iClass : productFile.CommandClasses.Class) {
if (iClass.Id.equals(classNumber)) {
return true;
}
}
return false;
}
/**
* Returns the command classes implemented by the device.
* FindProduct must be called before this method.
*
* @return true if the class is supported
*/
public List<ZWaveDbCommandClass> getProductCommandClasses() {
if (LoadProductFile() == null) {
return null;
}
if (productFile.CommandClasses == null) {
return null;
}
return productFile.CommandClasses.Class;
}
/**
* Returns the configuration parameters list. FindProduct must be called
* before this method.
*
* @return List of configuration parameters
*/
public List<ZWaveDbConfigurationParameter> getProductConfigParameters() {
if (LoadProductFile() == null) {
return Collections.emptyList();
}
return productFile.getConfiguration();
}
/**
* Returns the associations list. FindProduct must be called before this
* method.
*
* @return List of association groups
*/
public List<ZWaveDbAssociationGroup> getProductAssociationGroups() {
if (LoadProductFile() == null) {
return null;
}
return productFile.getAssociations();
}
private class ZWaveDbRoot {
@XStreamImplicit
List<ZWaveDbManufacturer> Manufacturer;
}
/**
* Helper function to find the label associated with the specified database
* language If no language is defined, or if the label cant be found in the
* specified language the english label will be returned.
*
* @param labelList
* A List defining the label
* @return String of the respective language
*/
public String getLabel(List<ZWaveDbLabel> labelList) {
if (labelList == null) {
return null;
}
for (ZWaveDbLabel label : labelList) {
if (label.Language == null) {
return label.Label;
}
if (label.Language.equals(language.toString())) {
return label.Label;
}
}
return null;
}
/**
* enum defining the languages used for the multilingual labels in the
* product database
*
*/
public enum Languages {
ENGLISH("en"),
GERMAN("de");
private String value;
private Languages(String value) {
this.value = value;
}
public static Languages fromString(String text) {
if (text != null) {
for (Languages c : Languages.values()) {
if (text.equalsIgnoreCase(c.value)) {
return c;
}
}
}
return ENGLISH;
}
@Override
public String toString() {
return this.value;
}
}
}