![JAR search and dependency download from the Maven repository](/logo.png)
in.workarounds.bundler.compiler.model.ReqBundlerModel Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of bundler-compiler Show documentation
Show all versions of bundler-compiler Show documentation
Compiler for bundler library
The newest version!
package in.workarounds.bundler.compiler.model;
import com.squareup.javapoet.ClassName;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Types;
import in.workarounds.bundler.annotations.Arg;
import in.workarounds.bundler.annotations.RequireBundler;
import in.workarounds.bundler.annotations.State;
import in.workarounds.bundler.compiler.Provider;
import in.workarounds.bundler.compiler.util.names.ClassProvider;
/**
* Created by madki on 16/10/15.
*/
public class ReqBundlerModel {
private static final String ACTIVITY = "android.app.Activity";
private static final String FRAGMENT = "android.app.Fragment";
private static final String FRAGMENT_V4 = "android.support.v4.app.Fragment";
private static final String SERVICE = "android.app.Service";
private VARIETY variety;
private ClassName className;
private Element element;
private String bundlerMethodName;
private boolean requireAll;
private List states;
private List args;
public ReqBundlerModel(Element element, Provider provider) {
init(element, provider);
args = retrieveArgs(element, provider);
states = retrieveStates(element, provider);
validateKeys(element, provider);
}
public ReqBundlerModel(Element element, ReqBundlerModel superClass, Provider provider) {
init(element, provider);
RequireBundler annotation = element.getAnnotation(RequireBundler.class);
if (annotation.inheritState()) {
states = getInheritedFields(retrieveStates(element, provider), superClass.getStates());
} else {
states = retrieveStates(element, provider);
}
if (annotation.inheritArgs()) {
args = getInheritedFields(retrieveArgs(element, provider), superClass.getArgs());
} else {
args = retrieveArgs(element, provider);
}
}
private void init(Element element, Provider provider) {
if (element.getKind() != ElementKind.CLASS) {
provider.error(element, "@%s annotation used on a non-class element %s",
RequireBundler.class.getSimpleName(),
element.getSimpleName());
provider.reportError();
return;
}
this.element = element;
RequireBundler annotation = element.getAnnotation(RequireBundler.class);
this.bundlerMethodName = annotation.bundlerMethod();
this.requireAll = annotation.requireAll();
variety = getVariety((TypeElement) element, provider.typeUtils());
String qualifiedName = ((TypeElement) element).getQualifiedName().toString();
className = ClassName.bestGuess(qualifiedName);
}
private void validateKeys(Element element, Provider provider) {
Map> argKeys = new HashMap<>();
Map> stateKeys = new HashMap<>();
mapKeys(args, argKeys);
mapKeys(states, stateKeys);
checkForErrors(args, argKeys, element, provider);
checkForErrors(states, stateKeys, element, provider);
}
private void checkForErrors(List extends AnnotatedField> fields,
Map> map,
Element element, Provider provider) {
if(map.size() == fields.size()) return;
for(Map.Entry> entry: map.entrySet()) {
if(entry.getValue().size() > 1) {
reportDuplicateKeys(entry.getKey(), entry.getValue(), element, provider);
}
}
}
private void reportDuplicateKeys(String key, List duplicateFields, Element element, Provider provider) {
StringBuilder error = new StringBuilder("Multiple fields {");
AnnotatedField field = null;
for (int i = 0; i < duplicateFields.size(); i++) {
field = duplicateFields.get(i);
error.append(field.getLabel());
if(i != duplicateFields.size() - 1) error.append(", ");
}
error.append("} in ")
.append(className.simpleName())
.append(" annotated with @")
.append(field != null ? field.getAnnotation().getSimpleName() : "?")
.append(" have the same key ")
.append("\"")
.append(key)
.append("\"")
.append(". Please make them unique.");
provider.error(element, error.toString());
}
private void mapKeys(List extends AnnotatedField> fields, Map> map) {
String key;
for (AnnotatedField field : fields) {
key = field.getKeyValue();
if (map.containsKey(key)) {
map.get(key).add(field);
} else {
List temp = new ArrayList<>();
temp.add(field);
map.put(key, temp);
}
}
}
private List getInheritedFields(List currentFields, List superFields) {
List tempFields = new ArrayList<>();
tempFields.addAll(superFields);
for (AnnotatedField field : currentFields) {
removeIfLabelPresent(field.getLabel(), tempFields);
}
tempFields.addAll(currentFields);
return tempFields;
}
private void removeIfLabelPresent(String label, List extends AnnotatedField> fields) {
AnnotatedField foundField = null;
for (AnnotatedField field : fields) {
if (field.getLabel().equals(label)) {
foundField = field;
}
}
if (foundField != null) {
fields.remove(foundField);
}
}
private List retrieveStates(Element element, Provider provider) {
List tempStates = new ArrayList<>();
for (Element enclosedElement : element.getEnclosedElements()) {
State instanceState = enclosedElement.getAnnotation(State.class);
if (instanceState != null) {
ClassName serializer = AnnotatedField.serializer(instanceState);
if (serializer == null)
reportInvalidSerializer(enclosedElement, State.class, provider);
StateModel state = new StateModel(enclosedElement, provider, serializer, instanceState.key());
tempStates.add(state);
}
}
return tempStates;
}
private List retrieveArgs(Element element, Provider provider) {
List tempArgs = new ArrayList<>();
for (Element enclosedElement : element.getEnclosedElements()) {
Arg arg = enclosedElement.getAnnotation(Arg.class);
if (arg != null) {
ClassName serializer = AnnotatedField.serializer(arg);
if (serializer == null)
reportInvalidSerializer(enclosedElement, Arg.class, provider);
ArgModel argModel = new ArgModel(enclosedElement, provider, requireAll(), serializer, arg.key());
tempArgs.add(argModel);
}
}
return tempArgs;
}
private void reportInvalidSerializer(Element element, Class annotation, Provider provider) {
provider.error(element,
"The serializer provided with @%s annotation does not implement %s. Please provide a valid serializer",
annotation.getSimpleName(), ClassProvider.serializer.simpleName());
}
private VARIETY getVariety(TypeElement element, Types typeUtils) {
// Check subclassing
TypeElement currentClass = element;
while (true) {
TypeMirror superClassType = currentClass.getSuperclass();
if (superClassType.getKind() == TypeKind.NONE) {
// Basis class (java.lang.Object) reached, so exit
return VARIETY.OTHER;
}
if (getVariety(superClassType.toString()) != VARIETY.OTHER) {
// Required super class found
return getVariety(superClassType.toString());
}
// Moving up in inheritance tree
currentClass = (TypeElement) typeUtils.asElement(superClassType);
}
}
private VARIETY getVariety(String className) {
switch (className) {
case ACTIVITY:
return VARIETY.ACTIVITY;
case FRAGMENT:
return VARIETY.FRAGMENT;
case FRAGMENT_V4:
return VARIETY.FRAGMENT_V4;
case SERVICE:
return VARIETY.SERVICE;
default:
return VARIETY.OTHER;
}
}
public List getRequiredArgs() {
List requiredArgs = new ArrayList<>();
for (ArgModel arg : getArgs()) {
if (arg.isRequired()) {
requiredArgs.add(arg);
}
}
return requiredArgs;
}
public boolean requireAll() {
return this.requireAll;
}
public String getBundlerMethodName() {
return this.bundlerMethodName;
}
public Element getElement() {
return element;
}
public VARIETY getVariety() {
return variety;
}
public String getSimpleName() {
return className.simpleName();
}
public String getPackageName() {
return className.packageName();
}
public ClassName getClassName() {
return className;
}
public enum VARIETY {
ACTIVITY,
FRAGMENT,
FRAGMENT_V4,
SERVICE,
OTHER
}
public List getArgs() {
return args;
}
public List getStates() {
return states;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy