001    // Copyright 2004, 2005 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    
015    package org.apache.tapestry.binding;
016    
017    import org.apache.hivemind.Location;
018    import org.apache.hivemind.util.Defense;
019    import org.apache.tapestry.BindingException;
020    import org.apache.tapestry.IBinding;
021    import org.apache.tapestry.coerce.ValueConverter;
022    
023    /**
024     * Base class for {@link IBinding}implementations.
025     * 
026     * @author Howard Lewis Ship
027     */
028    
029    public abstract class AbstractBinding implements IBinding
030    {
031        /** @since 4.0 */
032    
033        protected final String _description;
034    
035        /** @since 4.0 */
036    
037        private final ValueConverter _valueConverter;
038    
039        /** @since 3.0 */
040    
041        private final Location _location;
042    
043        /** @since 3.0 */
044    
045        protected AbstractBinding(String description, ValueConverter valueConverter, Location location)
046        {
047            Defense.notNull(description, "description");
048            Defense.notNull(valueConverter, "valueConverter");
049    
050            _description = description;
051            _valueConverter = valueConverter;
052            _location = location;
053        }
054    
055        public Location getLocation()
056        {
057            return _location;
058        }
059    
060        /**
061         * Overridden in subclasses that are not invariant.
062         */
063    
064        public void setObject(Object value)
065        {
066            throw createReadOnlyBindingException(this);
067        }
068    
069        /**
070         * Default implementation: returns true.
071         * 
072         * @since 2.0.3
073         */
074    
075        public boolean isInvariant()
076        {
077            return true;
078        }
079    
080        public Object getObject(Class type)
081        {
082            Defense.notNull(type, "type");
083    
084            Object raw = getObject();
085    
086            try
087            {
088                return _valueConverter.coerceValue(raw, type);
089            }
090            catch (Exception ex)
091            {
092                String message = BindingMessages.convertObjectError(this, ex);
093    
094                throw new BindingException(message, getComponent(), _location, this, ex);
095            }
096        }
097    
098        /**
099         * Returns the component to which this binding is connected; this is currently only used when
100         * building certain exceptions. This implementation returns null.
101         *
102         * @return The {@link org.apache.tapestry.IComponent} object this binding is set against.
103         * @since 4.0
104         */
105    
106        public Object getComponent()
107        {
108            return null;
109        }
110    
111        /** @since 3.0 */
112    
113        protected BindingException createReadOnlyBindingException(IBinding binding)
114        {
115            return new BindingException(BindingMessages.readOnlyBinding(binding), binding);
116        }
117    
118        /** @since 4.0 */
119    
120        public String getDescription()
121        {
122            return _description;
123        }
124    
125        /**
126         * Gets the converter used to coerce binding values in to their target types.
127         *
128         * @return The {@link ValueConverter} being used by this binding.
129         */
130        public ValueConverter getValueConverter()
131        {
132            return _valueConverter;
133        }
134    
135        public String toString()
136        {
137            StringBuffer buffer = new StringBuffer();
138            buffer.append(getClass().getName());
139            buffer.append("@");
140            buffer.append(Integer.toHexString(hashCode()));
141            buffer.append("[");
142            buffer.append(_description);
143    
144            extendDescription(buffer);
145    
146            buffer.append(", location=");
147            buffer.append(_location);
148            buffer.append("]");
149    
150            return buffer.toString();
151        }
152    
153        /**
154         * Does nothing, subclasses may override to add additional information.
155         */
156        protected void extendDescription(StringBuffer buffer)
157        {
158    
159        }
160    }