]> git.basschouten.com Git - openhab-addons.git/blob
f83f75d58bf0d28e74109f22c9300792d6ee22fa
[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.insteon.internal.device;
14
15 import java.io.IOException;
16 import java.io.InputStream;
17 import java.util.ArrayList;
18 import java.util.HashMap;
19 import java.util.List;
20 import java.util.Map;
21
22 import javax.xml.parsers.DocumentBuilder;
23 import javax.xml.parsers.DocumentBuilderFactory;
24 import javax.xml.parsers.ParserConfigurationException;
25
26 import org.eclipse.jdt.annotation.NonNullByDefault;
27 import org.eclipse.jdt.annotation.Nullable;
28 import org.openhab.binding.insteon.internal.utils.Utils;
29 import org.openhab.binding.insteon.internal.utils.Utils.ParsingException;
30 import org.openhab.core.library.types.DecimalType;
31 import org.openhab.core.library.types.IncreaseDecreaseType;
32 import org.openhab.core.library.types.OnOffType;
33 import org.openhab.core.library.types.PercentType;
34 import org.openhab.core.types.Command;
35 import org.w3c.dom.DOMException;
36 import org.w3c.dom.Document;
37 import org.w3c.dom.Element;
38 import org.w3c.dom.NamedNodeMap;
39 import org.w3c.dom.Node;
40 import org.w3c.dom.NodeList;
41 import org.xml.sax.SAXException;
42
43 /**
44  * Class that loads the device feature templates from an xml stream
45  *
46  * @author Daniel Pfrommer - Initial contribution
47  * @author Rob Nielsen - Port to openHAB 2 insteon binding
48  */
49 @NonNullByDefault
50 public class FeatureTemplateLoader {
51     public static List<FeatureTemplate> readTemplates(InputStream input) throws IOException, ParsingException {
52         List<FeatureTemplate> features = new ArrayList<>();
53         try {
54             DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
55             DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
56             // Parse it!
57             Document doc = dBuilder.parse(input);
58             doc.getDocumentElement().normalize();
59
60             Element root = doc.getDocumentElement();
61
62             NodeList nodes = root.getChildNodes();
63
64             for (int i = 0; i < nodes.getLength(); i++) {
65                 Node node = nodes.item(i);
66                 if (node.getNodeType() == Node.ELEMENT_NODE) {
67                     Element e = (Element) node;
68                     if (e.getTagName().equals("feature")) {
69                         features.add(parseFeature(e));
70                     }
71                 }
72             }
73         } catch (SAXException e) {
74             throw new ParsingException("Failed to parse XML!", e);
75         } catch (ParserConfigurationException e) {
76             throw new ParsingException("Got parser config exception! ", e);
77         }
78         return features;
79     }
80
81     private static FeatureTemplate parseFeature(Element e) throws ParsingException {
82         String name = e.getAttribute("name");
83         boolean statusFeature = e.getAttribute("statusFeature").equals("true");
84         FeatureTemplate feature = new FeatureTemplate(name, statusFeature, e.getAttribute("timeout"));
85
86         NodeList nodes = e.getChildNodes();
87
88         for (int i = 0; i < nodes.getLength(); i++) {
89             Node node = nodes.item(i);
90             if (node.getNodeType() == Node.ELEMENT_NODE) {
91                 Element child = (Element) node;
92                 if (child.getTagName().equals("message-handler")) {
93                     parseMessageHandler(child, feature);
94                 } else if (child.getTagName().equals("command-handler")) {
95                     parseCommandHandler(child, feature);
96                 } else if (child.getTagName().equals("message-dispatcher")) {
97                     parseMessageDispatcher(child, feature);
98                 } else if (child.getTagName().equals("poll-handler")) {
99                     parsePollHandler(child, feature);
100                 }
101             }
102         }
103
104         return feature;
105     }
106
107     private static HandlerEntry makeHandlerEntry(Element e) throws ParsingException {
108         String handler = e.getTextContent();
109         if (handler == null) {
110             throw new ParsingException("Could not find Handler for: " + e.getTextContent());
111         }
112
113         NamedNodeMap attributes = e.getAttributes();
114         Map<String, @Nullable String> params = new HashMap<>();
115         for (int i = 0; i < attributes.getLength(); i++) {
116             Node n = attributes.item(i);
117             params.put(n.getNodeName(), n.getNodeValue());
118         }
119         return new HandlerEntry(handler, params);
120     }
121
122     private static void parseMessageHandler(Element e, FeatureTemplate f) throws DOMException, ParsingException {
123         HandlerEntry he = makeHandlerEntry(e);
124         if (e.getAttribute("default").equals("true")) {
125             f.setDefaultMessageHandler(he);
126         } else {
127             String attr = e.getAttribute("cmd");
128             int command = (attr == null) ? 0 : Utils.from0xHexString(attr);
129             f.addMessageHandler(command, he);
130         }
131     }
132
133     private static void parseCommandHandler(Element e, FeatureTemplate f) throws ParsingException {
134         HandlerEntry he = makeHandlerEntry(e);
135         if (e.getAttribute("default").equals("true")) {
136             f.setDefaultCommandHandler(he);
137         } else {
138             Class<? extends Command> command = parseCommandClass(e.getAttribute("command"));
139             f.addCommandHandler(command, he);
140         }
141     }
142
143     private static void parseMessageDispatcher(Element e, FeatureTemplate f) throws DOMException, ParsingException {
144         HandlerEntry he = makeHandlerEntry(e);
145         f.setMessageDispatcher(he);
146     }
147
148     private static void parsePollHandler(Element e, FeatureTemplate f) throws ParsingException {
149         HandlerEntry he = makeHandlerEntry(e);
150         f.setPollHandler(he);
151     }
152
153     private static Class<? extends Command> parseCommandClass(String c) throws ParsingException {
154         if (c.equals("OnOffType")) {
155             return OnOffType.class;
156         } else if (c.equals("PercentType")) {
157             return PercentType.class;
158         } else if (c.equals("DecimalType")) {
159             return DecimalType.class;
160         } else if (c.equals("IncreaseDecreaseType")) {
161             return IncreaseDecreaseType.class;
162         } else {
163             throw new ParsingException("Unknown Command Type");
164         }
165     }
166 }