How to pass a getter as lambda function? - java

I want to pass the getter of a bean as a function. When the function is called the getter should be invoked. Example:
public class MyConverter {
public MyConverter(Function f) {
this.f = f;
}
public void process(DTO dto) {
// I just want to call the function with the dto, and the DTO::getList should be called
List<?> list = f.call(dto);
}
}
public class DTO {
private List<String> list;
public List<String> getList() { return list; }
}
Is that possible with java 8?

If the constructor of MyConverter must take a function, and process must take an object, this is probably the best way:
class MyConverter<T> {
// V takes a thing (in our case a DTO)
// V returns a list of Strings
private Function<T, List<String>> f;
public MyConverter(Function<T, List<String>> f) {
this.f = f;
}
public void process(T processable) {
List<String> list = f.apply(processable);
}
}
MyConverter<DTO> converter = new MyConverter<>(DTO::getList);
DTO dto = new DTO();
converter.process(dto);

Related

Exception java.lang.IllegalArgumentException: is not an interface when using dynamic proxies

I want to implement a generic functionality which would enable that our domain classes are being proxied for the case that its values to be xml compliant (escaping special characters in strings). The domain classes/objects are being generated, so that they can not be changed by me. What I tried to do was following code for the generation of proxies:
public class StringValuesFormatterForXml implements InvocationHandler {
public static interface IA {
String getMa1();
List<? extends IB> getBs();
}
public static class A implements IA {
#Override
public String getMa1() {
return "Ma1";
}
#Override
public List<? extends IB> getBs() {
return Arrays.asList(new B(), new B());
}
}
public static interface IB {
String getMb1();
String getMb2();
}
public static class B implements IB {
#Override
public String getMb1() {
return "Mb1";
}
#Override
public String getMb2() {
return "Mb2";
}
}
Object destObj;
private final Map<String, Method> methods = new HashMap<>();
#SuppressWarnings("unchecked")
public static IA createProxyA(IA destObj) {
return (IA) Proxy.newProxyInstance(destObj.getClass().getClassLoader(), new Class[] {
IA.class
}, new StringValuesFormatterForXml(destObj));
}
#SuppressWarnings("unchecked")
public static Object createProxy(Object destObj, Class<?> clazz) {
return Proxy.newProxyInstance(destObj.getClass().getClassLoader(), new Class[] {
clazz
}, new StringValuesFormatterForXml(destObj));
}
public StringValuesFormatterForXml(Object destObj) {
this.destObj = destObj;
for (Method method : destObj.getClass().getMethods()) {
this.methods.put(method.getName(), method);
}
}
#Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getReturnType().isAssignableFrom(List.class)) {
List<Object> elems = (List<Object>) method.invoke(destObj, args);
List<Object> proxyElems = new ArrayList<Object>();
for (Object obj : elems) {
Object proxyObj = createProxy(obj, obj.getClass());
proxyElems.add(proxyObj);
}
return proxyElems;
}
return method.invoke(destObj, args); // Here I will format the output for xml
}
public static void main(String[] args) {
A orig = new A();
IA proxy1 = createProxyA(orig);
A proxy2 = (A) createProxy(orig, orig.getClass());
}
}
Code in createProxy(orig, orig.getClass()) throws following error java.lang.IllegalArgumentException: StringValuesFormatterForXml$A is not an interface but the code createProxyA(orig) does not. So it seems that I would need to have a separate creator method for every interface which I use. In our domain model there are many classes and I do not want to create for every class separate creator.
Are there any other ways/frameworks which are better suited for my case of proxying objects.
Your createProxy method does work, you just have to pass the class of the interface as second parameter:
A orig = new A();
IA proxy1 = (IA) createProxy(orig, IA.class);
In addition I would recomment you to use the createProxy function as a generic function in order to avoid the obkect cast:
#SuppressWarnings("unchecked")
public static <T> T createProxyB(T destObj, Class<T> clazz) {
return (T) Proxy.newProxyInstance(destObj.getClass().getClassLoader(), new Class[] { clazz },
new StringValuesFormatterForXml(destObj));
}
In this case you can call the function like this:
A orig = new A();
IA proxy1 = createProxyB(orig, IA.class);

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);

How to add generic object to list in java?

How to add a generic object to list in java?
Currently, I have two classes doing the same function and would like to integrate them together
public class MyClass1 {
private List<Object1> myList = new ArrayList<>();
public void addList(Object1 o) {
myList.add(o);
}
}
public class MyClass2 {
private List<Object2> myList = new ArrayList<>();
public void addList(Object2 o) {
myList.add(o);
}
}
something like
public class MyClass {
private List<Object> myList = new ArrayList<>();
public void addList(Object o) {
myList.add(o);
}
}
You could make your own class generic:
public class MyClass<T> {
private List<T> myList = new ArrayList<>();
public void addList(T o) {
myList.add(o);
}
}
You can make both classes Object1 and Object2 implement the same interface 'ObjInterface'
public class MyClass {
private List<ObjInterface> myList = new ArrayList<>();
public void addList(ObjInterface o) {
myList.add(o);
}
}
If you want the class to contain only Object1 or only Object2 and never anything else, you can combine the other two answers:
interface ObjInterface {
// may be empty
}
public class MyClass<T extends ObjInterface> {
private List<T> myList = new ArrayList<>();
public void addList(T o) {
myList.add(o);
}
}
MyClass<Object1> object1only = new MyClass<>();
MyClass<Object2> object2only = new MyClass<>();
and add implements ObjInterface to the definitions of Object1 and Object2.
If you add methods common to both classes to ObjInterface, you can call those methods on the T objects in MyClass, since they're guaranteed to be a subclass of ObjInterface.

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.

Getting key from object for Map using object and interface

I have a Table class that implements a ForwardingMultimap of a certain type of object. I was wondering if it was over-doing it to create an interface that extracted the key from the object so it wouldn't be annoying for the caller to handle "Entry" objects when they call "values". Or would it just be better to have the caller put the object and key in themselves? If this is okay, would creating a separate class to handle each key like below be better, or should the caller implement it themselves ?
public class CustomObject {
public String propertyOne;
public int propertyTwo;
}
public interface ITableAggKey {
Object getKey(CustomObject customObj);
}
public class Table extends ForwardingMultimap<Object, CustomObject> {
Multimap m_map;
public Table(ITableAggKey aggKey){
m_map = HashMultimap.create();
m_aggKey = aggKey;
}
public boolean put(CustomObject obj) {
m_map.put(m_aggKey.getKey(obj), obj);
}
}
public class CustomObjectAggKeys {
public static final aggKeyOne = new ITableAggKey(){
#Overide
public Object getKey(CustomObject obj){
return obj.propertyOne;
}
};
public static final aggKeyOne = new ITableAggKey(){
#Overide
public Object getKey(CustomObject obj){
return obj.propertyTwo;
}
};
}
public class Table<K, T> extends ForwardingMultimap<K, T> {
Multimap<K, T> m_map;
Function<T, K> m_aggKey;
public Table(Function<T, K> aggKey){
m_map = HashMultimap.create();
m_aggKey = aggKey;
}
public boolean put(T obj) {
m_map.put(m_aggKey.apply(obj), obj);
}
}
public static void main(String[] args) {
Table<String, CustomObject> IndexOne = new Table<>(x -> x.propertyOne);
Table<Integer, CustomObject> IndexTwo = new Table<>(x -> x.propertyTwo);
}
If you cannot use Java8. Add Function interface.
public interface Function<T, K> {
K apply(T arg);
}
And
Table<String, CustomObject> indexOne = new Table<>(new Function<CustomObject, String>() {
#Override public String apply(CustomObject obj) {
return obj.propertyOne;
}
});

Categories