]> git.basschouten.com Git - openhab-addons.git/blob
691fe45e73c1467a3418aa3ee9dc386892d5abcb
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2024 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.bluetooth.govee.internal.readme;
14
15 import java.io.FileInputStream;
16 import java.io.StringWriter;
17 import java.util.ArrayList;
18 import java.util.Arrays;
19 import java.util.List;
20 import java.util.stream.Collectors;
21 import java.util.stream.Stream;
22
23 import javax.xml.parsers.DocumentBuilder;
24 import javax.xml.parsers.DocumentBuilderFactory;
25 import javax.xml.xpath.XPath;
26 import javax.xml.xpath.XPathConstants;
27 import javax.xml.xpath.XPathExpression;
28 import javax.xml.xpath.XPathFactory;
29
30 import org.eclipse.jdt.annotation.NonNullByDefault;
31 import org.eclipse.jdt.annotation.Nullable;
32 import org.openhab.binding.bluetooth.govee.internal.GoveeModel;
33 import org.w3c.dom.Document;
34 import org.w3c.dom.Node;
35 import org.w3c.dom.NodeList;
36
37 /**
38  * @author Connor Petty - Initial contribution
39  *
40  */
41 @NonNullByDefault
42 public class ThingTypeTableGenerator {
43
44     public static void main(String[] args) throws Exception {
45         FileInputStream fileIS = new FileInputStream("src/main/resources/OH-INF/thing/thing-types.xml");
46         DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
47         DocumentBuilder builder = builderFactory.newDocumentBuilder();
48         Document xmlDocument = builder.parse(fileIS);
49         XPath xPath = XPathFactory.newInstance().newXPath();
50         String expression = "/*[local-name()='thing-descriptions']/thing-type";
51         XPathExpression labelExpression = xPath.compile("label/text()");
52         XPathExpression descriptionExpression = xPath.compile("description/text()");
53
54         NodeList nodeList = (NodeList) xPath.compile(expression).evaluate(xmlDocument, XPathConstants.NODESET);
55
56         List<ThingTypeData> thingTypeDataList = new ArrayList<>();
57
58         for (int i = 0; i < nodeList.getLength(); i++) {
59             Node node = nodeList.item(i);
60             ThingTypeData data = new ThingTypeData();
61
62             data.id = node.getAttributes().getNamedItem("id").getTextContent();
63             data.label = (String) labelExpression.evaluate(node, XPathConstants.STRING);
64             data.description = (String) descriptionExpression.evaluate(node, XPathConstants.STRING);
65
66             thingTypeDataList.add(data);
67         }
68
69         String[] headerRow = new String[] { "Thing Type ID", "Description", "Supported Models" };
70
71         List<String[]> rows = new ArrayList<>();
72         rows.add(headerRow);
73         rows.addAll(thingTypeDataList.stream().map(ThingTypeTableGenerator::toRow).collect(Collectors.toList()));
74
75         int[] maxColumns = { maxColumnSize(rows, 0), maxColumnSize(rows, 1), maxColumnSize(rows, 2) };
76
77         StringWriter writer = new StringWriter();
78
79         // write actual rows
80         rows.forEach(row -> {
81             writer.append(writeRow(maxColumns, row, ' ')).append('\n');
82             if (row == headerRow) {
83                 writer.append(writeRow(maxColumns, new String[] { "", "", "" }, '-')).append('\n');
84             }
85         });
86
87         System.out.println(writer.toString());
88     }
89
90     private static String writeRow(int[] maxColumns, String[] row, char paddingChar) {
91         String prefix = "|" + paddingChar;
92         String infix = paddingChar + "|" + paddingChar;
93         String suffix = paddingChar + "|";
94
95         return Stream.of(0, 1, 2).map(i -> rightPad(row[i], maxColumns[i], paddingChar))
96                 .collect(Collectors.joining(infix, prefix, suffix));
97     }
98
99     private static String rightPad(String str, int minLength, char paddingChar) {
100         if (str.length() >= minLength) {
101             return str;
102         }
103         StringBuilder builder = new StringBuilder(minLength);
104         builder.append(str);
105         while (builder.length() < minLength) {
106             builder.append(paddingChar);
107         }
108         return builder.toString();
109     }
110
111     private static int maxColumnSize(List<String[]> rows, int column) {
112         return rows.stream().map(row -> row[column].length()).max(Integer::compare).get();
113     }
114
115     private static class ThingTypeData {
116         private @Nullable String id;
117         private @Nullable String label;
118         private @Nullable String description;
119     }
120
121     private static String[] toRow(ThingTypeData data) {
122         return new String[] { data.id, //
123                 data.description, //
124                 modelsForType(data.id).stream().map(model -> model.name()).collect(Collectors.joining(",")) };
125     }
126
127     private static List<GoveeModel> modelsForType(@Nullable String typeUID) {
128         return Arrays.stream(GoveeModel.values()).filter(model -> model.getThingTypeUID().getId().equals(typeUID))
129                 .collect(Collectors.toList());
130     }
131 }