2 * Copyright (c) 2010-2021 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
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
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.bluetooth.govee.internal.readme;
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;
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;
30 import org.openhab.binding.bluetooth.govee.internal.GoveeModel;
31 import org.w3c.dom.Document;
32 import org.w3c.dom.Node;
33 import org.w3c.dom.NodeList;
36 * @author Connor Petty - Initial contribution
39 public class ThingTypeTableGenerator {
41 public static void main(String[] args) throws Exception {
43 FileInputStream fileIS = new FileInputStream("src/main/resources/OH-INF/thing/thing-types.xml");
44 DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
45 DocumentBuilder builder = builderFactory.newDocumentBuilder();
46 Document xmlDocument = builder.parse(fileIS);
47 XPath xPath = XPathFactory.newInstance().newXPath();
48 String expression = "/*[local-name()='thing-descriptions']/thing-type";
49 XPathExpression labelExpression = xPath.compile("label/text()");
50 XPathExpression descriptionExpression = xPath.compile("description/text()");
52 NodeList nodeList = (NodeList) xPath.compile(expression).evaluate(xmlDocument, XPathConstants.NODESET);
54 List<ThingTypeData> thingTypeDataList = new ArrayList<>();
56 for (int i = 0; i < nodeList.getLength(); i++) {
57 Node node = nodeList.item(i);
58 ThingTypeData data = new ThingTypeData();
60 data.id = node.getAttributes().getNamedItem("id").getTextContent();
61 data.label = (String) labelExpression.evaluate(node, XPathConstants.STRING);
62 data.description = (String) descriptionExpression.evaluate(node, XPathConstants.STRING);
64 thingTypeDataList.add(data);
67 String[] headerRow = new String[] { "Thing Type ID", "Description", "Supported Models" };
69 List<String[]> rows = new ArrayList<>();
71 rows.addAll(thingTypeDataList.stream().map(ThingTypeTableGenerator::toRow).collect(Collectors.toList()));
73 int[] maxColumns = { maxColumnSize(rows, 0), maxColumnSize(rows, 1), maxColumnSize(rows, 2) };
75 StringWriter writer = new StringWriter();
79 writer.append(writeRow(maxColumns, row, ' ')).append('\n');
80 if (row == headerRow) {
81 writer.append(writeRow(maxColumns, new String[] { "", "", "" }, '-')).append('\n');
85 System.out.println(writer.toString());
88 private static String writeRow(int[] maxColumns, String[] row, char paddingChar) {
89 String prefix = "|" + paddingChar;
90 String infix = paddingChar + "|" + paddingChar;
91 String suffix = paddingChar + "|";
93 return Stream.of(0, 1, 2).map(i -> rightPad(row[i], maxColumns[i], paddingChar))
94 .collect(Collectors.joining(infix, prefix, suffix));
97 private static String rightPad(String str, int minLength, char paddingChar) {
98 if (str.length() >= minLength) {
101 StringBuilder builder = new StringBuilder(minLength);
103 while (builder.length() < minLength) {
104 builder.append(paddingChar);
106 return builder.toString();
109 private static int maxColumnSize(List<String[]> rows, int column) {
110 return rows.stream().map(row -> row[column].length()).max(Integer::compare).get();
113 private static class ThingTypeData {
115 private String label;
116 private String description;
119 private static String[] toRow(ThingTypeData data) {
120 return new String[] { data.id, //
122 modelsForType(data.id).stream().map(model -> model.name()).collect(Collectors.joining(",")) };
125 private static List<GoveeModel> modelsForType(String typeUID) {
126 return Arrays.stream(GoveeModel.values()).filter(model -> model.getThingTypeUID().getId().equals(typeUID))
127 .collect(Collectors.toList());