001/* 002 * (C) Copyright 2007 Nuxeo SAS (http://nuxeo.com/) and contributors. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser General Public License 006 * (LGPL) version 2.1 which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/lgpl.html 008 * 009 * This library is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * Contributors: 015 * Nuxeo - initial API and implementation 016 * 017 * $Id: MetaValueExpression.java 28491 2008-01-04 19:04:30Z sfermigier $ 018 */ 019 020package org.nuxeo.ecm.platform.ui.web.binding; 021 022import java.io.IOException; 023import java.io.ObjectInput; 024import java.io.ObjectOutput; 025import java.io.Serializable; 026 027import javax.el.ELContext; 028import javax.el.ELException; 029import javax.el.ExpressionFactory; 030import javax.el.FunctionMapper; 031import javax.el.ValueExpression; 032import javax.el.VariableMapper; 033import javax.faces.application.Application; 034import javax.faces.context.FacesContext; 035 036import org.apache.commons.logging.Log; 037import org.apache.commons.logging.LogFactory; 038import org.nuxeo.ecm.platform.ui.web.util.ComponentTagUtils; 039 040/** 041 * Meta value expression used to invoke the EL expression that is already the result of a value expression. 042 * 043 * @author <a href="mailto:at@nuxeo.com">Anahide Tchertchian</a> 044 */ 045public class MetaValueExpression extends ValueExpression implements Serializable { 046 047 private static final long serialVersionUID = -2721042412903607760L; 048 049 private static final Log log = LogFactory.getLog(MetaValueExpression.class); 050 051 private ValueExpression originalValueExpression; 052 053 private FunctionMapper fnMapper; 054 055 private VariableMapper varMapper; 056 057 public MetaValueExpression(ValueExpression originalValueExpression) { 058 this(originalValueExpression, null, null); 059 } 060 061 public MetaValueExpression(ValueExpression originalValueExpression, FunctionMapper fnMapper, 062 VariableMapper varMapper) { 063 this.originalValueExpression = originalValueExpression; 064 this.fnMapper = fnMapper; 065 this.varMapper = varMapper; 066 } 067 068 // Expression interface 069 070 @Override 071 public boolean equals(Object obj) { 072 if (this == obj) { 073 return true; 074 } 075 if (!(obj instanceof MetaValueExpression)) { 076 return false; 077 } 078 MetaValueExpression other = (MetaValueExpression) obj; 079 return originalValueExpression.equals(other.originalValueExpression); 080 } 081 082 @Override 083 public int hashCode() { 084 return originalValueExpression.hashCode(); 085 } 086 087 @Override 088 public String getExpressionString() { 089 return originalValueExpression.getExpressionString(); 090 } 091 092 @Override 093 public boolean isLiteralText() { 094 // XXX should invoke first 095 return originalValueExpression.isLiteralText(); 096 } 097 098 // ValueExpression interface 099 100 @Override 101 public Class<?> getExpectedType() { 102 // XXX should invoke first 103 return originalValueExpression.getExpectedType(); 104 } 105 106 private ELContext getLocalContext(ELContext context) { 107 return new org.nuxeo.ecm.platform.ui.web.binding.EvaluationContext(context, fnMapper, varMapper); 108 } 109 110 @Override 111 public Class<?> getType(ELContext context) { 112 ELContext nxcontext = getLocalContext(context); 113 // XXX should invoke first... 114 return originalValueExpression.getType(nxcontext); 115 } 116 117 @Override 118 public Object getValue(ELContext context) { 119 ELContext nxcontext = getLocalContext(context); 120 Object res = null; 121 if (originalValueExpression != null) { 122 res = originalValueExpression.getValue(nxcontext); 123 if (res instanceof String) { 124 String expression = (String) res; 125 if (ComponentTagUtils.isValueReference(expression)) { 126 FacesContext faces = FacesContext.getCurrentInstance(); 127 Application app = faces.getApplication(); 128 ExpressionFactory factory = app.getExpressionFactory(); 129 ValueExpression newExpr = factory.createValueExpression(nxcontext, expression, Object.class); 130 try { 131 res = newExpr.getValue(nxcontext); 132 } catch (ELException err) { 133 log.error(String.format("Error processing expression %s: %s", expression, err)); 134 res = null; 135 } 136 } else { 137 res = expression; 138 } 139 } 140 } 141 return res; 142 } 143 144 @Override 145 public boolean isReadOnly(ELContext context) { 146 return true; 147 } 148 149 @Override 150 public void setValue(ELContext context, Object value) { 151 // do nothing 152 } 153 154 // Externalizable interface 155 156 public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { 157 originalValueExpression = (ValueExpression) in.readObject(); 158 } 159 160 public void writeExternal(ObjectOutput out) throws IOException { 161 out.writeObject(originalValueExpression); 162 } 163 164}