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: MetaMethodExpression.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.MethodExpression; 034import javax.el.MethodInfo; 035import javax.el.VariableMapper; 036import javax.faces.application.Application; 037import javax.faces.context.FacesContext; 038 039import org.nuxeo.ecm.platform.ui.web.util.ComponentTagUtils; 040 041/** 042 * Meta method expression used to invoke the EL expression that is already the result of a method expression. 043 * <p> 044 * For instance it is useful to use this expression to provide action links defined in NXActions extensions with links 045 * like #{documentAction.createDocument('Domain')}. 046 * <p> 047 * There is no more than one level of abstraction: 048 * <ul> 049 * <li>the expression method value can be a standard method expression (with parameters or not); 050 * <li>the expression method value can result in another expression method value after being invoke, in which case it is 051 * reinvoked again using the same context; 052 * <li>no further method invoking will be performed. 053 * </ul> 054 * 055 * @author <a href="mailto:[email protected]">Anahide Tchertchian</a> 056 */ 057public class MetaMethodExpression extends MethodExpression implements Serializable { 058 059 private static final long serialVersionUID = -2721042412903607760L; 060 061 private MethodExpression originalMethodExpression; 062 063 private FunctionMapper fnMapper; 064 065 private VariableMapper varMapper; 066 067 public MetaMethodExpression(MethodExpression originalMethodExpression) { 068 this.originalMethodExpression = originalMethodExpression; 069 } 070 071 /** 072 * @since 8.2 073 */ 074 public MetaMethodExpression(MethodExpression originalMethodExpression, FunctionMapper fnMapper, 075 VariableMapper varMapper) { 076 this.originalMethodExpression = originalMethodExpression; 077 this.fnMapper = fnMapper; 078 this.varMapper = varMapper; 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 MetaMethodExpression)) { 089 return false; 090 } 091 MetaMethodExpression other = (MetaMethodExpression) obj; 092 return originalMethodExpression.equals(other.originalMethodExpression); 093 } 094 095 @Override 096 public int hashCode() { 097 return originalMethodExpression.hashCode(); 098 } 099 100 @Override 101 public String getExpressionString() { 102 return originalMethodExpression.getExpressionString(); 103 } 104 105 @Override 106 public boolean isLiteralText() { 107 return originalMethodExpression.isLiteralText(); 108 } 109 110 // MethodExpression interface 111 112 @Override 113 public MethodInfo getMethodInfo(ELContext context) { 114 // TODO Auto-generated method stub 115 return null; 116 } 117 118 private ELContext getLocalContext(ELContext context) { 119 if (fnMapper == null && varMapper == null) { 120 return context; 121 } 122 return new org.nuxeo.ecm.platform.ui.web.binding.EvaluationContext(context, fnMapper, varMapper); 123 } 124 125 @Override 126 public Object invoke(ELContext context, Object[] params) { 127 ELContext nxcontext = getLocalContext(context); 128 Object res = null; 129 if (originalMethodExpression != null) { 130 res = originalMethodExpression.invoke(nxcontext, params); 131 if (res instanceof String) { 132 String expression = (String) res; 133 if (ComponentTagUtils.isValueReference(expression)) { 134 FacesContext faces = FacesContext.getCurrentInstance(); 135 Application app = faces.getApplication(); 136 ExpressionFactory factory = app.getExpressionFactory(); 137 MethodExpression newMeth = factory.createMethodExpression(nxcontext, expression, Object.class, 138 new Class[0]); 139 try { 140 res = newMeth.invoke(nxcontext, null); 141 } catch (ELException e) { 142 throw e; 143 } catch (RuntimeException e) { 144 throw new ELException(e); 145 } 146 } else { 147 res = expression; 148 } 149 } 150 } 151 return res; 152 } 153 154 // Externalizable interface 155 156 public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { 157 originalMethodExpression = (MethodExpression) in.readObject(); 158 } 159 160 public void writeExternal(ObjectOutput out) throws IOException { 161 out.writeObject(originalMethodExpression); 162 } 163 164}