001    package org.apache.myfaces.tobago.compat;
002    
003    /*
004     * Licensed to the Apache Software Foundation (ASF) under one or more
005     * contributor license agreements.  See the NOTICE file distributed with
006     * this work for additional information regarding copyright ownership.
007     * The ASF licenses this file to You under the Apache License, Version 2.0
008     * (the "License"); you may not use this file except in compliance with
009     * the License.  You may obtain a copy of the License at
010     *
011     *      http://www.apache.org/licenses/LICENSE-2.0
012     *
013     * Unless required by applicable law or agreed to in writing, software
014     * distributed under the License is distributed on an "AS IS" BASIS,
015     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016     * See the License for the specific language governing permissions and
017     * limitations under the License.
018     */
019    
020    import org.apache.myfaces.tobago.event.TabChangeSource;
021    import org.apache.myfaces.tobago.event.ValueExpressionPopupActionListener;
022    import org.apache.myfaces.tobago.event.ValueExpressionTabChangeListener;
023    import org.apache.myfaces.tobago.util.ValueExpressionComparator;
024    import org.slf4j.Logger;
025    import org.slf4j.LoggerFactory;
026    
027    import javax.el.ExpressionFactory;
028    import javax.el.MethodExpression;
029    import javax.el.ValueExpression;
030    import javax.faces.component.ActionSource;
031    import javax.faces.component.ContextCallback;
032    import javax.faces.component.EditableValueHolder;
033    import javax.faces.component.NamingContainer;
034    import javax.faces.component.UIComponent;
035    import javax.faces.component.ValueHolder;
036    import javax.faces.context.FacesContext;
037    import javax.faces.el.EvaluationException;
038    import javax.faces.el.MethodBinding;
039    import javax.faces.event.AbortProcessingException;
040    import javax.faces.event.FacesEvent;
041    import javax.faces.validator.MethodExpressionValidator;
042    import java.util.Comparator;
043    
044    public class FacesUtilsEL {
045    
046      private static final Logger LOG = LoggerFactory.getLogger(FacesUtilsEL.class);
047    
048      public static boolean invokeOnComponent(
049          FacesContext context, UIComponent component, String clientId, ContextCallback callback) {
050        String thisClientId = component.getClientId(context);
051    
052        if (clientId.equals(thisClientId)) {
053          callback.invokeContextCallback(context, component);
054          return true;
055        } else if (component instanceof NamingContainer) {
056          // This component is a naming container. If the client id shows it's inside this naming container,
057          // then process further.
058          // Otherwise we know the client id we're looking for is not in this naming container,
059          // so for improved performance short circuit and return false.
060          if (clientId.startsWith(thisClientId)
061              && (clientId.charAt(thisClientId.length()) == NamingContainer.SEPARATOR_CHAR)) {
062            if (invokeOnComponentFacetsAndChildren(context, component, clientId, callback)) {
063              return true;
064            }
065          }
066        } else {
067          if (invokeOnComponentFacetsAndChildren(context, component, clientId, callback)) {
068            return true;
069          }
070        }
071    
072        return false;
073      }
074    
075      private static boolean invokeOnComponentFacetsAndChildren(
076          FacesContext context, UIComponent component, String clientId, ContextCallback callback) {
077        for (java.util.Iterator<UIComponent> it = component.getFacetsAndChildren(); it.hasNext();) {
078          UIComponent child = it.next();
079    
080          if (child.invokeOnComponent(context, clientId, callback)) {
081            return true;
082          }
083        }
084        return false;
085      }
086    
087      public static void invokeMethodBinding(FacesContext facesContext, MethodBinding methodBinding, FacesEvent event) {
088        if (methodBinding != null && event != null) {
089          try {
090            methodBinding.invoke(facesContext, new Object[]{event});
091          } catch (EvaluationException e) {
092            Throwable cause = e.getCause();
093            if (cause instanceof AbortProcessingException) {
094              throw (AbortProcessingException) cause;
095            } else {
096              throw e;
097            }
098          }
099        }
100      }
101    
102      public static void invokeMethodExpression(
103          FacesContext facesContext, MethodExpression methodExpression, FacesEvent event) {
104    
105        if (methodExpression != null && event != null) {
106          try {
107            methodExpression.invoke(facesContext.getELContext(), new Object[]{event});
108          } catch (Exception e) {
109            throw new AbortProcessingException(e);
110          }
111        }
112      }
113    
114      public static Object getValueFromValueBindingOrValueExpression(
115          FacesContext context, UIComponent component, String name) {
116        return component.getValueExpression(name).getValue(context.getELContext());
117      }
118    
119    
120      public static boolean hasValueBindingOrValueExpression(UIComponent component, String name) {
121        return component.getValueExpression(name) != null;
122      }
123    
124      public static boolean isReadonlyValueBindingOrValueExpression(
125          FacesContext context, UIComponent component, String name) {
126        return component.getValueExpression(name).isReadOnly(context.getELContext());
127      }
128    
129    
130      public static String getExpressionString(UIComponent component, String name) {
131        return component.getValueExpression(name).getExpressionString();
132      }
133    
134      public static void setValueOfBindingOrExpression(
135          FacesContext context, Object value, UIComponent component, String bindingName) {
136        ValueExpression ve = component.getValueExpression(bindingName);
137        if (ve != null) {
138          ve.setValue(context.getELContext(), value);
139        }
140      }
141    
142      public static void setValueOfBindingOrExpression(
143          FacesContext context, Object value, Object bindingOrExpression) {
144        if (bindingOrExpression instanceof ValueExpression) {
145          ValueExpression ve = (ValueExpression) bindingOrExpression;
146          ve.setValue(context.getELContext(), value);
147        }
148      }
149    
150      public static void copyValueBindingOrValueExpression(
151          UIComponent fromComponent, String fromName, UIComponent toComponent, String toName) {
152        ValueExpression ve = fromComponent.getValueExpression(fromName);
153        if (ve != null) {
154          toComponent.setValueExpression(toName, ve);
155        }
156      }
157    
158      public static Object getValueFromBindingOrExpression(Object obj) {
159        if (obj instanceof ValueExpression) {
160          ValueExpression expression = (ValueExpression) obj;
161          return expression.getValue(FacesContext.getCurrentInstance().getELContext());
162        }
163        return null;
164      }
165    
166      public static Object createExpressionOrBinding(String string) {
167        FacesContext facesContext = FacesContext.getCurrentInstance();
168        ExpressionFactory expressionFactory = facesContext.getApplication().getExpressionFactory();
169        ValueExpression valueExpression =
170            expressionFactory.createValueExpression(facesContext.getELContext(), string, Object.class);
171        return valueExpression;
172      }
173    
174      public static void setValidator(EditableValueHolder editableValueHolder, Object validator) {
175        if (validator instanceof MethodExpression) {
176          editableValueHolder.addValidator(new MethodExpressionValidator((MethodExpression) validator));
177        } else {
178          LOG.error("Unknow instance for validator: " + (validator != null ? validator.getClass().getName() : validator));
179        }
180      }
181    
182      public static void setConverter(ValueHolder valueHolder, Object converterExpression) {
183        if (converterExpression instanceof ValueExpression) {
184          ValueExpression expression = (ValueExpression) converterExpression;
185          if (!expression.isLiteralText()) {
186            ((UIComponent) valueHolder).setValueExpression("converter", expression);
187          } else {
188            valueHolder.setConverter(FacesContext.getCurrentInstance()
189                .getApplication().createConverter(expression.getExpressionString()));
190          }
191        }
192      }
193    
194      public static void setBindingOrExpression(UIComponent component, String name, Object valueBindingOrExpression) {
195        component.setValueExpression(name, (ValueExpression) valueBindingOrExpression);
196      }
197    
198      public static void addBindingOrExpressionTabChangeListener(
199          TabChangeSource source, String type, Object bindingOrExpression) {
200        if (bindingOrExpression instanceof ValueExpression) {
201          source.addTabChangeListener(new ValueExpressionTabChangeListener(type, (ValueExpression) bindingOrExpression));
202        }
203      }
204    
205      public static Comparator getBindingOrExpressionComparator(
206          FacesContext facesContext, UIComponent child, String var, boolean descending, Comparator comparator) {
207        ValueExpression valueBinding = child.getValueExpression("value");
208        return new ValueExpressionComparator(facesContext, var, valueBinding, descending, comparator);
209      }
210    
211      public static void addBindingOrExpressionPopupActionListener(ActionSource actionSource, Object bindingOrExpression) {
212        actionSource.addActionListener(new ValueExpressionPopupActionListener((ValueExpression) bindingOrExpression));
213      }
214    }