1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package com.puppycrawl.tools.checkstyle.meta;
21
22 import java.nio.file.Path;
23 import java.util.List;
24 import java.util.Locale;
25 import java.util.regex.Pattern;
26
27 import javax.xml.XMLConstants;
28 import javax.xml.parsers.DocumentBuilder;
29 import javax.xml.parsers.DocumentBuilderFactory;
30 import javax.xml.parsers.ParserConfigurationException;
31 import javax.xml.transform.OutputKeys;
32 import javax.xml.transform.Transformer;
33 import javax.xml.transform.TransformerException;
34 import javax.xml.transform.TransformerFactory;
35 import javax.xml.transform.dom.DOMSource;
36 import javax.xml.transform.stream.StreamResult;
37
38 import org.w3c.dom.Document;
39 import org.w3c.dom.Element;
40 import org.w3c.dom.Node;
41
42
43
44
45 public final class XmlMetaWriter {
46
47
48 private static final Pattern FILEPATH_CONVERSION = Pattern.compile("\\.");
49
50
51 private static final String XML_TAG_NAME = "name";
52
53
54 private static final String XML_TAG_DESCRIPTION = "description";
55
56
57 private static final String DEFAULT_FILE_SEPARATOR = "/";
58
59
60
61
62 private XmlMetaWriter() {
63 }
64
65
66
67
68
69
70
71
72 public static void write(ModuleDetails moduleDetails) throws TransformerException,
73 ParserConfigurationException {
74 final DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
75 dbFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
76 dbFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
77 final DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
78 final Document doc = dBuilder.newDocument();
79
80 final Element rootElement = doc.createElement("checkstyle-metadata");
81 final Element rootChild = doc.createElement("module");
82 rootElement.appendChild(rootChild);
83
84 doc.appendChild(rootElement);
85
86 final Element checkModule = doc.createElement(moduleDetails.getModuleType().getLabel());
87 rootChild.appendChild(checkModule);
88
89 checkModule.setAttribute(XML_TAG_NAME, moduleDetails.getName());
90 checkModule.setAttribute("fully-qualified-name",
91 moduleDetails.getFullQualifiedName());
92 checkModule.setAttribute("parent", moduleDetails.getParent());
93
94 final Element desc = doc.createElement(XML_TAG_DESCRIPTION);
95 final Node cdataDesc = doc.createCDATASection(moduleDetails.getDescription());
96 desc.appendChild(cdataDesc);
97 checkModule.appendChild(desc);
98 createPropertySection(moduleDetails, checkModule, doc);
99 final List<String> violationMessageKeys = moduleDetails.getViolationMessageKeys();
100 if (!violationMessageKeys.isEmpty()) {
101 final Element messageKeys = doc.createElement("message-keys");
102 for (String msg : violationMessageKeys) {
103 final Element messageKey = doc.createElement("message-key");
104 messageKey.setAttribute("key", msg);
105 messageKeys.appendChild(messageKey);
106 }
107 checkModule.appendChild(messageKeys);
108 }
109
110 writeToFile(doc, moduleDetails);
111 }
112
113
114
115
116
117
118
119
120 private static void createPropertySection(ModuleDetails moduleDetails, Element checkModule,
121 Document doc) {
122 final List<ModulePropertyDetails> moduleProperties = moduleDetails.getProperties();
123 if (!moduleProperties.isEmpty()) {
124 final Element properties = doc.createElement("properties");
125 checkModule.appendChild(properties);
126 for (ModulePropertyDetails modulePropertyDetails : moduleProperties) {
127 final Element property = doc.createElement("property");
128 properties.appendChild(property);
129 property.setAttribute(XML_TAG_NAME, modulePropertyDetails.getName());
130 property.setAttribute("type", modulePropertyDetails.getType());
131 final String defaultValue = modulePropertyDetails.getDefaultValue();
132 if (defaultValue != null && !"null".equals(defaultValue)) {
133 property.setAttribute("default-value", defaultValue);
134 }
135 final String validationType = modulePropertyDetails.getValidationType();
136 if (validationType != null) {
137 property.setAttribute("validation-type", validationType);
138 }
139 final Element propertyDesc = doc.createElement(XML_TAG_DESCRIPTION);
140 propertyDesc.appendChild(doc.createCDATASection(
141 modulePropertyDetails.getDescription()));
142 property.appendChild(propertyDesc);
143 }
144 }
145 }
146
147
148
149
150
151
152
153
154 private static void writeToFile(Document document, ModuleDetails moduleDetails)
155 throws TransformerException {
156 String fileSeparator = DEFAULT_FILE_SEPARATOR;
157 if (System.getProperty("os.name").toLowerCase(Locale.ENGLISH).contains("win")) {
158 fileSeparator = "\\" + fileSeparator;
159 }
160 final String modifiedPath;
161 final String xmlExtension = ".xml";
162 final String rootOutputPath = System.getProperty("user.dir") + "/src/main/resources";
163 final String fullQualifiedName = moduleDetails.getFullQualifiedName();
164 if (fullQualifiedName.startsWith("com.puppycrawl.tools.checkstyle")) {
165 final String moduleFilePath = FILEPATH_CONVERSION
166 .matcher(fullQualifiedName)
167 .replaceAll(fileSeparator);
168 final String checkstyleString = "checkstyle";
169 final int indexOfCheckstyle =
170 moduleFilePath.indexOf(checkstyleString) + checkstyleString.length();
171
172 modifiedPath = rootOutputPath + DEFAULT_FILE_SEPARATOR
173 + moduleFilePath.substring(0, indexOfCheckstyle) + "/meta/"
174 + moduleFilePath.substring(indexOfCheckstyle + 1) + xmlExtension;
175 }
176 else {
177 String moduleName = moduleDetails.getName();
178 if (moduleDetails.getModuleType() == ModuleType.CHECK) {
179 moduleName += "Check";
180 }
181 modifiedPath = rootOutputPath + "/checkstylemeta-" + moduleName + xmlExtension;
182 }
183
184 final TransformerFactory transformerFactory = TransformerFactory.newInstance();
185 final Transformer transformer = transformerFactory.newTransformer();
186 transformer.setOutputProperty(OutputKeys.INDENT, "yes");
187 transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
188
189 final DOMSource source = new DOMSource(document);
190 final StreamResult result = new StreamResult(Path.of(modifiedPath).toFile());
191 transformer.transform(source, result);
192
193 }
194 }