blob: ba70a9a854e04e1b2e75e391c241e1a1cc60cb88 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package javax.faces.component;
import javax.el.ELContext;
import javax.el.ELException;
import javax.el.PropertyNotFoundException;
import javax.el.PropertyNotWritableException;
import javax.el.ValueExpression;
import javax.faces.context.FacesContext;
import javax.faces.el.EvaluationException;
import javax.faces.el.ValueBinding;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Wraps a ValueBinding inside a ValueExpression. Also allows access to the original ValueBinding object.
*
* Although ValueExpression implements Serializable, this class implements StateHolder instead.
*
* ATTENTION: If you make changes to this class, treat {@link _ValueBindingToValueExpression} accordingly.
*
* @author Stan Silvert
* @see javax.faces.component._ValueBindingToValueExpression
*/
@SuppressWarnings("deprecation")
class _ValueBindingToValueExpression extends ValueExpression implements StateHolder
{
private static final long serialVersionUID = 8071429285360496554L;
private static final Log logger = LogFactory.getLog(_ValueBindingToValueExpression.class);
private ValueBinding _valueBinding;
private boolean _transient;
/**
* No-arg constructor used during restoreState
*/
protected _ValueBindingToValueExpression()
{
}
private ValueBinding getNotNullValueBinding()
{
if (_valueBinding == null)
{
throw new IllegalStateException("value binding is null");
}
return _valueBinding;
}
/** Creates a new instance of ValueBindingToValueExpression */
public _ValueBindingToValueExpression(ValueBinding valueBinding)
{
if (valueBinding == null)
{
throw new IllegalArgumentException("value binding must not be null");
}
this._valueBinding = valueBinding;
}
public ValueBinding getValueBinding()
{
return _valueBinding;
}
@Override
public boolean isReadOnly(final ELContext context) throws NullPointerException, PropertyNotFoundException,
ELException
{
return invoke(new Invoker<Boolean>()
{
public Boolean invoke()
{
return getNotNullValueBinding().isReadOnly(getFacesContext(context));
}
});
}
@Override
public Object getValue(final ELContext context) throws NullPointerException, PropertyNotFoundException, ELException
{
return invoke(new Invoker<Object>()
{
public Object invoke()
{
return getNotNullValueBinding().getValue(getFacesContext(context));
}
});
}
@Override
public Class<?> getType(final ELContext context) throws NullPointerException, PropertyNotFoundException,
ELException
{
return invoke(new Invoker<Class<?>>()
{
public Class<?> invoke()
{
return getNotNullValueBinding().getType(getFacesContext(context));
}
});
}
@Override
public void setValue(final ELContext context, final Object value) throws NullPointerException,
PropertyNotFoundException, PropertyNotWritableException, ELException
{
invoke(new Invoker<Object>()
{
public Object invoke()
{
getNotNullValueBinding().setValue(getFacesContext(context), value);
return null;
}
});
}
@Override
public int hashCode()
{
final int PRIME = 31;
int result = 1;
result = PRIME * result + (_transient ? 1231 : 1237);
result = PRIME * result + ((_valueBinding == null) ? 0 : _valueBinding.hashCode());
return result;
}
@Override
public boolean equals(Object obj)
{
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
final _ValueBindingToValueExpression other = (_ValueBindingToValueExpression) obj;
if (_transient != other._transient)
return false;
if (_valueBinding == null)
{
if (other._valueBinding != null)
return false;
}
else if (!_valueBinding.equals(other._valueBinding))
return false;
return true;
}
@Override
public boolean isLiteralText()
{
return false;
}
@Override
public String getExpressionString()
{
return getNotNullValueBinding().getExpressionString();
}
@Override
public Class<?> getExpectedType()
{
if (_valueBinding != null)
{
try
{
Object value = getNotNullValueBinding().getValue(FacesContext.getCurrentInstance());
if (value != null)
{
return value.getClass();
}
}
catch (Throwable e)
{
logger.warn("Could not determine expected type for '" + _valueBinding.getExpressionString() + "': "
+ e.getMessage(), e);
}
}
return null;
}
public void restoreState(FacesContext context, Object state)
{
if (state instanceof ValueBinding)
{
_valueBinding = (ValueBinding) state;
}
else if (state != null)
{
Object[] stateArray = (Object[]) state;
_valueBinding = (ValueBinding) _ClassUtils.newInstance((String) stateArray[0], ValueBinding.class);
((StateHolder) _valueBinding).restoreState(context, stateArray[1]);
}
}
public Object saveState(FacesContext context)
{
if (!_transient)
{
if (_valueBinding instanceof StateHolder)
{
Object[] state = new Object[2];
state[0] = _valueBinding.getClass().getName();
state[1] = ((StateHolder) _valueBinding).saveState(context);
return state;
}
return _valueBinding;
}
return null;
}
public void setTransient(boolean newTransientValue)
{
_transient = newTransientValue;
}
public boolean isTransient()
{
return _transient;
}
private FacesContext getFacesContext(ELContext context)
{
if (context == null)
{
throw new IllegalArgumentException("el context must not be null.");
}
FacesContext facesContext = (FacesContext) context.getContext(FacesContext.class);
if (context == null)
{
throw new IllegalStateException("faces context not available in el context.");
}
return facesContext;
}
private <T> T invoke(Invoker<T> invoker)
{
try
{
return invoker.invoke();
}
catch (javax.faces.el.PropertyNotFoundException e)
{
throw new PropertyNotFoundException(e.getMessage(), e);
}
catch (EvaluationException e)
{
throw new ELException(e.getMessage(), e);
}
}
private interface Invoker<T>
{
T invoke();
}
}