package org.hamcrest.generator;
import com.thoughtworks.qdox.model.DocletTag;
import com.thoughtworks.qdox.model.JavaClass;
import com.thoughtworks.qdox.model.JavaMethod;
import com.thoughtworks.qdox.model.JavaParameter;
import com.thoughtworks.qdox.model.Type;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Pattern;
public class QDoxFactoryReader implements Iterable<FactoryMethod> {
private final Iterable<FactoryMethod> wrapped;
private final JavaClass classSource;
private static final Pattern GENERIC_REGEX = Pattern.compile("<.*>");
private static final Pattern VARARGS_REGEX = Pattern.compile("...", Pattern.LITERAL);
public QDoxFactoryReader(Iterable<FactoryMethod> wrapped, QDox qdox, String className) {
this.wrapped = wrapped;
this.classSource = qdox.getClassByName(className);
}
@Override
public Iterator<FactoryMethod> iterator() {
final Iterator<FactoryMethod> iterator = wrapped.iterator();
return new Iterator<FactoryMethod>() {
@Override
public boolean hasNext() {
return iterator.hasNext();
}
@Override
public FactoryMethod next() {
return enhance(iterator.next());
}
@Override
public void remove() {
iterator.remove();
}
};
}
private FactoryMethod enhance(FactoryMethod factoryMethod) {
JavaMethod methodSource = findMethodInSource(factoryMethod);
if (methodSource != null) {
factoryMethod.setJavaDoc(createJavaDocComment(methodSource));
JavaParameter[] parametersFromSource
= methodSource.getParameters();
List<FactoryMethod.Parameter> parametersFromReflection
= factoryMethod.getParameters();
if (parametersFromReflection.size() == parametersFromSource.length) {
for (int i = 0; i < parametersFromSource.length; i++) {
parametersFromReflection.get(i).setName(
parametersFromSource[i].getName());
}
}
}
return factoryMethod;
}
private JavaMethod findMethodInSource(FactoryMethod factoryMethod) {
List<FactoryMethod.Parameter> params = factoryMethod.getParameters();
Type[] types = new Type[params.size()];
boolean varArgs = false;
for (int i = 0; i < types.length; i++) {
String type = params.get(i).getType();
varArgs = VARARGS_REGEX.matcher(type).find();
type = GENERIC_REGEX.matcher(type).replaceAll("");
type = VARARGS_REGEX.matcher(type).replaceAll("");
types[i] = new Type(type);
}
JavaMethod[] methods = classSource.getMethodsBySignature(factoryMethod.getName(), types, false, varArgs);
return methods.length == 1 ? methods[0] : null;
}
private static String createJavaDocComment(JavaMethod methodSource) {
String comment = methodSource.getComment();
DocletTag[] tags = methodSource.getTags();
if ((comment == null || comment.trim().length() == 0) && tags.length == 0) {
return null;
}
StringBuilder result = new StringBuilder();
result.append(comment);
result.append("\n\n");
for (DocletTag tag : tags) {
result.append('@').append(tag.getName())
.append(' ').append(tag.getValue())
.append('\n');
}
return result.toString();
}
}