Search code examples
wicketwicket-6

Is it possible to pass arguments in the expression of a PropertyModel?


I have a model object that has a getter/setter that accepts a String.

public String getStringValue(String key)

I need to know if it is possible to use that getter with a PropertyModel and if so how do I do it? An example might look something like this:

new PropertyModel<String>(myObj, "StringValue[key]");

Solution

  • There isn't built in way to do it. But you can define your own Wicket Model to do it via reflection. For example:

    public class FunctionReflectionReadOnlyModel<T, R> extends AbstractReadOnlyModel<T> {
    
        private Object object;
        private String functionName;
        private R key;
        private Class<R> keyClass;
    
        public FunctionReflectionReadOnlyModel(Object object, String expression, Class<R> keyClass) {
            this.object = object;
            this.functionName = getFunctionName(expression);
            this.key = getKey(expression);
            this.keyClass = keyClass;
        }
    
        @Override
        public T getObject() {
            try {
                Method method = object.getClass().getMethod(functionName, keyClass);
                return (T)method.invoke(object, key);
            } catch (Exception ex) {
                //process exception
                return null;
            }
        }
    }
    

    You just need implement getFunctionName(String expression) and getKey(String expression) on your needs.

    But I think that is better use another variant. It's not particularly what you ask, but it is typified. Also required Java 8.

    public class FunctionWithKeyReadOnlyModel<T, R> extends AbstractReadOnlyModel<T> {
    
        private Function<R, T> function;
        private R key;
    
        public FunctionWithKeyReadOnlyModel(Function<R, T> function, R key) {
            this.function = function;
            this.key = key;
        }
    
        @Override
        public T getObject() {
            return function.apply(key);
        }
    }
    

    And then you can use it like this:

    new FunctionWithKeyReadOnlyModel(obj::getStringValue, "key");
    

    I've read about usage only PropertyModel too late. In this case you can inherit your class from PropertyModel and change getModel/setModel like in example FunctionReflectionReadOnlyModel. So you don't need change other classes API. But if you want all features of PropertyModel (nested objects) you need implement it.