001: /*
002: * Copyright 2006 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package javax.faces.component;
018:
019: import javax.el.ELContext;
020: import javax.el.ELException;
021: import javax.el.PropertyNotFoundException;
022: import javax.el.PropertyNotWritableException;
023: import javax.el.ValueExpression;
024: import javax.faces.context.FacesContext;
025: import javax.faces.el.EvaluationException;
026: import javax.faces.el.ValueBinding;
027:
028: import org.apache.commons.logging.Log;
029: import org.apache.commons.logging.LogFactory;
030:
031: /**
032: * Wraps a ValueBinding inside a ValueExpression. Also allows access to the original ValueBinding object.
033: *
034: * Although ValueExpression implements Serializable, this class implements StateHolder instead.
035: *
036: * ATTENTION: If you make changes to this class, treat {@link _ValueBindingToValueExpression} accordingly.
037: *
038: * @author Stan Silvert
039: * @see javax.faces.component._ValueBindingToValueExpression
040: */
041: @SuppressWarnings("deprecation")
042: class _ValueBindingToValueExpression extends ValueExpression implements
043: StateHolder {
044: private static final long serialVersionUID = 8071429285360496554L;
045:
046: private static final Log logger = LogFactory
047: .getLog(_ValueBindingToValueExpression.class);
048:
049: private ValueBinding _valueBinding;
050:
051: private boolean _transient;
052:
053: /**
054: * No-arg constructor used during restoreState
055: */
056: protected _ValueBindingToValueExpression() {
057: }
058:
059: private ValueBinding getNotNullValueBinding() {
060: if (_valueBinding == null) {
061: throw new IllegalStateException("value binding is null");
062: }
063: return _valueBinding;
064: }
065:
066: /** Creates a new instance of ValueBindingToValueExpression */
067: public _ValueBindingToValueExpression(ValueBinding valueBinding) {
068: if (valueBinding == null) {
069: throw new IllegalArgumentException(
070: "value binding must not be null");
071: }
072: this ._valueBinding = valueBinding;
073: }
074:
075: public ValueBinding getValueBinding() {
076: return _valueBinding;
077: }
078:
079: @Override
080: public boolean isReadOnly(final ELContext context)
081: throws NullPointerException, PropertyNotFoundException,
082: ELException {
083: return invoke(new Invoker<Boolean>() {
084: public Boolean invoke() {
085: return getNotNullValueBinding().isReadOnly(
086: getFacesContext(context));
087: }
088: });
089: }
090:
091: @Override
092: public Object getValue(final ELContext context)
093: throws NullPointerException, PropertyNotFoundException,
094: ELException {
095: return invoke(new Invoker<Object>() {
096: public Object invoke() {
097: return getNotNullValueBinding().getValue(
098: getFacesContext(context));
099: }
100: });
101: }
102:
103: @Override
104: public Class<?> getType(final ELContext context)
105: throws NullPointerException, PropertyNotFoundException,
106: ELException {
107: return invoke(new Invoker<Class<?>>() {
108: public Class<?> invoke() {
109: return getNotNullValueBinding().getType(
110: getFacesContext(context));
111: }
112: });
113: }
114:
115: @Override
116: public void setValue(final ELContext context, final Object value)
117: throws NullPointerException, PropertyNotFoundException,
118: PropertyNotWritableException, ELException {
119: invoke(new Invoker<Object>() {
120: public Object invoke() {
121: getNotNullValueBinding().setValue(
122: getFacesContext(context), value);
123: return null;
124: }
125: });
126: }
127:
128: @Override
129: public int hashCode() {
130: final int PRIME = 31;
131: int result = 1;
132: result = PRIME * result + (_transient ? 1231 : 1237);
133: result = PRIME
134: * result
135: + ((_valueBinding == null) ? 0 : _valueBinding
136: .hashCode());
137: return result;
138: }
139:
140: @Override
141: public boolean equals(Object obj) {
142: if (this == obj)
143: return true;
144: if (obj == null)
145: return false;
146: if (getClass() != obj.getClass())
147: return false;
148: final _ValueBindingToValueExpression other = (_ValueBindingToValueExpression) obj;
149: if (_transient != other._transient)
150: return false;
151: if (_valueBinding == null) {
152: if (other._valueBinding != null)
153: return false;
154: } else if (!_valueBinding.equals(other._valueBinding))
155: return false;
156: return true;
157: }
158:
159: @Override
160: public boolean isLiteralText() {
161: return false;
162: }
163:
164: @Override
165: public String getExpressionString() {
166: return getNotNullValueBinding().getExpressionString();
167: }
168:
169: @Override
170: public Class<?> getExpectedType() {
171: if (_valueBinding != null) {
172: try {
173: Object value = getNotNullValueBinding().getValue(
174: FacesContext.getCurrentInstance());
175: if (value != null) {
176: return value.getClass();
177: }
178: } catch (Throwable e) {
179: logger.warn("Could not determine expected type for '"
180: + _valueBinding.getExpressionString() + "': "
181: + e.getMessage(), e);
182: }
183: }
184: return null;
185: }
186:
187: public void restoreState(FacesContext context, Object state) {
188: if (state instanceof ValueBinding) {
189: _valueBinding = (ValueBinding) state;
190: } else if (state != null) {
191: Object[] stateArray = (Object[]) state;
192: _valueBinding = (ValueBinding) _ClassUtils.newInstance(
193: (String) stateArray[0], ValueBinding.class);
194: ((StateHolder) _valueBinding).restoreState(context,
195: stateArray[1]);
196: }
197: }
198:
199: public Object saveState(FacesContext context) {
200: if (!_transient) {
201: if (_valueBinding instanceof StateHolder) {
202: Object[] state = new Object[2];
203: state[0] = _valueBinding.getClass().getName();
204: state[1] = ((StateHolder) _valueBinding)
205: .saveState(context);
206: return state;
207: }
208: return _valueBinding;
209: }
210: return null;
211: }
212:
213: public void setTransient(boolean newTransientValue) {
214: _transient = newTransientValue;
215: }
216:
217: public boolean isTransient() {
218: return _transient;
219: }
220:
221: private FacesContext getFacesContext(ELContext context) {
222: if (context == null) {
223: throw new IllegalArgumentException(
224: "el context must not be null.");
225: }
226: FacesContext facesContext = (FacesContext) context
227: .getContext(FacesContext.class);
228: if (context == null) {
229: throw new IllegalStateException(
230: "faces context not available in el context.");
231: }
232: return facesContext;
233: }
234:
235: private <T> T invoke(Invoker<T> invoker) {
236: try {
237: return invoker.invoke();
238: } catch (javax.faces.el.PropertyNotFoundException e) {
239: throw new PropertyNotFoundException(e.getMessage(), e);
240: } catch (EvaluationException e) {
241: throw new ELException(e.getMessage(), e);
242: }
243: }
244:
245: private interface Invoker<T> {
246: T invoke();
247: }
248: }
|