package com.hypnoticocelot.jaxrs.doclet.translator;
import com.hypnoticocelot.jaxrs.doclet.parser.AnnotationHelper;
import com.hypnoticocelot.jaxrs.doclet.parser.AnnotationParser;
import com.sun.javadoc.FieldDoc;
import com.sun.javadoc.MethodDoc;
import com.sun.javadoc.ProgramElementDoc;
import com.sun.javadoc.Type;
import java.util.HashMap;
import java.util.Map;
import static com.hypnoticocelot.jaxrs.doclet.translator.Translator.OptionalName.ignored;
import static com.hypnoticocelot.jaxrs.doclet.translator.Translator.OptionalName.presentOrMissing;
public class AnnotationAwareTranslator implements Translator {
private final Map<OptionalName, Type> reverseIndex;
private final Map<Type, OptionalName> namedTypes;
private String ignore;
private String element;
private String elementProperty;
private String rootElement;
private String rootElementProperty;
public AnnotationAwareTranslator() {
reverseIndex = new HashMap<OptionalName, Type>();
namedTypes = new HashMap<Type, OptionalName>();
}
public AnnotationAwareTranslator ignore(String qualifiedAnnotationType) {
this.ignore = qualifiedAnnotationType;
return this;
}
public AnnotationAwareTranslator element(String qualifiedAnnotationType, String property) {
this.element = qualifiedAnnotationType;
this.elementProperty = property;
return this;
}
public AnnotationAwareTranslator rootElement(String qualifiedAnnotationType, String property) {
this.rootElement = qualifiedAnnotationType;
this.rootElementProperty = property;
return this;
}
@Override
public OptionalName typeName(Type type) {
if (namedTypes.containsKey(type)) {
return namedTypes.get(type);
}
if (AnnotationHelper.isPrimitive(type) || type.asClassDoc() == null) {
return null;
}
OptionalName name = nameFor(rootElement, rootElementProperty, type.asClassDoc());
if (name.isPresent()) {
StringBuilder nameBuilder = new StringBuilder(name.value());
while (reverseIndex.containsKey(name)) {
nameBuilder.append('_');
name = presentOrMissing(nameBuilder.toString());
}
namedTypes.put(type, name);
reverseIndex.put(name, type);
}
return name;
}
@Override
public OptionalName fieldName(FieldDoc field) {
return nameFor(element, elementProperty, field);
}
@Override
public OptionalName methodName(MethodDoc method) {
return nameFor(element, elementProperty, method);
}
private OptionalName nameFor(String annotation, String property, ProgramElementDoc doc) {
AnnotationParser element = new AnnotationParser(doc);
if (element.isAnnotatedBy(ignore)) {
return ignored();
}
return presentOrMissing(element.getAnnotationValue(annotation, property));
}
}