/* * Copyright 2017 OmniFaces * * Licensed 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 org.omnifaces.el; import javax.el.ELContext; import javax.el.PropertyNotWritableException; import javax.el.ValueExpression; import org.omnifaces.util.Callback; /** * Implementation of a read only value expression that can be used when the value is not yet available at construction time, or when the * value would be too expensive to create and it's not yet clear if the expression will actually be evaluated. * * <p> * A callback (lambda in Java 8) that obtains the value can be provided, or the getValue() method can be overridden. * * @since 2.0 * @author Arjan Tijms */ public class ReadOnlyValueExpression extends ValueExpression { private static final long serialVersionUID = 1L; private Callback.SerializableReturning<Object> callback; private Class<?> expectedType; public ReadOnlyValueExpression(Class<?> expectedType, Callback.SerializableReturning<Object> callback) { this(expectedType); this.callback = callback; } public ReadOnlyValueExpression(Class<?> expectedType) { this.expectedType = expectedType; } public ReadOnlyValueExpression() { // } @Override public Object getValue(ELContext context) { if (callback != null) { return callback.invoke(); } return null; } @Override public void setValue(ELContext context, Object value) { throw new PropertyNotWritableException(); } @Override public boolean isReadOnly(ELContext context) { return true; } @Override public Class<?> getType(ELContext context) { Object value = getValue(context); return value == null ? null : value.getClass(); } @Override public Class<?> getExpectedType() { return expectedType; } @Override public String getExpressionString() { return null; } @Override public boolean equals(Object object) { // Basic checks. if (object == this) { return true; } if (object == null || object.getClass() != getClass()) { return false; } // Property checks. ReadOnlyValueExpression other = (ReadOnlyValueExpression) object; Object value = getValue(null); Object otherValue = other.getValue(null); if (value == null ? otherValue != null : !value.equals(otherValue)) { return false; } // All passed. return true; } @Override public int hashCode() { Object value = getValue(null); return value == null ? 0 : value.hashCode(); } @Override public boolean isLiteralText() { return true; } /** * Returns the functional interface that will be called when the value expression is resolved * * @return the functional interface that will be called when the value expression is resolved * @since 2.1 */ public Callback.SerializableReturning<Object> getCallbackReturning() { return callback; } /** * Sets the functional interface that will be called when the value expression is resolved * * @param callbackReturning functional interface returning what the value expression will return * @since 2.1 */ public void setCallbackReturning(Callback.SerializableReturning<Object> callbackReturning) { this.callback = callbackReturning; } }