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: GenericValueHolderRule.java 28456 2008-01-03 12:01:11Z sfermigier $
018 */
019
020package org.nuxeo.ecm.platform.ui.web.tag.jsf;
021
022import javax.el.MethodExpression;
023import javax.el.ValueExpression;
024import javax.faces.component.UIComponent;
025import javax.faces.component.ValueHolder;
026import javax.faces.convert.Converter;
027import javax.faces.view.facelets.FaceletContext;
028import javax.faces.view.facelets.MetaRule;
029import javax.faces.view.facelets.Metadata;
030import javax.faces.view.facelets.MetadataTarget;
031import javax.faces.view.facelets.TagAttribute;
032
033import org.nuxeo.ecm.platform.ui.web.binding.MethodValueExpression;
034import org.nuxeo.ecm.platform.ui.web.util.ComponentTagUtils;
035
036import com.sun.faces.facelets.el.LegacyValueBinding;
037
038/**
039 * Generic value rule, used to evaluate an expression as a regular value expression, or invoking a method expression.
040 * <p>
041 * The method can have parameters and the expression must use parentheses even if no parameters are needed.
042 *
043 * @author <a href="mailto:at@nuxeo.com">Anahide Tchertchian</a>
044 * @deprecated since 5.7.3: resolving method expressions for value expressions is now supported by the default EL, this
045 *             is now useless
046 */
047@Deprecated
048public class GenericValueHolderRule extends MetaRule {
049
050    static final class LiteralConverterMetadata extends Metadata {
051
052        private final String converterId;
053
054        LiteralConverterMetadata(String converterId) {
055            this.converterId = converterId;
056        }
057
058        @Override
059        public void applyMetadata(FaceletContext ctx, Object instance) {
060            ((ValueHolder) instance).setConverter(ctx.getFacesContext().getApplication().createConverter(converterId));
061        }
062    }
063
064    static final class DynamicConverterMetadata2 extends Metadata {
065
066        private final TagAttribute attr;
067
068        DynamicConverterMetadata2(TagAttribute attr) {
069            this.attr = attr;
070        }
071
072        @Override
073        public void applyMetadata(FaceletContext ctx, Object instance) {
074            ((UIComponent) instance).setValueExpression("converter", attr.getValueExpression(ctx, Converter.class));
075        }
076    }
077
078    static final class LiteralValueMetadata extends Metadata {
079
080        private final String value;
081
082        LiteralValueMetadata(String value) {
083            this.value = value;
084        }
085
086        @Override
087        public void applyMetadata(FaceletContext ctx, Object instance) {
088            ((ValueHolder) instance).setValue(value);
089        }
090    }
091
092    static final class DynamicValueExpressionMetadata extends Metadata {
093
094        private final TagAttribute attr;
095
096        DynamicValueExpressionMetadata(TagAttribute attr) {
097            this.attr = attr;
098        }
099
100        @Override
101        public void applyMetadata(FaceletContext ctx, Object instance) {
102            ((UIComponent) instance).setValueExpression("value", attr.getValueExpression(ctx, Object.class));
103        }
104    }
105
106    static final class MethodValueBindingMetadata extends Metadata {
107
108        private final TagAttribute attr;
109
110        MethodValueBindingMetadata(TagAttribute attr) {
111            this.attr = attr;
112        }
113
114        @Override
115        public void applyMetadata(FaceletContext ctx, Object instance) {
116            Class[] paramTypesClasses = new Class[0];
117            Class returnType = Object.class;
118            MethodExpression meth = attr.getMethodExpression(ctx, returnType, paramTypesClasses);
119            ValueExpression ve = new MethodValueExpression(ctx.getFunctionMapper(), ctx.getVariableMapper(), meth,
120                    paramTypesClasses);
121            ((UIComponent) instance).setValueBinding("value", new LegacyValueBinding(ve));
122        }
123    }
124
125    public static final GenericValueHolderRule Instance = new GenericValueHolderRule();
126
127    @Override
128    public Metadata applyRule(String name, TagAttribute attribute, MetadataTarget meta) {
129        if (meta.isTargetInstanceOf(ValueHolder.class)) {
130
131            if ("converter".equals(name)) {
132                if (attribute.isLiteral()) {
133                    return new LiteralConverterMetadata(attribute.getValue());
134                } else {
135                    return new DynamicConverterMetadata2(attribute);
136                }
137            }
138
139            if ("genericValue".equals(name)) {
140                if (attribute.isLiteral()) {
141                    return new LiteralValueMetadata(attribute.getValue());
142                } else {
143                    String value = attribute.getValue();
144                    if (ComponentTagUtils.isMethodReference(value)) {
145                        // value expression resolved invoking a method
146                        // expression
147                        return new MethodValueBindingMetadata(attribute);
148                    } else {
149                        // regular value expression
150                        return new DynamicValueExpressionMetadata(attribute);
151                    }
152                }
153            }
154
155        }
156        return null;
157    }
158
159}