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 }