package japicmp.filter;
import com.google.common.base.Splitter;
import japicmp.exception.JApiCmpException;
import japicmp.util.SignatureParser;
import javassist.CtBehavior;
import javassist.CtClass;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
public class JavadocLikeBehaviorFilter implements BehaviorFilter {
private final String filterString;
private final Pattern classPattern;
private final Pattern methodPattern;
private final List<Pattern> parameterPatterns = new ArrayList<>();
public JavadocLikeBehaviorFilter(String filterString) {
this.filterString = filterString;
String regEx = filterString.replace(".", "\\.");
regEx = regEx.replace("*", ".*");
regEx = regEx.replace("$", "\\$");
String[] parts = regEx.split("#");
if (parts.length != 2) {
throw new JApiCmpException(JApiCmpException.Reason.CliError, "Filter option '" + filterString + "' should not contain more than one '#'.");
}
classPattern = Pattern.compile(parts[0]);
String methodPart = parts[1];
int indexOpeningBracket = methodPart.indexOf('(');
int indexClosingBracket = methodPart.indexOf(')');
if (indexOpeningBracket == -1) {
throw new JApiCmpException(JApiCmpException.Reason.CliError, "Filter option '" + filterString + "' should contain one opening '('.");
}
if (indexClosingBracket == -1) {
throw new JApiCmpException(JApiCmpException.Reason.CliError, "Filter option '" + filterString + "' should contain one opening ')'.");
}
if (indexClosingBracket <= indexOpeningBracket) {
throw new JApiCmpException(JApiCmpException.Reason.CliError, "Filter option '" + filterString + "' should contain first an opening '(' and then a closing ')'.");
}
if (indexOpeningBracket == 0) {
throw new JApiCmpException(JApiCmpException.Reason.CliError, "Filter option '" + filterString + "' should contain at least one character before the opening '('.");
}
String methodName = methodPart.substring(0, indexOpeningBracket);
methodPattern = Pattern.compile(methodName);
String paramList = methodPart.substring(indexOpeningBracket + 1, indexClosingBracket);
if (paramList.length() > 0) {
for (String param : Splitter.on(",").trimResults().omitEmptyStrings().split(paramList)) {
param = param.replaceAll("\\s+", "");
parameterPatterns.add(Pattern.compile(param));
}
}
}
@Override
public boolean matches(CtBehavior ctBehavior) {
boolean classMatches = true;
boolean methodMatches = true;
boolean parameterMatches = true;
CtClass declaringClass = ctBehavior.getDeclaringClass();
String name = declaringClass.getName();
if (!classPattern.matcher(name).matches()) {
classMatches = false;
}
String methodName = ctBehavior.getName();
if (!methodPattern.matcher(methodName).matches()) {
methodMatches = false;
}
SignatureParser signatureParser = new SignatureParser();
signatureParser.parse(ctBehavior.getSignature());
List<String> parameters = signatureParser.getParameters();
if (parameters.size() != parameterPatterns.size()) {
parameterMatches = false;
} else {
for (int i = 0; i < parameters.size(); i++) {
Pattern pattern = parameterPatterns.get(i);
if (!pattern.matcher(parameters.get(i)).matches()) {
parameterMatches = false;
}
}
}
return (classMatches && methodMatches && parameterMatches);
}
@Override
public String toString() {
return this.filterString;
}
}