package xapi.dev.ui;
import xapi.ui.api.Ui;
import xapi.ui.api.UiField;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
/**
* Created by james on 6/6/16.
*/
public class UiAnnotatedElements {
Map<TypeElement, Ui> uiTypes;
Map<ExecutableElement, Ui> uiMethods;
Map<ExecutableElement, UiField> boundMethods;
Map<VariableElement, UiField> boundFields;
Set<ExecutableElement> boundParameters;
public UiAnnotatedElements() {
uiTypes = new LinkedHashMap<>();
uiMethods = new LinkedHashMap<>();
boundMethods = new LinkedHashMap<>();
boundFields = new LinkedHashMap<>();
boundParameters = new LinkedHashSet<>();
}
public void maybeAddType(TypeElement element) {
final Ui typeUi = element.getAnnotation(Ui.class);
if (typeUi != null) {
uiTypes.put(element, typeUi);
}
}
public void maybeAddVariable(VariableElement var) {
}
public void maybeAddExecutable(ExecutableElement exe) {
final Ui exeUi = exe.getAnnotation(Ui.class);
if (exeUi != null) {
uiMethods.put(exe, exeUi);
}
// for now, we will ignore Gwt UiField annotations, and only handle our own
// in the future, we can find any annotation named UiField, and adapt accordingly
final UiField uiField = exe.getAnnotation(UiField.class);
if (uiField != null) {
boundMethods.put(exe, uiField);
}
boolean hadUnannotated = false;
boolean hadAnnotated = false;
for (VariableElement param : exe.getParameters()) {
final UiField paramAnno = param.getAnnotation(UiField.class);
if (paramAnno == null) {
if (hadAnnotated) {
throwBadParameterAnnotations(exe);
}
hadUnannotated = true;
} else {
if (hadUnannotated) {
throwBadParameterAnnotations(exe);
}
hadAnnotated = true;
boundParameters.add(exe);
}
}
}
public boolean hasAnyAnnotations() {
return hasUiAnnotations() || hasBoundAnnotations();
}
public boolean hasUiAnnotations() {
return !(uiTypes.isEmpty() && uiMethods.isEmpty());
}
public boolean hasBoundAnnotations() {
return !(boundMethods.isEmpty() && boundFields.isEmpty() && boundParameters.isEmpty());
}
private void throwBadParameterAnnotations(ExecutableElement exe) {
throw new IllegalStateException("ExecutableElement " + exe + " had bad parameter annotations; " +
"Contains some but not all parameters with @UiField annotations. " + exe.getParameters());
}
@Override
public String toString() {
return "UiAnnotatedElements{" +
"uiTypes=" + uiTypes +
", uiMethods=" + uiMethods +
", boundMethods=" + boundMethods +
", boundFields=" + boundFields +
", boundParameters=" + boundParameters +
", sAnyAnnotations=" + hasAnyAnnotations() +
", sUiAnnotations=" + hasUiAnnotations() +
", sBoundAnnotations=" + hasBoundAnnotations() +
'}';
}
}