views:

429

answers:

3

Hello!

I'm not even sure if this is possible, but hopefully it is in Java. I know I've done it in PHP by using variable variables and accessing a variable dynamically, but I read this isn't possible in Java in a different question.

I have an array of strings which contains the state of checkboxes in my JSF GUI. If all checkboxes are set the array will then be filled with strings containing the value of different checkboxes.

The labels and values of the checkboxes are built by looping through an array that looks like this:

private static final String[][] OVERVIEW_FIELDS = {{"ID", "requestid"},
    {"Date added", "dob"}, {"Title", "requestTitle"}, {"Process", "processId"},
..., ..., ...};

Then I iterate through the array and make JSF SelectItems out of it:

for (int i = 0; i < OVERVIEW_FIELDS.length; i++) {
    SelectItem item = new SelectItem(OVERVIEW_FIELDS[i][0], OVERVIEW_FIELDS[i][1]);
    getFields().add(item);
}

The problem and current solution (hopefully someone can help me refactor it into something better:

for (String item : getVisibleFields()) {
           if (item.equals("dob")) {
                setDob(true);
            }
            if (item.equals("requestTitle")) {
                setRequestTitle(true);
            }
            if (item.equals("processId")) {
                setProcessId(true);
            }
            if (...) {
            }
}

And so on it continues for 11 booleans. I don't like this solution, and I see similar patterns in other beans in my system.

Does anyone know if there's a better solution to this? The booleans control columns where I set their rendered field to true/false according to what the checkbox array contains.

I was hoping in the JSF EL I could access the visibleFields variable and the contains method, thus returning either true or false if the object exist in array. This doesn't seem to work though and the EL doesn't give me access to the contains method.

I'm currently using:

rendered="#{overviewFilterBean.dob}"

And I tried with this code:

rendered="#{overviewFilterBean.visibleFields.contains['dob']}">

Now this led me to try to use my final array and set the booleans according to getFields().contains(OVERVIEW_FIELDS[i][1]), but how can I make this possible?

Part real and part pseudo code follows (the solution I was aiming for now):

for (int i = 0; i < OVERVIEW_FIELDS.length; i++) {
    if (item.equals(OVERVIEW_FIELDS[i][1])) {
           setOVERVIEW_FIELDS[i][1](true);
       }
    }

The big question:

Is there a way for me to use the value from OVERVIEW_FIELDS[i][1] to set the correct boolean variable or can I turn this into a Map maybe and use the JSF EL to check if key exists in the map?

Thank you for your time, and sorry for writing such a lengthy question to get to a small point :/

EDIT:

The reflection method resulted in 5 exceptions, big block of code handling them and also people said that its an expensive method. This leads me to believe that either my old solution or by using maps is the best way of doing it. Im gonna try the map solution =)

A: 

You can use the Java reflection API to look up the field dynamically and set it, as in this example. Note that there will be a performance hit to this method.

bdonlan
+3  A: 

With reflection, you can do:

for (String item : getVisibleFields()) {
    getClass().getMethod("get" + capitalize(item)).invoke(this, true);
}

Exception handling and the capitalize method are left as an exercise to the reader (invoke throws a lot of exceptions).

Michael Myers
Hello, and thank you for showing the code which this manner can be done. Its very true as you say, this generates tons of exceptions, and tbh if its a really expensive way of doing things, maybe IM better off with just trying on each boolean?
ChrisAD
Yes, it would be better if you had a list containing only the boolean fields (I misunderstood your question when I wrote this). But if you had such a list, you might as well make it into a Map, as noselasd suggests.
Michael Myers
yes I accepted his answer, because I found out that in JSF EL I could simply do rendered="#{!empty testBean.map['test']}" and populate the map instead of setting the bools! Thanks
ChrisAD
+1  A: 

You could always store the values in a map rather. However if you want to invoke methods based on the methodname as a string, use reflection. See http://java.sun.com/developer/technicalArticles/ALT/Reflection/

nos