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