All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.discursive.plugins.ValidateChapterIdentifiersMojo Maven / Gradle / Ivy

The newest version!
package com.discursive.plugins;

import java.io.File;
import java.io.FileFilter;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.io.filefilter.WildcardFileFilter;
import org.apache.commons.lang.StringUtils;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.project.MavenProject;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;

/**
 * This Mojo simply verifies that each chapter has an appropriate identifer.
 * 
 * @goal validate-chapter-ids
 * @phase test
 * @requiresProject
 */
public class ValidateChapterIdentifiersMojo extends AbstractMojo {

	/**
	 * @parameter expression="${project}"
	 * @required
	 * @readonly
	 */
	protected MavenProject project;

	/**
	 * @parameter
	 */
	protected String wildcardFilter = "*.xml";

	/**
	 * @parameter expression="${project.build.outputDirectory}"
	 * @required
	 */
	protected File outputDir;

	/**
	 * @parameter
	 */
	protected Boolean validateElementIds = true;

	/**
	 * @parameter
	 */
	protected Boolean validateSectionIds = true;

	/**
	 * @parameter
	 */
	protected Boolean validateExampleIds = true;

	/**
	 * @parameter
	 */
	protected Boolean validateFigureIds = true;

	/**
	 * @parameter
	 */
	protected String filenamePattern = "${elementName}-${elementId}.xml";

	/**
	 * @parameter
	 */
	protected String figureIdPattern = "${elementId}-fig-.*";

	/**
	 * @parameter
	 */
	protected String sectionIdPattern = "${elementId}-sect-.*";

	/**
	 * @parameter
	 */
	protected String exampleIdPattern = "${elementId}-ex-.*";

	/**
	 * @parameter
	 */
	protected String figureXPath = "//figure";

	/**
	 * @parameter
	 */
	protected String sectionXPath = "//section";

	/**
	 * @parameter
	 */
	protected String exampleXPath = "//example";

	private List validationFailures = new ArrayList();

	public void execute() throws MojoExecutionException, MojoFailureException {

		FileFilter fileFilter = new WildcardFileFilter(wildcardFilter);
		File[] xmlFiles = outputDir.listFiles(fileFilter);
		for (int i = 0; i < xmlFiles.length; i++) {

			try {
				processXml(xmlFiles[i]);
			} catch (Exception e) {
				throw new MojoExecutionException("Problem parsing XML file: "
						+ xmlFiles[i], e);
			}

		}

		if (validationFailures.size() > 0) {
			throw new MojoFailureException("\n"
					+ StringUtils.join(validationFailures.iterator(), "\n"));
		}

	}

	private void processXml(File file) throws MalformedURLException,
			DocumentException {

		String fileName = file.getName();
		Document doc = parse(file.toURL());
		Element rootElement = doc.getRootElement();

		if (!fileName.startsWith(rootElement.getName())) {
			String failure = "File: " + fileName
					+ " contains a root element of type "
					+ rootElement.getName()
					+ ", but file name does not start with "
					+ rootElement.getName();
			validationFailures.add(failure);
		}

		String fileNameRegex = StringUtils.replace(filenamePattern,
				"${elementName}", rootElement.getName());
		fileNameRegex = StringUtils.replace(fileNameRegex, "${elementId}",
				"(.*)");
		Pattern p = Pattern.compile(fileNameRegex.trim());
		Matcher m = p.matcher(fileName.trim());
		if (!m.matches()) {
			String failure = "File: " + fileName
					+ " does not follow the regex: " + fileNameRegex;
			validationFailures.add(failure);
			return;
		}

		String fileId = m.group(1);

		Attribute idAttr = rootElement.attribute("id");
		String elementId = idAttr.getValue();

		if (!fileId.equals(elementId)) {
			String failure = "File: " + fileName
					+ " the identfier from the filename '" + fileId
					+ "' does not match the root element id of '" + elementId
					+ "'";
			validationFailures.add(failure);
		}

		if (validateSectionIds) {
			validateIds(fileName, doc, elementId, sectionXPath, sectionIdPattern, "Section");
		}

		if (validateExampleIds) {
			validateIds(fileName, doc, elementId, exampleXPath, exampleIdPattern, "Example");
		}

		if (validateFigureIds) {
			validateIds(fileName, doc, elementId, figureXPath, figureIdPattern, "Figure");
		}
	}

	private void validateIds(String fileName, Document doc, String elementId,
			String xpath, String idPattern, String type) {
		List selectNodes = doc.selectNodes(xpath);
		List nodes = new ArrayList(selectNodes);
		int i = 1;
		for (Node node : nodes) {
			Element section = (Element) node;
			Attribute sectIdAttr = section.attribute("id");
			if (sectIdAttr == null) {
				String failure = "File: " + fileName + " " + type + " #" + i
						+ " lacks an identifier";
				validationFailures.add(failure);
			} else {

				String sectId = sectIdAttr.getValue();

				String regex = StringUtils.replace(idPattern, "${elementId}",
						elementId);
				if (!sectId.matches(regex)) {
					String failure = "File: " + fileName + " " + type + " "
							+ sectId + " does not match regex " + regex;
					validationFailures.add(failure);
				}
			}

			i++;
		}
	}

	public Document parse(URL url) throws DocumentException {
		SAXReader reader = new SAXReader();
		reader.setValidation( false );
		Document document = reader.read(url);
		return document;
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy