Chilis
Chilis

Reputation: 27

How to get specific class and attribute using java 8

I've defined the following set of data

Response response = new Response();
        List<ObjectTest> objList = new ArrayList<ObjectTest>();

        objList.add(new ObjectTest(new Attributes(new FirstName("ab","1"),new LastName("hernandez","2"))));
        objList.add(new ObjectTest(new Attributes(new FirstName("jose","1"),new LastName("perez","2"))));
        objList.add(new ObjectTest(new Attributes(new FirstName("paco","2"),new LastName("jackson","2"))));
        objList.add(new ObjectTest(new Attributes(new FirstName("pedro","1"),new LastName("herrera","2"))));
        objList.add(new ObjectTest(new Attributes(new FirstName("juan","2"),new LastName("flores","2"))));

       response.setObjectList(objList);

So based on what the user selects I need to be able to get the specific class and the attribute, for example:

if the user selects [Attributes - FirstName - value] the output would be : ab jose paco pedro juan

if the user selects [Attributes - LastName- status] the output would be: 2 2 2 2 2

The problem here is that I dont know how to get the specific class in runtime. Also the main object could have any number of classes inside of it like MainClass.ClassA.ClasstB.ClassX.classAttributeValue. The only thing that I know is that the last value is going to be the one that I have to take in that case I have to print classAttributeValue . Any ideas how to solve this using java 8 ?

Upvotes: 1

Views: 790

Answers (3)

Chilis
Chilis

Reputation: 27

Thank you for your responses, what I finally did was to use JsonNode and based on the attribute I wanted to get I was iterating the same object and assign the result to se same object for example:

Json Response: Object.Person1.firstName.value

I created an array of that and split it by "." then I created a for and I used this jsonNode = jsonNode.get(inputArray[x]);

at the end the last element of the array is the one that I need so I added some logic to get it.

Upvotes: 0

boot-and-bonnet
boot-and-bonnet

Reputation: 761

Assuming your class structure looks something like this:

    public static abstract class Attribute {
        public final String value;
        public final String status;

        public Attribute(String value, String status) {
            this.value = value;
            this.status = status;
        }
    }

    public static class FirstName extends Attribute {
        public FirstName(String value, String status) {
            super(value, status);
        }
    }

    public static class LastName extends Attribute {
        public LastName(String value, String status) {
            super(value, status);
        }
    }

    public static class Attributes {
        public final FirstName firstName;
        public final LastName lastName;

        public Attributes(FirstName firstName, LastName lastName) {
            this.firstName = firstName;
            this.lastName = lastName;
        }
    }

    public static class ObjectTest {
        public final Attributes attributes;

        public ObjectTest(Attributes attributes) {
            this.attributes = attributes;
        }
    }

You can define java.util.function.Function accessors for each stage:

    Function<ObjectTest, Attributes> attributes = t -> t.attributes;
    Function<Attributes, FirstName> firstName = t -> t.firstName;
    Function<Attributes, LastName> lastName = t -> t.lastName;
    Function<Attribute, String> value = t -> t.value;
    Function<Attribute, String> status = t -> t.status;

And combine them like so:

    Function<ObjectTest, String> attributeFirstNameValue =
        attributes.andThen(firstName).andThen(value);
    Function<ObjectTest, String> attributeLastNameStatus =
        attributes.andThen(lastName).andThen(status);

Then apply the combined accessor to the list:

    objList.stream().map(attributeFirstNameValue).forEach(System.out::println);
    objList.stream().map(attributeLastNameStatus).forEach(System.out::println);

Upvotes: 2

TemaTre
TemaTre

Reputation: 1424

Is it critical to use this class structure?

In your example using a associative container is more suitable.

For example you can create class with structure like this:

Firstly you shoud something for itterate by Tree:

class DynamicObjectNode {
private HashMap<String, DynamicObjectNode> childs = new HashMap<>();

public HashMap<String, DynamicObjectNode> getChilds() {
    return childs;
}

}

All values should be in leafs:

class DynamicObjectNodeValue<T> extends DynamicObjectNode {

public DynamicObjectNodeValue(T value) {
    this.value = value;
}

private T value;

public T getValue() {
    return value;
}

public void setValue(T value) {
    this.value = value;
}

@Override
public HashMap<String, DynamicObjectNode> getChilds() {
    return null; //Tree leafs should not has childs
}

}

If you need to work with this as objects. You can use wrapped class like this:

class FirstNameAttribute extends DynamicObjectNode{
private static final String NameValueProperty = "NameValue";
private static final String StatusProperty = "Status";

private DynamicObjectNodeValue<String> nameValue = new DynamicObjectNodeValue<String>("Default name");
private DynamicObjectNodeValue<Integer> status = new DynamicObjectNodeValue<Integer>(1);

public FirstNameAttribute() {
    getChilds().put(NameValueProperty, nameValue);
    getChilds().put(StatusProperty, status);
}

public String getName() {
    return nameValue.getValue();
}

public Integer getStatus() {
    return status.getValue();
}

public void setName(String val) {
    nameValue.setValue(val);
}

public void setStatus(Integer val) {
    status.setValue(val);
}

}

So, with this code you can iterate it as a Tree and get values Dynamic.

And you can use this as objects to call some methods.

Upvotes: 1

Related Questions