Moved field annotation responsibilities to FieldElement

FieldElement processes Format and PrimaryKey annotations
Created AnnotationElement root class
This commit is contained in:
Collin Smith 2020-12-15 16:56:03 -08:00
parent c33390503e
commit 645d2eb25b
8 changed files with 142 additions and 67 deletions

View File

@ -7,4 +7,5 @@ dependencies {
api project(':table:core')
implementation "org.apache.commons:commons-text:1.8"
implementation "org.apache.commons:commons-collections4:4.1"
}

View File

@ -0,0 +1,34 @@
package com.riiablo.table.annotation;
import java.lang.annotation.Annotation;
import java.util.Map;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.ExecutableElement;
import org.apache.commons.lang3.builder.ToStringBuilder;
abstract class AnnotationElement<A extends Annotation> {
protected final Context context;
protected final A annotation;
protected final AnnotationMirror mirror;
protected AnnotationElement(Context context, A annotation, AnnotationMirror mirror) {
this.context = context;
this.annotation = annotation;
this.mirror = mirror;
}
Map<? extends ExecutableElement, ? extends AnnotationValue>
defaults() {
return context.elementUtils.getElementValuesWithDefaults(mirror);
}
@Override
public String toString() {
return new ToStringBuilder(this)
.append("context", context)
.append("annotation", annotation)
.append("mirror", mirror)
.toString();
}
}

View File

@ -10,6 +10,7 @@ final class Constants {
static final ClassName STRING = ClassName.get(String.class);
static final ClassName PRIMARY_KEY = ClassName.get(PrimaryKey.class);
static final ClassName FORMAT = ClassName.get(Format.class);
static final TypeName[] PRIMARY_KEY_TYPES = { TypeName.INT, STRING };

View File

@ -67,7 +67,7 @@ class Context {
}
}
messager.printMessage(kind, builder);
messager.printMessage(kind, builder, element, annotationMirror, annotationValue);
}
void error(String message, Object... args) {

View File

@ -0,0 +1,38 @@
package com.riiablo.table.annotation;
import java.util.Collection;
import javax.lang.model.element.VariableElement;
final class FieldElement {
static FieldElement get(Context context, VariableElement element) {
FormatElement formatElement = FormatElement.get(context, element);
PrimaryKeyElement primaryKeyElement = PrimaryKeyElement.get(context, element);
return new FieldElement(element, formatElement, primaryKeyElement);
}
static FieldElement firstPrimaryKey(Collection<FieldElement> fields) {
for (FieldElement field : fields) {
if (field.primaryKeyElement != null || Constants.isPrimaryKey(field.element)) {
return field;
}
}
return null;
}
final VariableElement element;
final FormatElement formatElement;
final PrimaryKeyElement primaryKeyElement;
FieldElement(VariableElement element, FormatElement formatElement, PrimaryKeyElement primaryKeyElement) {
this.element = element;
this.formatElement = formatElement;
this.primaryKeyElement = primaryKeyElement;
}
@Override
public String toString() {
return element.toString();
}
}

View File

@ -0,0 +1,17 @@
package com.riiablo.table.annotation;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.VariableElement;
final class FormatElement extends AnnotationElement<Format> {
static FormatElement get(Context context, VariableElement element) {
Format annotation = element.getAnnotation(Format.class);
if (annotation == null) return null;
AnnotationMirror mirror = context.getAnnotationMirror(element, Constants.FORMAT);
return new FormatElement(context, annotation, mirror);
}
FormatElement(Context context, Format annotation, AnnotationMirror mirror) {
super(context, annotation, mirror);
}
}

View File

@ -1,63 +1,17 @@
package com.riiablo.table.annotation;
import java.util.Collection;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import org.apache.commons.lang3.builder.ToStringBuilder;
final class PrimaryKeyElement {
static PrimaryKeyElement find(
Context context,
TypeElement element,
Collection<VariableElement> elements
) {
VariableElement firstAcceptableElement = null, primaryKeyElement = null;
for (VariableElement e : elements) {
if (firstAcceptableElement == null && Constants.isPrimaryKey(e)) {
firstAcceptableElement = e;
}
PrimaryKey annotation = e.getAnnotation(PrimaryKey.class);
if (annotation != null) {
if (primaryKeyElement == null) {
primaryKeyElement = e;
} else {
context.error(
e, context.getAnnotationMirror(e, Constants.PRIMARY_KEY),
"{} already declared as {}", primaryKeyElement, PrimaryKey.class);
}
}
}
if (primaryKeyElement == null) {
if (firstAcceptableElement == null) {
context.error(element, "{element} did not declare any {}", PrimaryKey.class);
return null;
}
context.warn(element, "{element} did not declare any {}, using {}",
PrimaryKey.class, firstAcceptableElement);
primaryKeyElement = firstAcceptableElement;
}
AnnotationMirror primaryKeyMirror = context.getAnnotationMirror(primaryKeyElement, Constants.PRIMARY_KEY);
return new PrimaryKeyElement(primaryKeyElement, primaryKeyMirror);
final class PrimaryKeyElement extends AnnotationElement<PrimaryKey> {
static PrimaryKeyElement get(Context context, VariableElement element) {
PrimaryKey annotation = element.getAnnotation(PrimaryKey.class);
if (annotation == null) return null;
AnnotationMirror mirror = context.getAnnotationMirror(element, Constants.PRIMARY_KEY);
return new PrimaryKeyElement(context, annotation, mirror);
}
final VariableElement element;
final AnnotationMirror mirror;
PrimaryKeyElement(VariableElement element, AnnotationMirror mirror) {
this.element = element;
this.mirror = mirror;
}
@Override
public String toString() {
return new ToStringBuilder(this)
.append("element", element)
.append("mirror", mirror)
.toString();
PrimaryKeyElement(Context context, PrimaryKey annotation, AnnotationMirror mirror) {
super(context, annotation, mirror);
}
}

View File

@ -2,37 +2,63 @@ package com.riiablo.table.annotation;
import com.squareup.javapoet.ClassName;
import java.util.ArrayList;
import java.util.List;
import java.util.Collection;
import java.util.Iterator;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeMirror;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.IteratorUtils;
import org.apache.commons.collections4.Predicate;
import org.apache.commons.lang3.builder.ToStringBuilder;
final class SchemaElement {
static SchemaElement get(Context context, Element element) {
static SchemaElement get(final Context context, Element element) {
TypeElement typeElement = (TypeElement) element;
List<VariableElement> columns = collectColumns(context, typeElement);
PrimaryKeyElement primaryKeyElement = PrimaryKeyElement.find(context, typeElement, columns);
Collection<FieldElement> fields = collectFieldElements(context, typeElement);
// for (VariableElement e : columns) {
// System.out.println(e);
// }
final FieldElement primaryKeyFieldElement;
Collection<FieldElement> primaryKeys = CollectionUtils.select(fields, new Predicate<FieldElement>() {
@Override
public boolean evaluate(FieldElement e) {
return e.primaryKeyElement != null;
}
});
if (primaryKeys.size() >= 1) {
Iterator<FieldElement> it = primaryKeys.iterator();
primaryKeyFieldElement = it.next();
for (FieldElement e : IteratorUtils.asIterable(it)) {
context.warn(e.element, e.primaryKeyElement.mirror,
"{} already declared as {}",
primaryKeyFieldElement, PrimaryKey.class);
}
} else {
primaryKeyFieldElement = FieldElement.firstPrimaryKey(fields);
if (primaryKeyFieldElement == null) {
context.error(element, "{element} did not declare any {}", PrimaryKey.class);
return null;
}
context.warn(element,
"{element} did not declare any {}, using {}",
PrimaryKey.class, primaryKeyFieldElement);
}
TableElement tableElement = TableElement.get(context, typeElement);
SerializerElement serializerElement = SerializerElement.get(context, typeElement);
return new SchemaElement(typeElement, tableElement, serializerElement);
return new SchemaElement(typeElement, tableElement, serializerElement, primaryKeyFieldElement);
}
static List<VariableElement> collectColumns(Context context, TypeElement typeElement) {
List<VariableElement> columns = new ArrayList<>();
static Collection<FieldElement> collectFieldElements(Context context, TypeElement typeElement) {
Collection<FieldElement> columns = new ArrayList<>();
TypeElement superclassElement = typeElement;
for (;;) {
for (Element e : superclassElement.getEnclosedElements()) {
switch (e.getKind()) {
case FIELD:
columns.add((VariableElement) e);
columns.add(FieldElement.get(context, (VariableElement) e));
break;
}
}
@ -50,14 +76,17 @@ final class SchemaElement {
final TypeElement element;
final TableElement tableElement;
final SerializerElement serializerElement;
final FieldElement primaryKeyFieldElement;
SchemaElement(
TypeElement element,
TableElement tableElement,
SerializerElement serializerElement) {
SerializerElement serializerElement,
FieldElement primaryKeyFieldElement) {
this.element = element;
this.tableElement = tableElement;
this.serializerElement = serializerElement;
this.primaryKeyFieldElement = primaryKeyFieldElement;
}
@Override
@ -66,6 +95,7 @@ final class SchemaElement {
.append("element", element)
.append("tableElement", tableElement)
.append("serializerElement", serializerElement)
.append("primaryKeyFieldElement", primaryKeyFieldElement)
.toString();
}
}