001/* 002 * (C) Copyright 2007 Nuxeo SA (http://nuxeo.com/) and others. 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 * Contributors: 017 * Nuxeo - initial API and implementation 018 * 019 * $Id: MetaValueExpression.java 28491 2008-01-04 19:04:30Z sfermigier $ 020 */ 021 022package org.nuxeo.ecm.platform.ui.web.binding; 023 024import java.io.IOException; 025import java.io.ObjectInput; 026import java.io.ObjectOutput; 027import java.io.Serializable; 028 029import javax.el.ELContext; 030import javax.el.ELException; 031import javax.el.ExpressionFactory; 032import javax.el.FunctionMapper; 033import javax.el.ValueExpression; 034import javax.el.VariableMapper; 035import javax.faces.application.Application; 036import javax.faces.context.FacesContext; 037 038import org.apache.commons.logging.Log; 039import org.apache.commons.logging.LogFactory; 040import org.nuxeo.ecm.platform.ui.web.util.ComponentTagUtils; 041 042/** 043 * Meta value expression used to invoke the EL expression that is already the result of a value expression. 044 * 045 * @author <a href="mailto:[email protected]">Anahide Tchertchian</a> 046 */ 047public class MetaValueExpression extends ValueExpression implements Serializable { 048 049 private static final long serialVersionUID = -2721042412903607760L; 050 051 private static final Log log = LogFactory.getLog(MetaValueExpression.class); 052 053 private ValueExpression originalValueExpression; 054 055 private FunctionMapper fnMapper; 056 057 private VariableMapper varMapper; 058 059 private Class<?> expectedType; 060 061 /** 062 * @see {@link #MetaValueExpression(ValueExpression, FunctionMapper, VariableMapper)} 063 */ 064 public MetaValueExpression(ValueExpression originalValueExpression) { 065 this(originalValueExpression, null, null, Object.class); 066 } 067 068 public MetaValueExpression(ValueExpression originalValueExpression, FunctionMapper fnMapper, 069 VariableMapper varMapper) { 070 this(originalValueExpression, fnMapper, varMapper, Object.class); 071 } 072 073 public MetaValueExpression(ValueExpression originalValueExpression, FunctionMapper fnMapper, 074 VariableMapper varMapper, Class<?> expectedType) { 075 this.originalValueExpression = originalValueExpression; 076 this.fnMapper = fnMapper; 077 this.varMapper = varMapper; 078 this.expectedType = expectedType; 079 } 080 081 // Expression interface 082 083 @Override 084 public boolean equals(Object obj) { 085 if (this == obj) { 086 return true; 087 } 088 if (!(obj instanceof MetaValueExpression)) { 089 return false; 090 } 091 MetaValueExpression other = (MetaValueExpression) obj; 092 return originalValueExpression.equals(other.originalValueExpression); 093 } 094 095 @Override 096 public int hashCode() { 097 return originalValueExpression.hashCode(); 098 } 099 100 @Override 101 public String getExpressionString() { 102 return originalValueExpression.getExpressionString(); 103 } 104 105 @Override 106 public boolean isLiteralText() { 107 // XXX should invoke first 108 return originalValueExpression.isLiteralText(); 109 } 110 111 // ValueExpression interface 112 113 @Override 114 public Class<?> getExpectedType() { 115 // XXX should invoke first 116 return originalValueExpression.getExpectedType(); 117 } 118 119 private ELContext getLocalContext(ELContext context) { 120 if (fnMapper == null && varMapper == null) { 121 return context; 122 } 123 return new org.nuxeo.ecm.platform.ui.web.binding.EvaluationContext(context, fnMapper, varMapper); 124 } 125 126 @Override 127 public Class<?> getType(ELContext context) { 128 ELContext nxcontext = getLocalContext(context); 129 // XXX should invoke first... 130 return originalValueExpression.getType(nxcontext); 131 } 132 133 @Override 134 public Object getValue(ELContext context) { 135 ELContext nxcontext = getLocalContext(context); 136 Object res = null; 137 if (originalValueExpression != null) { 138 res = originalValueExpression.getValue(nxcontext); 139 if (res instanceof String) { 140 String expression = (String) res; 141 if (ComponentTagUtils.isValueReference(expression)) { 142 FacesContext faces = FacesContext.getCurrentInstance(); 143 Application app = faces.getApplication(); 144 ExpressionFactory factory = app.getExpressionFactory(); 145 ValueExpression newExpr = factory.createValueExpression(nxcontext, expression, expectedType); 146 try { 147 res = newExpr.getValue(nxcontext); 148 } catch (ELException err) { 149 log.error("Error processing expression " + expression + ": " + err); 150 res = null; 151 } 152 } else { 153 res = expression; 154 } 155 } 156 } 157 return res; 158 } 159 160 @Override 161 public boolean isReadOnly(ELContext context) { 162 return true; 163 } 164 165 @Override 166 public void setValue(ELContext context, Object value) { 167 // do nothing 168 } 169 170 // Externalizable interface 171 172 public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { 173 originalValueExpression = (ValueExpression) in.readObject(); 174 } 175 176 public void writeExternal(ObjectOutput out) throws IOException { 177 out.writeObject(originalValueExpression); 178 } 179 180}