package org.codefx.mvn.jdeps.parse;
import org.codefx.mvn.jdeps.dependency.InternalType;
import java.util.Objects;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Parses a single line of JDeps output to an {@link InternalType}.
* <p>
* Such lines must generally be of the following form:
*
* <pre>
* -> package.name.ClassName category (source)
* </pre>
*/
class InternalTypeLineParser {
private static final Pattern JDEPS_DEPENDENCY_PATTERN = Pattern.compile(""
+ "\\s+->\\s+" // leading spaces and arrow, e.g. " -> "
+ "([a-zA-Z_][\\.\\w]*)" // qualified class name (simplified), e.g. "sun.misc.Unsafe"
+ "\\s+" // spaces to fill up the column
+ "(\\w[\\w\\s]*\\w*)" // category, e.g. "JDK Internal API"
+ "\\s" // space between category and source
+ "\\(([\\w\\.]*)\\)" // source, e.g. "(jt.jar)"
+ ".*");
/**
* Indicates whether the specified line is an {@link InternalType}.
*
* @param line
* the line to check
* @return true if the line can be parsed to an {@link InternalType}
*/
public boolean isInternalTypeLine(String line) {
Objects.requireNonNull(line, "The argument 'line' must not be null.");
return JDEPS_DEPENDENCY_PATTERN.matcher(line).matches();
}
/**
* Tries to parse the specified line to an {@link InternalType}.
*
* @param line
* the line to parse
* @return an {@link InternalType} if the line could be parsed; otherwise an empty {@link Optional}
*/
public Optional<InternalType> parseLine(String line) {
Objects.requireNonNull(line, "The argument 'line' must not be null.");
Matcher lineMatcher = JDEPS_DEPENDENCY_PATTERN.matcher(line);
if (!lineMatcher.matches() || lineMatcher.groupCount() != 3)
return Optional.empty();
String fullyQualifiedClassName = lineMatcher.group(1);
String category = lineMatcher.group(2);
String source = lineMatcher.group(3);
InternalType type = InternalType.of(
extractPackageName(fullyQualifiedClassName),
extractClassName(fullyQualifiedClassName),
category,
source);
return Optional.of(type);
}
private static String extractPackageName(String fullyQualifiedClassName) {
int indexOfLastPoint = fullyQualifiedClassName.lastIndexOf('.');
return fullyQualifiedClassName.substring(0, indexOfLastPoint);
}
private static String extractClassName(String fullyQualifiedClassName) {
int indexOfLastPoint = fullyQualifiedClassName.lastIndexOf('.');
return fullyQualifiedClassName.substring(indexOfLastPoint + 1);
}
}