    001// Copyright 2006, 2008, 2009 The Apache Software Foundation
    002//
    003// Licensed under the Apache License, Version 2.0 (the "License");
    004// you may not use this file except in compliance with the License.
    005// You may obtain a copy of the License at
    006//
    007//     http://www.apache.org/licenses/LICENSE-2.0
    008//
    009// Unless required by applicable law or agreed to in writing, software
    010// distributed under the License is distributed on an "AS IS" BASIS,
    011// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    012// See the License for the specific language governing permissions and
    013// limitations under the License.
    014
    015package org.apache.tapestry5.internal.bindings;
    016
    017import java.lang.annotation.Annotation;
    018import java.lang.reflect.Type;
    019
    020import org.apache.tapestry5.beanmodel.PropertyConduit;
    021import org.apache.tapestry5.beanmodel.PropertyConduit2;
    022import org.apache.tapestry5.beanmodel.internal.services.Invariant;
    023import org.apache.tapestry5.commons.Location;
    024import org.apache.tapestry5.commons.internal.util.TapestryException;
    025import org.apache.tapestry5.internal.TapestryInternalUtils;
    026
    027/**
    028 * Base class for bindings created by the {@link org.apache.tapestry5.internal.bindings.PropBindingFactory}. A subclass
    029 * of this is created at runtime.
    030 */
    031public class PropBinding extends AbstractBinding implements InternalPropBinding
    032{
    033    private final Object root;
    034
    035    private final PropertyConduit conduit;
    036
    037    private final String toString;
    038
    039    private boolean invariant;
    040
    041    private final String expression;
    042
    043    public PropBinding(final Location location, final Object root, final PropertyConduit conduit, final String expression, final String toString)
    044    {
    045        super(location);
    046
    047        this.root = root;
    048        this.conduit = conduit;
    049        this.expression = expression.intern();
    050        this.toString = toString;
    051
    052        invariant = conduit.getAnnotation(Invariant.class) != null;
    053    }
    054
    055    /**
    056     * The default implementation of get() will throw a TapestryException (binding is write only). The fabricated
    057     * subclass <em>may</em> override this method (as well as set()).
    058     */
    059    public Object get()
    060    {
    061        try
    062        {
    063            return conduit.get(root);
    064        }
    065        catch (Exception ex)
    066        {
    067            throw new TapestryException(ex.getMessage(), getLocation(), ex);
    068        }
    069    }
    070
    071    @Override
    072    public void set(Object value)
    073    {
    074        try
    075        {
    076            conduit.set(root, value);
    077        }
    078        catch (Exception ex)
    079        {
    080            throw new TapestryException(ex.getMessage(), getLocation(), ex);
    081        }
    082    }
    083
    084    @Override
    085    public String toString()
    086    {
    087        return toString;
    088    }
    089
    090    /**
    091     * Almost always returns false, unless the conduit provides the {@link org.apache.tapestry5.beanmodel.internal.services.Invariant}
    092     * annotation.
    093     */
    094    @Override
    095    public boolean isInvariant()
    096    {
    097        return invariant;
    098    }
    099
    100    @Override
    101    public Class getBindingType()
    102    {
    103        return conduit.getPropertyType();
    104    }
    105
    106    /**
    107     * Get the generic type from the underlying property
    108     *
    109     * @see PropertyConduit2#getPropertyGenericType()
    110     */
    111    @Override
    112    public Type getBindingGenericType()
    113    {
    114        if (conduit instanceof PropertyConduit2) {
    115            return ((PropertyConduit2) conduit).getPropertyGenericType();
    116        }
    117        return conduit.getPropertyType();
    118    }
    119
    120    @Override
    121    public <T extends Annotation> T getAnnotation(Class<T> annotationClass)
    122    {
    123        return conduit.getAnnotation(annotationClass);
    124    }
    125
    126    public String getPropertyName()
    127    {
    128        return TapestryInternalUtils.toInternalPropertyConduit(conduit).getPropertyName();
    129    }
    130
    131    public String getExpression()
    132    {
    133        return expression;
    134    }
    135
    136}