001// Copyright 2006, 2011 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 org.apache.tapestry5.Binding;
018import org.apache.tapestry5.Binding2;
019import org.apache.tapestry5.commons.Location;
020import org.apache.tapestry5.commons.internal.util.TapestryException;
021import org.apache.tapestry5.ioc.BaseLocatable;
022
023import java.lang.annotation.Annotation;
024import java.lang.reflect.Type;
025
026/**
027 * Abstract base class for bindings. Assumes that the binding is read only and invariant. Subclasses must provide an
028 * implementation of {@link Binding#get()}.
029 */
030public abstract class AbstractBinding extends BaseLocatable implements Binding2
031{
032    public AbstractBinding()
033    {
034        this(null);
035    }
036
037    protected AbstractBinding(Location location)
038    {
039        super(location);
040    }
041
042    /**
043     * @throws TapestryException always
044     */
045    public void set(Object value)
046    {
047        throw new TapestryException(String.format("Binding %s is read-only.", this), this, null);
048    }
049
050    /**
051     * Returns true. Subclasses that do not supply a fixed, read-only value should override this method to return
052     * false.
053     */
054    public boolean isInvariant()
055    {
056        return true;
057    }
058
059    /**
060     * Returns the actual class, by invoking {@link Binding#get()}. Subclasses may override this method to work more
061     * efficiently (say, when the binding type is known statically).
062     */
063    public Class getBindingType()
064    {
065        return get().getClass();
066    }
067    
068    /**
069     * Passes straight through to {@link AbstractBinding#getBindingType()}. Subclasses may override this method to
070     * return the generic type if it is available
071     */
072    public Type getBindingGenericType()
073    {
074        return getBindingType();
075    }
076
077    /**
078     * Always returns null. Bindings that provide access to a method or field will override this method to return the
079     * appropriate annotation.
080     */
081    public <T extends Annotation> T getAnnotation(Class<T> annotationClass)
082    {
083        return null;
084    }
085
086}