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