Using enum as a mapper - java

I have a lot of different objects which are being mapped so I've written a bunch of static mapping methods and one giant switch-case method which takes the type (a built-in field) and then uses the specialized mapping function.
Example:
public static SomeOtherObject mapFrom(SomeObject someObject) {
//... mapping logic
return someOtherObjectInstance;
}
//... a bunch of those
// root/main mapper
public static SomeOtherObjectBase mapFrom(SomeObjectBase someObjectBase) {
switch(someObjectBase.getType()) {
case SOME_TYPE: return mapFrom((SomeObject)someObjectBase);
//...
}
}
I then thought that I could probably convert this to an enum where each enumeration would be a mapper and would be bound to the type, thus avoiding a switch-case... something like this:
public enum SomeObjectMappers {
SOME_TYPE_MAPPER(SOME_TYPE) {
#Override
SomeOtherObject mapFrom(SomeObject someObject) {
//... mapping logic
return someOtherObjectInstance;
}
},
//... a bunch of those
;
private final Type type;
//constructor, getters...
abstract <T extends SomeOtherObjectBase, U extends SomeObjectBase> T mapFrom(U obj);
public static SomeOtherObjectBase mapFrom(SomeObjectBase obj) {
return Arrays.stream(values())
.filter(v -> v.getType() == type)
.map(m -> m.mapFrom(obj))
.findFirst()
.orElse(null);
}
}
However this does not really compile/work as for some reason mapper implementation in SOME_TYPE_MAPPERdoes not accept concrete subclasses SomeOtherObject and SomeObject as valid signatures for the abstract method.
Can this not be done?

Related

JOOQ choose field Converter by another field

I want to convert between Set of Enum POJO and String[] Database(postgres) column.
and the enum class would be changed by another field type.
So I can say Enum class which's using in fooSet is changable and it's up to field type.
I know it's a messy. but I need a help.
Below are models
public interface A {
enum B implements A {
step1,
step2,
step3
}
enum C implements A {
step4,
step5,
step6
}
}
public abstract class Foo {
private String type;
}
public abstract class FooA {
private Set<B> fooSet;
}
public abstract class FooB {
private Set<C> fooSet;
}
I want to make a Converter like below.
SetOfEnumConverter<U extends Enum<U> & A> implements Converter<String[], Set<U>> {
#Override
public Set<U> from(String[] databaseObject) {
if (databaseObject == null) {
return null;
}
return Arrays.stream(databaseObject)
.map(x -> U.valueOf(U.class, x)). // here's the problem point
.collect(Collectors.toSet());
}
#Override
public String[] to(Set<U> userObject) {
if (userObject == null || userObject.isEmpty()) {
return null;
}
String[] strings = userObject.stream()
.map(Enum::name)
.toArray(String[]::new);
return ArrayUtils.isEmpty(strings) ? new String[0]: strings;
}
#Override
public Class<String[]> fromType() {
return String[].class;
}
#Override
public Class<Set<U>> toType() {
return (Class) TreeSet.class;
}
}
But the problem is I can't point .class attribute from a generic type maybe because of Generic Type erasure.
So, What I want to do is mapping the setEnum class to be used in the field fooSet according to the field type.
Because I have to make a single table for Foo and map from FooA, FooB and FooZ.
You can't do this without passing an actual Class<U> reference to your converter, e.g. like this:
SetOfEnumConverter<U extends Enum<U> & A> implements Converter<String[], Set<U>> {
final Class<U> u;
SetOfEnumConverter(Class<U> u) {
this.u = u;
}
// ...
}
And inside of the converter, you can use:
Enum.valueOf(u, x)
To look up arbitrary enum values by their names. Then, instantiate it with e.g.
new SetOfEnumConverter<>(MyEnum.class);

Can I set value for specific property of generic object in generic function in java?

I have a function which is responsible to save generic object like that:
public <T> T save(final T o){
return (T) getCurrentSession().save(o);
}
My object have some common specific properties such as createDate, createId, updateId, updateDate,...
Can I set these properties in my save function like:
o.setProperty("propertyName", value)
You can put bounds on the type parameter T to allow you to call methods on it from an interface you have defined:
interface MyObject {
void createDate();
void createId();
...
}
public <T extends MyObject> T save(final T o){
o.createDate();
return (T) getCurrentSession().save(o);
}
You can use Java Reflection API to create an universal setter.
A bit ugly, straightforward, not typesafe and too many Object values but still a working solution.
public Object setValue(Object classObject, String fieldIdentifier, Object value) {
Class<?> clazz = classObject.getClass();
Field retrievedField = Arrays.stream(clazz.getDeclaredFields())
.filter(field -> field.getName().equalsIgnoreCase(fieldIdentifier))
.findFirst().orElse(null);//add an exception here when null
retrievedField.setAccessible(true);
retrievedField.set(classObject, value);
return classObject;
}

Effective version of writing the following method

Is there an elegant and best approach to write the following method?
private void throwException(Object obj) {
if (obj instanceof ClassA) {
ClassA resp = (ClassA) obj;
throw new CustomException(resp.getMessage(), resp.getCode());
} else if (obj instanceof ClassB) {
ClassB resp = (ClassB) obj;
throw new CustomException(resp.getMessage(), resp.getCode());
}
}
Note that ClassA and ClassB has the same exact properties. My point is that, I don't want to repeat the throw statement as much as possible.
Define a map like
Map<Class<?>, Function<Object, ? extends RuntimeException>> handlers = new LinkedHashMap<>();
The handlers will contain a Function that you can use to map the Object passed to throwException to get an exception. The key of the map is a class and value is the function that will map an object of the type (class) of the key to an exception.
Populate the above map as
handlers.put(ClassA.class, (obj) -> new CustomException(((ClassA) obj).getMessage(), ((ClassA) obj).getCode));
handlers.put(ClassB.class, (obj) -> new CustomException(((ClassB) obj).getMessage(), ((ClassB) obj).getCode));
With this, throwException would look like,
private void throwException(Object obj) {
Function<Object, ? extends RuntimeException> handler = handlers.entrySet().stream()
.filter(entry -> entry.getKey().isAssignableFrom(obj.getClass()))
.map(Map.Entry::getValue)
.findFirst()
.orElseThrow(() -> new RuntimeException("No handler found")); //Or use a default using orElseGet
throw handler.apply(obj);
}
I agree that it moves the casting elsewhere to make the method look clean.
The key part is the line
.filter(entry -> entry.getKey().isAssignableFrom(obj.getClass()))
We are checking if the object (passed to throwException) is of type returned by entry.getKey (the class of the map key). So, if you have inheritance hierarchy among the classes (ClassA, ClassB..), then you must populate the map in such an order so that the most generic ones (say like Object.class) comes after more specific ones.
A consequence of putting an entry into handlers with Object.class as the first entry would mean that the function (value) of Object.class will always be picked up for any object passed to it.
You can use Function<>s to wrap the getters into a custom interface beforehand.
interface Wrapper {
String getMessage();
int getCode();
<T> Function<T, Wrapper<T>> of(Function<T,String> getMsg, Function<T, Integer> getCde) {
return object -> new Wrapper() {
public String getMessage() { return getMsg.apply(object); }
public int getCode() { return getCde.apply(object); }
}
}
}
class Thrower {
Map<Class<?>, Supplier<Wrapper>> wrappers = new HashMap();
static {
wrappers.put(A.class, Wrapper.of(A.class, A::getMessage, A::getCode));
wrappers.put(B.class, Wrapper.of(B.class, B::getMessage, B::getCode));
}
void throwException(Object o) {
Wrapper wrapper = wrappers.get(o.getClass()).apply(o);
throw new CustomException(wrapper.getMessage(), wrapper.getCode());
}
}
You can kill two birds with one stone as this is a classical problem in the clean code design where you can choose to implement Visitor Design Pattern as a workaround to multiple If/else instanceof type of conditioning with a little bit of expansion to cover the problem of excessive throwing of new CustomExeption.
Here is what I can suggest you :
First it's better to change you design for ClassA and ClassB as:
abstract class ClassParent {
// your fields
public ClassParent (//your fields) {
// initializing your fields
}
public abstract void accept(ClassVisitor cv);
}
class ClassA extends ClassParent {
public ClassA(//your fileds) {
super(//your fileds);
}
/// other Implementation
public void accept(ClassVisitor cv) {
cv.visit(this);
}
}
class ClassB extends ClassParent {
public ClassB(//your fileds) {
super(//your fileds);
}
/// other Implementation
public void accept(ClassVisitor cv) {
cv.visit(this);
}
}
Now define your vistors as :
interface ClassVisitor {
abstract void visit(ClassA classA);
abstract void visit(ClassB classB);
}
class Visitor implements ClassVisitor {
public void visit(ClassA classA) {
classA.DoSomthing();
}
public void visit(ClassB classB) {
classB.DoSomthing();
}
}
Now it your ThrowException you can define :
private ClassVisitor visitor = new Visitor();
public void ThrowException(ClassParent classParent){
classParent.accept(visitor);
throw new CustomException(classParent.getMessage(), classParent.getCode);
}
This way you achieve both a cleaner code, more maintainable with
higher readablity by avoiding duplicate codes at the same time.

Step builder pattern using delegation and enums?

I have this project I'm working on and basically this is what I would like to achieve.
This is what I have:
MyObject obj = MyObject.builder()
.withValue("string")
.withAnotherValue("string")
.build();
MyObject obj = MyObject.builder()
.withValue("string")
.withAnotherValue("string")
.withField("key", "value")
.build();
So the step builder pattern forces the user to use the withValue() method and the withAnotherValue() method in that order. The method field() is optional and can be used as many times as you want.I followed this website for example http://www.svlada.com/step-builder-pattern/
So what I would like to achieve is this:
MyObject obj = MyObject.builder(Type.ROCK)
.withColour("blue")
.withValue("string")
.withAnotherValue("string")
.build();
MyObject obj = MyObject.builder(Type.STONE)
.withWeight("heavy")
.withValue("string")
.withAnotherValue("string")
.withField("key", "value")
.build();
So in the builder() method you'd put an enum type and based on the enum you'd have a different set of methods appear. So for ROCK the withValue(),withAnotherValue() and withColour() are now mandatory. But for STONE withWeight(), withAnotherValue() and withColour() are mandatory.
I something like this possible? I have been trying for the past two days to figure this out but I just can't seem to get it to give specific methods for each type. It just shows all the methods in the Builder.
Any thoughts and help is much appreciated.
Code:
Enum
public enum Type implements ParameterType<Type> {
ROCK, STONE
}
ParameterType
interface ParameterType<T> {}
MyObject
public class MyObject implements Serializable {
private static final long serialVersionUID = -4970453769180420689L;
private List<Field> fields = new ArrayList<>();
private MyObject() {
}
public interface Type {
Value withValue(String value);
}
public interface Value {
Build withAnotherValue(String anotherValue);
}
public interface Build {
MyObject build();
}
public Type builder(Parameter type) {
return new Builder();
}
public static class Builder implements Build, Type, Value {
private final List<Field> fields = new ArrayList<>();
#Override
public Build withAnotherValue(String anotherValue) {
fields.add(new Field("AnotherValue", anotherValue));
return this;
}
#Override
public Value withValue(String value) {
fields.add(new Field("Value", value));
return this;
}
#Override
public MyObject build() {
MyObject myObject = new MyObject();
myObject.fields.addAll(this.fields);
return myObject;
}
}
}
This isn't possible using enum, but you could do this with a custom enum-like class:
public final class Type<B extends MyObject.Builder> {
private final Supplier<? extends B> supplier;
private Type(Supplier<? extends B> supplier) {
this.supplier = Objects.requireNonNull(supplier);
}
public B builder() {
return supplier.get();
}
public static final Type<MyObject.RockBuilder> ROCK =
new Type<>(MyObject.RockBuilder::new);
public static final Type<MyObject.StoneBuilder> STONE =
new Type<>(MyObject.StoneBuilder::new);
}
public class MyObject {
// ...
// And this method is probably superfluous at this point.
public static <B extends MyObject.Builder> builder(Type<? extends B> type) {
return type.builder();
}
}
You could adapt that approach to a step builder easily, but there's a separate issue here. Since each step in a step builder specifies the next step in the return type, you can't re-use step interfaces very easily. You would need to declare, for example, separate interfaces RockValueStep, StoneValueStep, etc. because the interfaces themselves specify the step order.
The only simple way around that would be if the separate types (rock, stone, etc.) only strictly added steps such that e.g. Type.ROCK returns a ColourStep and Type.STONE returns a WeightStep, and both ColourStep and WeightStep return ValueStep:
// Rock builder starts here.
interface ColourStep { ValueStep withColour(String c); }
// Stone builder starts here.
interface WeightStep { ValueStep withWeight(String w); }
// Shared.
interface ValueStep { AnotherValueStep withValue(String v); }
And then:
public final class Type<B /* extends ABuilderStepMarker, possibly */> {
// (Constructor and stuff basically same as before.)
public static final Type<MyObject.ColourStep> ROCK =
new Type<>(/* implementation */::new);
public static final Type<MyObject.WeightStep> STONE =
new Type<>(/* implementation */::new);
}
The reasons this kind of thing can't be done using enum are pretty much:
enum can't be generic:
// This is an error.
enum Type<T> {
}
Although you could declare an abstract method on an enum and override it with a covariant return type, the covariant return type is never visible:
// This is valid code, but the actual type of
// Type.ROCK is just Type, so the return type of
// Type.ROCK.builder() is just MyObject.Builder,
// despite the override.
enum Type {
ROCK {
#Override
public MyObject.RockBuilder builder() {
return new MyObject.RockBuilder();
}
};
public abstract MyObject.Builder builder();
}
Considering you are looking for specific methods for a specific type of builder, having multiple builders, one for each type of MyObject that can be built may work best. You can create an interface that defines the builder and then put the common functionality into an abstract class, from which the individual builders extend. For example:
public interface Builder {
public MyObject build();
}
public abstract class AbstractBuilder() {
private final List<Field> fields = new ArrayList<>();
protected void addField(String key, String value) {
fields.add(new Field(key, value));
}
#Override
public MyObject build() {
MyObject myObject = new MyObject();
myObject.fields.addAll(this.fields);
return myObject;
}
}
public class StoneBuilder extends AbstractBuilder {
public StoneBuilder withValue(String value) {
addField("Value", value);
return this;
}
// ...More builder methods...
}
public class RockBuilder extends AbstractBuilder {
public RockBuilder withAnotherValue(String value) {
addField("AnotherValue", value);
return this;
}
// ...More builder methods...
}
This allows you to build MyObject instances in the following manner:
MyObject obj = new RockBuilder()
.withValue("string")
.build();
MyObject obj = new StoneBuilder()
.withAnotherValue("string")
.build();
Your question can be generalised as follows: "How can I write the following method?"
public <T extends AbstractBuilder> T builder(final SomeNonGenericObject object) {
// code goes here
}
And the answer is: "You cannot, because there is no way for the compiler to infer what the type of T is. The only way that this is possible is by somehow passing T as a parameter:
public <T extends AbstractBuilder> T builder(final SomeNonGenericObject object, final Class<T> builderClass) {
// code goes here
}
or
public <T extends AbstractBuilder> T builder(final SomeGenericObject<T> object) {
// code goes here
}
For example:
public <T extends AbstractBuilder> T builder(final Supplier<T> object) {
return supplier.get();
}
final Supplier<AbstractBuilder> rockBuilderSupplier = RockBuilder::new;
builder(rockBuilerSupplier)
.withColour("blue")
// etc
Or simply use Justin Albano's answer, which works just as well.

Type safety with different generic values in collection

Suppose I have an interface like this;
interface Validator<T>{
void validate<T value>
}
And these implementations ;
class StringValidator implements Validator<String>{
void validate<String value>{}
}
class OrderValidator implements Validator<Order>{
void validate<Order value>{}
}
In ValidatorRegisterer class I have a map;
class ValidationRegisterer{
Map<String, Validator> validatorsForPath = new HashMap<String, Validator>();
public Map<String, Validator> registerers(){
return validatorsForPath;
}
public void register(String path, Validator validator){
validatorsForPath.put(path, validator);
}
}
What I want is to iterate over this map in ValidationManager class with type safety;
class ValidationManager<RootObject>{
List<ValidationRegisterer> validationRegisterers;
public ValidationManager(List<ValidationRegisterer> validationRegisterers){
this.validationRegisterers = validationRegisterers;
}
public void validate(RootObject object){
for(ValidationRegisterer validationRegisterer in validationRegisterers){
for(String path : validationRegisterer.keySet()){
Object value = object.getPath(path);
Validator validator = validationRegisterer.get(path);
validator.validate(value);
//this line gets unchecked call to validate(T) warning and I want to get rid of it
//the problem is validationRegisterers map can contain both StringValidator and OrderValidator,
//so the value can be a String or an Order
//do I have to cast the value to the type of validator's T type?
}
}
}
Map<String, Validator> validatorsForPath = new HashMap<String, Validator>();
}
I tried to explain the situation in the last code sample comments.
Declare as follows to remove warnings :
Validator<Object> validator = validationRegisterer.get(path);
In this case you are declaring the validator reference that would work on Object type.
later you can typecast to Order or String after doing an instanceof test.
You need to make ValidationRegisterer class generic like this:
class ValidationRegisterer<T extends Validator> {
Map<String, T> validatorsForPath = new HashMap<String, T>();
public Map<String, T> registerers(){
return validatorsForPath;
}
public void register(String path, T validator){
validatorsForPath.put(path, validator);
}
}
And then maintain separate lists for these two types of ValidationRegisterer
class ValidationManager {
List<ValidationRegisterer<StringValidator>> strValidationRegisterers;
List<ValidationRegisterer<OrderValidator>> ordValidationRegisterers;
....
}
I will assume that with "type safety" you mean that you want to be certain that the object returned for a certain path is really of the type that the associated Validator accepts.
One problem is that the type parameter for the Validator is not available at compile time since, as you say yourself, any kind of Validator can be in the map.
Also, object.getPath(path) will always return an Object which will always need casting at runtime, so the fact that the validate method limits its argument to type T is of little use.
So the best you can do is make validation fail fast in case the object is not of the correct type.
A solution would be to
1. store the Class object for the Validator,
2. let validate accept an Object as parameter and dynamically cast the object to the validator type at the beginning of the validate method. This can be done in an abstract base class.
Example:
interface Validator<T> {
void validate(Object value);
Class<T> getType();
}
abstract class BaseValidator<T> implements Validator<T> {
private final Class<T> type;
public BaseValidator(Class<T> type) {
this.type = type;
}
public final void validate(Object o) {
doValidate(type.cast(o)); // wrong type will fail fast here
}
public final Class<T> getType() {
return type;
}
protected abstract void doValidate(T value);
}
class StringValidator extends BaseValidator<String> {
public StringValidator() {
super(String.class);
}
protected void doValidate(String value) {
// do actual string validation here
}
}
An alternative solution if you want to keep Object out of the Validator interface would be to let the path be resolved by a type parameterized object that has a reference the validator and performs the dynamic cast, and keep that in your registry map as value:
interface Validator<T> {
void validate(final T value);
}
class PathValidator<T> {
private final Class<T> type;
private final Validator<T> validator;
public PathValidator(final Class<T> type, final Validator<T> validator) {
this.type = type;
this.validator = validator;
}
public void validate(final RootObject object, final String path) {
T value = type.cast(object.getPath(path)); // throws ClassCastException here if not the correct type
validator.validate(value);
}
}
You would then have a Map<String, PathValidator<?> in your ValidationRegisterer class.
I'd personally prefer this alternative solution.

Categories