0
\$\begingroup\$

I've an ArrayList of Object that could contain String, Date and Long. The Object list is nearly mandatory. (I obtain this list through reflection, reading all the member variables of an unknown class.)

    ArrayList <Object> values = new ArrayList<Object>();

I build dynamically a query for Alfresco cmis from it:

        addObjectToQueryStatement(qs, i+1, values.get(i));

I came only with this idea:

private void addObjectToQueryStatement(QueryStatement qs, int parameterIndex, Object value)
{
    if (value instanceof String)
    {
        qs.setString(parameterIndex, (String) value);
    }
    else if (value instanceof Date)
    {
        qs.setDateTime(parameterIndex, (Date)value);
    }
    else if (value instanceof Long)
    {
        qs.setNumber(parameterIndex, (Long)value);
    }
}

Does it exist a better and more elegant implementation?

\$\endgroup\$
  • \$\begingroup\$ In what aspect, you need better implementation? \$\endgroup\$ – Harish Gyanani Nov 23 '16 at 13:15
  • \$\begingroup\$ I suppose that using instanceof is not a best practice. \$\endgroup\$ – Accollativo Nov 23 '16 at 14:44
3
\$\begingroup\$

This is missing the point of polymorphism. Its great strength is that you don't need to know or care about the type. With your code, you still need to check type using the instanceof operator.

One way to resolve this is using a variation on the command pattern. First, define a common interface (I used an abstract class) that all three implementations can inherit from. Let call it QueryParameter:

abstract class QueryParameter {
    protected final int index;

    public QueryParameter(int index) {
        this.index = index;
    }

    public abstract void addTo(QueryStatement queryStatement);

}

Now you define three implementations. Here is the String version:

class StringParameter extends QueryParameter {
    private final String value;

    public StringParameter(String value, int index) {
        super(index);
        this.value = value;
    }

    @Override
    public void addTo(QueryStatement queryStatement) {
        queryStatement.setString(index, value);
    }

}

Now, you may construct an arbitrary number of parameters and save them in a collection. Once you've got your QueryStatement ready, simply call the addTo() methods of every parameter in no particular order and you're done!

final Set<QueryParameter> params = new HashSet<>();
//Add bunch of parameters.
params.stream().forEach((param) -> param.addTo(queryStatement));

Of course there are many ways to go about doing this, my example is not necessarily the best fit for you.

\$\endgroup\$
  • \$\begingroup\$ This is a good implementation, but I can't use it. The object list is nearly mandatory. (I obtain this list through reflection, reading all the member variables (String, Date and Long) of an unknown class). \$\endgroup\$ – Accollativo Nov 23 '16 at 14:42
  • 1
    \$\begingroup\$ @Accollativo In that case, I think instanceof is the way to go. One other thing you might want to consider is that maybe there's a better way to obtain the parameters. Reflection is probably not something you want to use unless there's no other way. Check out: softwareengineering.stackexchange.com/questions/193526/… \$\endgroup\$ – A Boschman Nov 23 '16 at 15:15
  • \$\begingroup\$ I can have different classes, so the only way to dynamically load the member variables and put them in a map is through reflection. \$\endgroup\$ – Accollativo Nov 30 '16 at 9:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.