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