
com.crabshue.commons.aggregator.Analysed Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of commons-aggregator Show documentation
Show all versions of commons-aggregator Show documentation
Library aggregating fields using annotations in complex objects structures
The newest version!
package com.crabshue.commons.aggregator;
import com.crabshue.commons.aggregator.model.Collect;
import com.crabshue.commons.aggregator.model.Execute;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.*;
@Data
@Slf4j
class Analysed {
private CLASS_TYPE classType;
private String classContext;
private List classCollects;
private Map> collects;
private Map> executes;
private Map variables;
private List otherFields;
@Override
public String toString() {
return "Analysed{" +
"classType=" + classType +
", classContext='" + classContext + '\'' +
", classCollects=" + classCollects +
", collects=" + collects +
", executes=" + executes +
", variables=" + variables +
", otherFields=" + otherFields +
'}';
}
Analysed(Class objectClass, IgnorableClassDetector ignorableClassDetector) {
Context cx = (Context) objectClass.getDeclaredAnnotation(Context.class);
classContext = cx == null ? null : cx.value();
classCollects = analyse(null,
(com.crabshue.commons.aggregator.Collect[]) objectClass.getDeclaredAnnotationsByType(
com.crabshue.commons.aggregator.Collect.class));
if (classCollects.size() == 0)
classCollects = null;
if (objectClass.isArray()) {
classType = CLASS_TYPE.ARRAY;
} else if (List.class.isAssignableFrom(objectClass)) {
classType = CLASS_TYPE.LIST;
} else if (Map.class.isAssignableFrom(objectClass)) {
classType = CLASS_TYPE.MAP;
} else if (Iterable.class.isAssignableFrom(objectClass)) {
classType = CLASS_TYPE.ITERABLE;
} else if (objectClass.isPrimitive()) {
classType = CLASS_TYPE.IGNORABLE;
} else if (!isProcessable(objectClass)) {
classType = CLASS_TYPE.IGNORABLE;
} else if (ignorableClassDetector.canIgnore(objectClass)) {
classType = CLASS_TYPE.IGNORABLE;
} else {
classType = CLASS_TYPE.PROCESSABLE;
variables = new HashMap<>();
executes = new HashMap<>();
collects = new HashMap<>();
otherFields = new ArrayList<>();
for (Field f : getFields(objectClass)) {
Variable variable = f.getDeclaredAnnotation(Variable.class);
if (variable != null) {
variables.put(f.getName(), variable.value());
}
com.crabshue.commons.aggregator.Execute[] executors = f.getDeclaredAnnotationsByType(
com.crabshue.commons.aggregator.Execute.class);
com.crabshue.commons.aggregator.Collect[] collectors = f.getDeclaredAnnotationsByType(
com.crabshue.commons.aggregator.Collect.class);
String fieldName = sanitizeFieldName(f.getName());
if (!isProcessable(objectClass, f, fieldName)) {
continue;
}
boolean executorsExist = executors != null && executors.length > 0;
boolean collectorsExist = collectors != null && collectors.length > 0;
if (executorsExist) {
executes.put(fieldName, analyse(fieldName, executors));
}
if (collectorsExist) {
collects.put(fieldName, analyse(fieldName, collectors));
}
if (!executorsExist && !collectorsExist) {
otherFields.add(fieldName);
}
}
}
}
public static boolean isProcessable(Class objectClass) {
if (!Modifier.isPublic(objectClass.getModifiers())) {
logger.warn("Ignoring non public class:'{}', as it will likely fail any evaluation", objectClass.getName());
return false;
}
return true;
}
public static boolean isProcessable(Class clazz, Field f, String fieldName) {
if (!Modifier.isPublic(f.getModifiers()) && !hasPublicAccessor(clazz, fieldName)) {
logger.warn("Ignoring non public field:'{}' of class:'{}', as it will likely fail any evaluation", fieldName, clazz.getName());
return false;
}
return true;
}
private static boolean hasPublicAccessor(Class clazz, String fieldName) {
String accessorName = "get" + Character.toUpperCase(fieldName.charAt(0)) + fieldName.substring(1);
try {
return Modifier.isPublic(clazz.getMethod(accessorName).getModifiers());
} catch (NoSuchMethodException e) {
return false;
}
}
Analysed() {
classCollects = new ArrayList<>();
otherFields = new ArrayList<>();
collects = new HashMap<>();
executes = new HashMap<>();
variables = new HashMap<>();
}
private static List getFields(Class baseClass) {
ArrayList ret = new ArrayList<>();
while (baseClass != null && baseClass != Object.class) {
Collections.addAll(ret, baseClass.getDeclaredFields());
baseClass = baseClass.getSuperclass();
}
return ret;
}
private List analyse(String field, com.crabshue.commons.aggregator.Execute[] executes) {
List executeList = new ArrayList<>();
for (com.crabshue.commons.aggregator.Execute execute : executes) {
executeList.add(new Execute(field, execute.value(), execute.when()));
}
return executeList;
}
private List analyse(String field, com.crabshue.commons.aggregator.Collect[] collects) {
List ret = new ArrayList<>();
for (com.crabshue.commons.aggregator.Collect collect : collects) {
ret.add(new Collect(field, collect.what(), collect.value(), collect.when()));
}
return ret;
}
private String sanitizeFieldName(String name) {
//TODO: also do for or and eq ne lt gt le ge div mod not null true false new var return
if ("size".equals(name)) {
return "'" + name + "'";
}
return name;
}
void addExecute(String field, String jexl, String when) {
Execute ex = new Execute(field, jexl, when);
field = sanitizeFieldName(field);
if (!executes.containsKey(field)) {
executes.put(field, new ArrayList<>());
}
executes.get(field).add(ex);
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
Analysed analysed = (Analysed) o;
if (classType != analysed.classType)
return false;
if (classContext != null ? !classContext.equals(analysed.classContext) : analysed.classContext != null)
return false;
if (classCollects != null ? !classCollects.equals(analysed.classCollects) : analysed.classCollects != null)
return false;
if (collects != null ? !collects.equals(analysed.collects) : analysed.collects != null)
return false;
if (executes != null ? !executes.equals(analysed.executes) : analysed.executes != null)
return false;
if (variables != null ? !variables.equals(analysed.variables) : analysed.variables != null)
return false;
return otherFields != null ? otherFields.equals(analysed.otherFields) : analysed.otherFields == null;
}
@Override
public int hashCode() {
return Objects.hash(classType, classContext, classCollects, collects, executes, variables, otherFields);
}
void addCollectField(String field, String to, String when) {
field = sanitizeFieldName(field);
Collect collect = new Collect(field, null, to, when);
if (!collects.containsKey(field)) {
collects.put(field, new ArrayList<>());
}
collects.get(field).add(collect);
}
void addCollectClass(String what, String to, String when) {
classCollects.add(new Collect(null, what, to, when));
}
void addVariable(String field, String variable) {
field = sanitizeFieldName(field);
variables.put(field, variable);
}
void addOtherFields(Class clazz) {
for (Field f : getFields(clazz)) {
String fieldName = sanitizeFieldName(f.getName());
//check static
if (!executes.containsKey(fieldName) && !collects.containsKey(fieldName) && isProcessable(clazz, f, fieldName))
otherFields.add(fieldName);
}
}
void prune() {
if (classCollects.isEmpty())
classCollects = null;
}
public enum CLASS_TYPE {ARRAY, LIST, MAP, ITERABLE, IGNORABLE, PROCESSABLE}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy