org.apache.wicket.model.AbstractPropertyModel.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.wicket.model.AbstractPropertyModel.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.wicket.model;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

import org.apache.wicket.Application;
import org.apache.wicket.Session;
import org.apache.wicket.WicketRuntimeException;
import org.apache.wicket.core.util.lang.PropertyResolver;
import org.apache.wicket.core.util.lang.PropertyResolverConverter;
import org.apache.wicket.util.string.Strings;

/**
 * Serves as a base class for different kinds of property models. By default, this class uses
 * {@link PropertyResolver} to resolve expressions on the target model object. Note that the
 * property resolver by default provides access to private members and methods. If guaranteeing
 * encapsulation of the target objects is a big concern, you should consider using an alternative
 * implementation.
 * 
 * @see PropertyResolver
 * @see org.apache.wicket.model.IDetachable
 * 
 * @author Chris Turner
 * @author Eelco Hillenius
 * @author Jonathan Locke
 * 
 * @param <T>
 *            The Model object type
 */
public abstract class AbstractPropertyModel<T> extends ChainingModel<T>
        implements IObjectClassAwareModel<T>, IPropertyReflectionAwareModel<T> {
    private static final long serialVersionUID = 1L;

    /**
     * Constructor
     * 
     * @param modelObject
     *            The nested model object
     */
    public AbstractPropertyModel(final Object modelObject) {
        super(modelObject);
    }

    @Override
    @SuppressWarnings("unchecked")
    public T getObject() {
        final String expression = propertyExpression();
        if (Strings.isEmpty(expression)) {
            // Return a meaningful value for an empty property expression
            return (T) getInnermostModelOrObject();
        } else if (expression.startsWith(".")) {
            throw new IllegalArgumentException("Property expressions cannot start with a '.' character");
        }

        final Object target = getInnermostModelOrObject();
        if (target != null) {
            return (T) PropertyResolver.getValue(expression, target);
        }
        return null;
    }

    /**
     * Gets the property expression for this model
     * 
     * @return The property expression
     */
    public final String getPropertyExpression() {
        return propertyExpression();
    }

    /**
     * Applies the property expression on the model object using the given object argument.
     * 
     * @param object
     *            The object that will be used when setting a value on the model object
     * @see IModel#setObject(Object)
     */
    @Override
    @SuppressWarnings("unchecked")
    public void setObject(T object) {
        final String expression = propertyExpression();
        if (Strings.isEmpty(expression)) {
            // TODO check, really do this?
            // why not just set the target to the object?
            Object target = getTarget();
            if (target instanceof IModel) {
                ((IModel<T>) target).setObject(object);
            } else {
                setTarget(object);
            }
        } else {
            PropertyResolverConverter prc = new PropertyResolverConverter(Application.get().getConverterLocator(),
                    Session.get().getLocale());
            PropertyResolver.setValue(expression, getInnermostModelOrObject(), object, prc);
        }
    }

    /**
     * @return model object class
     */
    @Override
    @SuppressWarnings("unchecked")
    public Class<T> getObjectClass() {
        final String expression = propertyExpression();
        final Object target = getInnermostModelOrObject();

        if (Strings.isEmpty(expression)) {
            // Return a meaningful value for an empty property expression
            return (Class<T>) (target != null ? target.getClass() : null);
        }

        if (target != null) {
            try {
                return (Class<T>) PropertyResolver.getPropertyClass(expression, target);
            } catch (Exception e) {
                // ignore.
            }
        } else if (getTarget() instanceof IObjectClassAwareModel) {
            try {
                Class<?> targetClass = ((IObjectClassAwareModel<?>) getTarget()).getObjectClass();
                if (targetClass != null) {
                    return PropertyResolver.getPropertyClass(expression, targetClass);
                }
            } catch (WicketRuntimeException e) {
                // it was just a try.
            }

        }
        return null;
    }

    @Override
    public Field getPropertyField() {
        String expression = propertyExpression();
        if (Strings.isEmpty(expression) == false) {
            Object target = getInnermostModelOrObject();
            if (target != null) {
                try {
                    return PropertyResolver.getPropertyField(expression, target);
                } catch (Exception ignore) {
                    // ignore.
                }
            }
        }
        return null;
    }

    @Override
    public Method getPropertyGetter() {
        String expression = propertyExpression();
        if (Strings.isEmpty(expression) == false) {
            Object target = getInnermostModelOrObject();
            if (target != null) {
                try {
                    return PropertyResolver.getPropertyGetter(expression, target);
                } catch (Exception ignore) {
                }
            }
        }
        return null;
    }

    @Override
    public Method getPropertySetter() {
        String expression = propertyExpression();
        if (Strings.isEmpty(expression) == false) {
            Object target = getInnermostModelOrObject();
            if (target != null) {
                try {
                    return PropertyResolver.getPropertySetter(expression, target);
                } catch (Exception ignore) {
                }
            }
        }
        return null;
    }

    /**
     * @return The property expression for the component
     */
    protected abstract String propertyExpression();

    /**
     * @return The innermost model or the object if the target is not a model
     */
    public final Object getInnermostModelOrObject() {
        Object object = getTarget();
        while (object instanceof IModel) {
            Object tmp = ((IModel<?>) object).getObject();
            if (tmp == object) {
                break;
            }
            object = tmp;
        }
        return object;
    }
}