Created
December 8, 2019 12:59
-
-
Save asouza/c4e0df99b1b614878671b900e32e0d2e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class DataView<T> { | |
private T proxy; | |
private Trace trace; | |
private T original; | |
private Map<String, Object> complexValues = new HashMap<>(); | |
private DataView(T instance) { | |
Enhancer enhancer = new Enhancer(); | |
enhancer.setSuperclass(instance.getClass()); | |
this.trace = new Trace(instance); | |
enhancer.setCallback(this.trace); | |
this.proxy = (T) enhancer.create(); | |
this.original = instance; | |
} | |
public static <T> DataView<T> of(T instance) { | |
return new DataView<T>(instance); | |
} | |
public <ReturnType, MapperType> DataView<T> add(String key, Function<T, ReturnType> supplier, | |
Function<ReturnType, MapperType> mapper) { | |
MapperType finalObject = supplier.andThen(mapper).apply(original); | |
complexValues.put(key, finalObject); | |
return this; | |
} | |
public <ReturnType, MapperType> DataView<T> addCollection(String key, Function<T, Collection<ReturnType>> supplier, | |
Function<ReturnType, MapperType> mapper) { | |
Collection<ReturnType> collection = supplier.apply(original); | |
// using list to keep the original order | |
List<MapperType> resultList = collection.stream().map(mapper).collect(Collectors.toList()); | |
complexValues.put(key, resultList); | |
return this; | |
} | |
public DataView<T> add(Function<T, Object> supplier) { | |
supplier.apply(proxy); | |
return this; | |
} | |
public DataView<T> add(String key, Function<T, Object> supplier) { | |
complexValues.put(key, supplier.apply(original)); | |
return this; | |
} | |
public DataView<T> addDate(String key, Function<T, TemporalAccessor> supplier, String pattern) { | |
Function<TemporalAccessor, Object> formatter = (temporal) -> { | |
return DateTimeFormatter.ofPattern(pattern).format(temporal); | |
}; | |
return this.addFormatted(key, supplier, formatter); | |
} | |
public DataView<T> addPercentual(String key, Function<T, Number> supplier) { | |
Function<Number, Object> formatter = (number) -> { | |
DecimalFormat df = new DecimalFormat("##.##%"); | |
return df.format(number.doubleValue() / 100); | |
}; | |
return this.addFormatted(key, supplier, formatter); | |
} | |
public <ReturnType> DataView<T> addFormatted(String key, Function<T, ReturnType> supplier, | |
Function<ReturnType, Object> formatter) { | |
ReturnType result = supplier.apply(original); | |
complexValues.put(key, formatter.apply(result)); | |
return this; | |
} | |
public Map<String, Object> build() { | |
Map<String, Object> json = trace.getJson(); | |
complexValues.entrySet().forEach(entry -> { | |
json.put(entry.getKey(), entry.getValue()); | |
}); | |
return json; | |
} | |
} | |
class Trace implements MethodInterceptor { | |
private Map<String, Object> json = new HashMap<>(); | |
private Object instance; | |
public Trace(Object instance) { | |
this.instance = instance; | |
} | |
@Override | |
public Object intercept(Object proxy, Method currentMethod, Object[] args, MethodProxy proxyMethod) | |
throws Throwable { | |
String methodName = currentMethod.getName(); | |
//FIXME tem que fazer o mecanismo o de defesa para o caso de invocação de nome de metodo que nao comeca com getter ou is | |
String propertyName = Introspector.decapitalize(methodName.substring(methodName.startsWith("is") ? 2 : 3)); | |
Object methodResult = currentMethod.invoke(instance, args); | |
json.put(propertyName, methodResult); | |
return methodResult; | |
} | |
public Map<String, Object> getJson() { | |
return json; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment