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

de.is24.deadcode4j.analyzer.CustomXmlAnalyzer Maven / Gradle / Ivy

There is a newer version: 2.1.0
Show newest version
package de.is24.deadcode4j.analyzer;

import de.is24.deadcode4j.AnalysisContext;
import de.is24.deadcode4j.AnalysisSink;
import de.is24.deadcode4j.AnalyzedCode;
import de.is24.deadcode4j.Utils;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static com.google.common.base.Preconditions.checkArgument;

/**
 * Analyzes XML files: lists the registered elements' text or attribute values as being referenced classes.
 *
 * @since 1.3
 */
public final class CustomXmlAnalyzer extends SimpleXmlAnalyzer {

    //                                                              element       [@attribute='value']    /   @attribute|text()
    private static final Pattern XPATH_PATTERN = Pattern.compile("^([^/\\[]+)(?:\\[@([^=]+)='([^']+)'\\])?/(?:@(.*)|text\\(\\))$");
    private static volatile int instanceNumber = 0; // we assign this to make sure the self check works
    private boolean dependencyWasFound = false;

    /**
     * Creates a new CustomXmlAnalyzer.
     * Be sure to call {@link #registerXPath(String)} after construction.
     *
     * @param dependerId    a description of the depending entity with which to
     *                      call {@link de.is24.deadcode4j.AnalysisContext#addDependencies(String, Iterable)}
     * @param endOfFileName the file suffix used to determine if a file should be analyzed; this can be a mere file
     *                      extension like .xml or a partial path like WEB-INF/web.xml
     * @param rootElement   the expected XML root element or null if such an element does not exist;
     *                      i.e. there are multiple valid root elements
     * @since 1.3
     */
    protected CustomXmlAnalyzer(@Nonnull String dependerId, @Nonnull String endOfFileName, @Nullable String rootElement) {
        super(dependerId, endOfFileName, rootElement);
    }

    /**
     * Creates a new CustomXmlAnalyzer.
     * Be sure to call {@link #registerXPath(String)} after construction.
     *
     * @param endOfFileName the file suffix used to determine if a file should be analyzed; this can be a mere file
     *                      extension like .xml or a partial path like WEB-INF/web.xml
     * @param rootElement   the expected XML root element or null if such an element does not exist;
     *                      i.e. there are multiple valid root elements
     * @since 1.3
     */
    public CustomXmlAnalyzer(@Nonnull String endOfFileName, @Nullable String rootElement) {
        this("_custom-XML#" + getNewInstanceNumber() + "_", endOfFileName, rootElement);
    }

    private static int getNewInstanceNumber() {
        return instanceNumber++;
    }

    /**
     * Register an XPath expression identifying an XML node which is to be recognized as a class being in use.
     * Supported expressions are:
     * 
    *
  • element/text()
  • *
  • element/@attribute
  • *
* An element may be further restricted by defining a predicate like * element[@attributeName='attributeValue']. * * @throws IllegalArgumentException if xPath is not supported */ public void registerXPath(String xPath) throws IllegalArgumentException { Matcher matcher = XPATH_PATTERN.matcher(xPath); checkArgument(matcher.matches(), "Although [" + xPath + "] may be a valid XPath expression, it is not supported!"); String elementName = matcher.group(1); String attribute = matcher.group(4); Element element; if (attribute != null) { element = registerClassAttribute(elementName, attribute); } else { element = registerClassElement(elementName); } if (matcher.group(2) != null) { element.withAttributeValue(matcher.group(2), matcher.group(3)); } } @Override public void finishAnalysis(@Nonnull AnalysisContext analysisContext) { super.finishAnalysis(analysisContext); Set dependencies = analysisContext.getAnalyzedCode().getCodeDependencies().get(super.dependerId); if (!Utils.isEmpty(dependencies)) { dependencyWasFound = true; } } @Override public void finishAnalysis(@Nonnull AnalysisSink analysisSink, @Nonnull AnalyzedCode analyzedCode) { super.finishAnalysis(analysisSink, analyzedCode); if (!dependencyWasFound) { logger.warn("The {} didn't find any class to report. You should remove the configuration entry.", this); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy