com.puppycrawl.tools.checkstyle.meta.XmlMetaWriter Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of checkstyle Show documentation
Show all versions of checkstyle Show documentation
Checkstyle is a development tool to help programmers write Java code
that adheres to a coding standard
////////////////////////////////////////////////////////////////////////////////
// checkstyle: Checks Java source code for adherence to a set of rules.
// Copyright (C) 2001-2021 the original author or authors.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
////////////////////////////////////////////////////////////////////////////////
package com.puppycrawl.tools.checkstyle.meta;
import java.io.File;
import java.util.Locale;
import java.util.regex.Pattern;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
/**
* Class to write module details object into an XML file.
*/
public final class XmlMetaWriter {
/** Compiled pattern for {@code .} used for generating file paths from package names. */
private static final Pattern FILEPATH_CONVERSION = Pattern.compile("\\.");
/** Name tag of metadata XML files. */
private static final String XML_TAG_NAME = "name";
/** Description tag of metadata XML files. */
private static final String XML_TAG_DESCRIPTION = "description";
/** Default(UNIX) file separator. */
private static final String DEFAULT_FILE_SEPARATOR = "/";
/**
* Do no allow {@code XmlMetaWriter} instances to be created.
*/
private XmlMetaWriter() {
}
/**
* Helper function to write module details to XML file.
*
* @param moduleDetails module details
* @throws TransformerException if a transformer exception occurs
* @throws ParserConfigurationException if a parser configuration exception occurs
*/
public static void write(ModuleDetails moduleDetails) throws TransformerException,
ParserConfigurationException {
final DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
dbFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
dbFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
final DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
final Document doc = dBuilder.newDocument();
final Element rootElement = doc.createElement("checkstyle-metadata");
final Element rootChild = doc.createElement("module");
rootElement.appendChild(rootChild);
doc.appendChild(rootElement);
final Element checkModule = doc.createElement(moduleDetails.getModuleType().getLabel());
rootChild.appendChild(checkModule);
checkModule.setAttribute(XML_TAG_NAME, moduleDetails.getName());
checkModule.setAttribute("fully-qualified-name",
moduleDetails.getFullQualifiedName());
checkModule.setAttribute("parent", moduleDetails.getParent());
final Element desc = doc.createElement(XML_TAG_DESCRIPTION);
final Node cdataDesc = doc.createCDATASection(moduleDetails.getDescription());
desc.appendChild(cdataDesc);
checkModule.appendChild(desc);
createPropertySection(moduleDetails, checkModule, doc);
if (!moduleDetails.getViolationMessageKeys().isEmpty()) {
final Element messageKeys = doc.createElement("message-keys");
for (String msg : moduleDetails.getViolationMessageKeys()) {
final Element messageKey = doc.createElement("message-key");
messageKey.setAttribute("key", msg);
messageKeys.appendChild(messageKey);
}
checkModule.appendChild(messageKeys);
}
writeToFile(doc, moduleDetails);
}
/**
* Create the property section of the module detail object.
*
* @param moduleDetails module details
* @param checkModule root doc element
* @param doc document object
*/
private static void createPropertySection(ModuleDetails moduleDetails, Element checkModule,
Document doc) {
if (!moduleDetails.getProperties().isEmpty()) {
final Element properties = doc.createElement("properties");
checkModule.appendChild(properties);
for (ModulePropertyDetails modulePropertyDetails : moduleDetails.getProperties()) {
final Element property = doc.createElement("property");
properties.appendChild(property);
property.setAttribute(XML_TAG_NAME, modulePropertyDetails.getName());
property.setAttribute("type", modulePropertyDetails.getType());
if (modulePropertyDetails.getDefaultValue() != null) {
property.setAttribute("default-value",
modulePropertyDetails.getDefaultValue());
}
if (modulePropertyDetails.getValidationType() != null) {
property.setAttribute("validation-type",
modulePropertyDetails.getValidationType());
}
final Element propertyDesc = doc.createElement(XML_TAG_DESCRIPTION);
propertyDesc.appendChild(doc.createCDATASection(
modulePropertyDetails.getDescription()));
property.appendChild(propertyDesc);
}
}
}
/**
* Function to write the prepared document object into an XML file.
*
* @param document document updated with all module metadata
* @param moduleDetails the corresponding module details object
* @throws TransformerException if a transformer exception occurs
*/
private static void writeToFile(Document document, ModuleDetails moduleDetails)
throws TransformerException {
String fileSeparator = DEFAULT_FILE_SEPARATOR;
if (System.getProperty("os.name").toLowerCase(Locale.ENGLISH).contains("win")) {
fileSeparator = "\\" + fileSeparator;
}
final String modifiedPath;
final String xmlExtension = ".xml";
final String rootOutputPath = System.getProperty("user.dir") + "/src/main/resources";
if (moduleDetails.getFullQualifiedName().startsWith("com.puppycrawl.tools.checkstyle")) {
final String moduleFilePath = FILEPATH_CONVERSION
.matcher(moduleDetails.getFullQualifiedName())
.replaceAll(fileSeparator);
final String checkstyleString = "checkstyle";
final int indexOfCheckstyle =
moduleFilePath.indexOf(checkstyleString) + checkstyleString.length();
modifiedPath = rootOutputPath + DEFAULT_FILE_SEPARATOR
+ moduleFilePath.substring(0, indexOfCheckstyle) + "/meta/"
+ moduleFilePath.substring(indexOfCheckstyle + 1) + xmlExtension;
}
else {
String moduleName = moduleDetails.getName();
if (moduleDetails.getModuleType() == ModuleType.CHECK) {
moduleName += "Check";
}
modifiedPath = rootOutputPath + "/checkstylemeta-" + moduleName + xmlExtension;
}
if (!moduleDetails.getDescription().isEmpty()) {
final TransformerFactory transformerFactory = TransformerFactory.newInstance();
final Transformer transformer = transformerFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
final DOMSource source = new DOMSource(document);
final StreamResult result = new StreamResult(new File(modifiedPath));
transformer.transform(source, result);
}
}
}