
de.is24.deadcode4j.analyzer.CustomXmlAnalyzer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of deadcode4j-maven-plugin Show documentation
Show all versions of deadcode4j-maven-plugin Show documentation
Finds unused classes of a project
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