/**
* 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.insteonplm.internal.device;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.openhab.binding.insteonplm.internal.utils.Utils;
import org.openhab.binding.insteonplm.internal.utils.Utils.ParsingException;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.IncreaseDecreaseType;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.PercentType;
import org.openhab.core.types.Command;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
/**
* Class that loads the device feature templates from an xml stream
*
* @author Daniel Pfrommer
* @since 1.6.0
*/
public class FeatureTemplateLoader {
public static ArrayList<FeatureTemplate> s_readTemplates(InputStream input) throws IOException, ParsingException {
ArrayList<FeatureTemplate> features = new ArrayList<FeatureTemplate>();
try {
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
// Parse it!
Document doc = dBuilder.parse(input);
doc.getDocumentElement().normalize();
Element root = doc.getDocumentElement();
NodeList nodes = root.getChildNodes();
for (int i = 0; i < nodes.getLength(); i++) {
Node node = nodes.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element e = (Element) node;
if (e.getTagName().equals("feature")) {
features.add(s_parseFeature(e));
}
}
}
} catch (SAXException e) {
throw new ParsingException("Failed to parse XML!", e);
} catch (ParserConfigurationException e) {
throw new ParsingException("Got parser config exception! ", e);
}
return features;
}
private static FeatureTemplate s_parseFeature(Element e) throws ParsingException {
String name = e.getAttribute("name");
boolean statusFeature = e.getAttribute("statusFeature").equals("true");
FeatureTemplate feature = new FeatureTemplate();
feature.setName(name);
feature.setStatusFeature(statusFeature);
feature.setTimeout(e.getAttribute("timeout"));
NodeList nodes = e.getChildNodes();
for (int i = 0; i < nodes.getLength(); i++) {
Node node = nodes.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element child = (Element) node;
if (child.getTagName().equals("message-handler")) {
s_parseMessageHandler(child, feature);
} else if (child.getTagName().equals("command-handler")) {
s_parseCommandHandler(child, feature);
} else if (child.getTagName().equals("message-dispatcher")) {
s_parseMessageDispatcher(child, feature);
} else if (child.getTagName().equals("poll-handler")) {
s_parsePollHandler(child, feature);
}
}
}
return feature;
}
private static HandlerEntry s_makeHandlerEntry(Element e) throws ParsingException {
String handler = e.getTextContent();
if (handler == null) {
throw new ParsingException("Could not find Handler for: " + e.getTextContent());
}
NamedNodeMap attributes = e.getAttributes();
HashMap<String, String> params = new HashMap<String, String>();
for (int i = 0; i < attributes.getLength(); i++) {
Node n = attributes.item(i);
params.put(n.getNodeName(), n.getNodeValue());
}
return new HandlerEntry(handler, params);
}
private static void s_parseMessageHandler(Element e, FeatureTemplate f) throws DOMException, ParsingException {
HandlerEntry he = s_makeHandlerEntry(e);
if (e.getAttribute("default").equals("true")) {
f.setDefaultMessageHandler(he);
} else {
String attr = e.getAttribute("cmd");
int command = (attr == null) ? 0 : Utils.from0xHexString(attr);
f.addMessageHandler(command, he);
}
}
private static void s_parseCommandHandler(Element e, FeatureTemplate f) throws ParsingException {
HandlerEntry he = s_makeHandlerEntry(e);
if (e.getAttribute("default").equals("true")) {
f.setDefaultCommandHandler(he);
} else {
Class<? extends Command> command = s_parseCommandClass(e.getAttribute("command"));
f.addCommandHandler(command, he);
}
}
private static void s_parseMessageDispatcher(Element e, FeatureTemplate f) throws DOMException, ParsingException {
HandlerEntry he = s_makeHandlerEntry(e);
f.setMessageDispatcher(he);
if (he.getName() == null) {
throw new ParsingException("Could not find MessageDispatcher for: " + e.getTextContent());
}
}
private static void s_parsePollHandler(Element e, FeatureTemplate f) throws ParsingException {
HandlerEntry he = s_makeHandlerEntry(e);
f.setPollHandler(he);
}
private static Class<? extends Command> s_parseCommandClass(String c) throws ParsingException {
if (c.equals("OnOffType")) {
return OnOffType.class;
} else if (c.equals("PercentType")) {
return PercentType.class;
} else if (c.equals("DecimalType")) {
return DecimalType.class;
} else if (c.equals("IncreaseDecreaseType")) {
return IncreaseDecreaseType.class;
} else {
throw new ParsingException("Unknown Command Type");
}
}
public static void main(String[] args) throws Exception {
File f = new File(System.getProperty("user.home")
+ "/workspace/openhab/bundles/binding/org.openhab.binding.insteonplm/src/main/resources/device_features.xml");
InputStream s = new FileInputStream(f);
ArrayList<FeatureTemplate> features = s_readTemplates(s);
for (FeatureTemplate feature : features) {
System.out.println(feature);
System.out.println(
"\tPOLL: " + feature.getPollHandler() + "\n\tDISPATCH: " + feature.getDispatcher().getName());
System.out.println(
"\tDCH: " + feature.getDefaultCommandHandler() + "\n\tDMH: " + feature.getDefaultMessageHandler());
System.out.println("\tMSG HANDLERS: " + feature.getMessageHandlers().size());
System.out.println("\tCMD HANDLERS: " + feature.getCommandHandlers());
}
}
}