py.una.pol.karaku.util.ELHelper.java Source code

Java tutorial

Introduction

Here is the source code for py.una.pol.karaku.util.ELHelper.java

Source

/*-
 * Copyright (c)
 *
 *       2012-2014, Facultad Politcnica, Universidad Nacional de Asuncin.
 *       2012-2014, Facultad de Ciencias Mdicas, Universidad Nacional de Asuncin.
 *       2012-2013, Centro Nacional de Computacin, Universidad Nacional de Asuncin.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301  USA
 */
package py.una.pol.karaku.util;

import java.lang.reflect.Field;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.el.ELContext;
import javax.el.ELException;
import javax.el.ExpressionFactory;
import javax.el.MethodExpression;
import javax.el.ValueExpression;
import javax.faces.FacesException;
import javax.faces.application.Application;
import javax.faces.context.FacesContext;
import javax.faces.event.AjaxBehaviorEvent;
import org.ajax4jsf.component.behavior.MethodExpressionAjaxBehaviorListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.ReflectionUtils;

/**
 * Clase que provee funcionalidades para el uso de expresiones
 * 
 * @author Arturo Volpe Torres
 * @author Nathalia Ochoa
 * @since 1.0
 * @version 1.3.2 25/07/2013
 * 
 */
@Component
public class ELHelper {

    /**
     * 
     */
    private static final String CAN_NOT_FIND_THE_FIELD_OF_THE_EXPRESSION = "Can not find the field of the expression: {}";
    public static final ELHelper INSTANCE = new ELHelper();
    private static final String ACTION_METHOD = "#{CONTROLLER.METHOD}";

    /**
     * Dada una expresin del tipo:<br />
     * 
     * <pre>
     *       #{controller.bean.field}
     * </pre>
     * 
     * Determina tres grupos, de la siguiente forma
     * <table>
     * <tr>
     * <th>Expresin</th>
     * <th>Significado</th>
     * </tr>
     * <tr>
     * <td>'#{controller.bean':</td>
     * <td>Parte que determina el bean, completar con <code>}</code> para
     * obtener la expresin.</td>
     * </tr>
     * <tr>
     * <td>'nombre1':</td>
     * <td>Parte que determina el nombre del atributo.</td>
     * </tr>
     * <tr>
     * <td>'}':</td>
     * <td>Parte que completa la Expresin</td>
     * </tr>
     * </table>
     * <br />
     * <br />
     * Reemplazando por ejemplo con $1$3 obtenemos la expresion:
     * 
     * <pre>
     * #{controller.bean}
     * </pre>
     */
    public static final String EXTRACT_FIELD_FROM_EXPRESSION_REGEX = "(#\\{.*)\\.(.*)(\\})";
    private static Pattern pattern;

    private static final Logger LOG = LoggerFactory.getLogger(ELHelper.class);

    /**
     * Crea una expression que se utiliza para representar el tipo
     * 
     * @param expression
     * @param type
     * @return value expression con la expression pasada que retorna el type
     *         especificado
     */
    public ValueExpression makeValueExpression(final String expression, final Class<?> type) {

        ValueExpression ve = getExpressionFactory().createValueExpression(getElContext(), expression, type);
        return ve;
    }

    public MethodExpression makeMethodExpression(final String expression, final Class<?> expectedReturnType,
            final Class<?>... expectedParamTypes) {

        MethodExpression methodExpression = null;
        try {
            FacesContext fc = getContext();
            ExpressionFactory factory = getExpressionFactory();
            methodExpression = factory.createMethodExpression(fc.getELContext(), expression, expectedReturnType,
                    expectedParamTypes);

            return methodExpression;
        } catch (Exception e) {
            throw new FacesException("Method expression '" + expression + "' no se puede crear.", e);
        }
    }

    /**
     * Este mtodo debe retornar un String que se usara para el mapa de
     * navegacin, retornar null o "" para refrescar la pgina
     * 
     * @param controller
     * @param action
     * @return
     */
    public MethodExpression makeActionMethodExpression(final String controller, final String action) {

        String expression = formatExpression(controller, action);
        return makeMethodExpression(expression, String.class);
    }

    /**
     * Crea un mtodo con el formato #{CONTROLLER.ACTION}
     * 
     * @param controller
     * @param action
     * @return
     */
    private String formatExpression(final String controller, final String action) {

        return ACTION_METHOD.replaceFirst("CONTROLLER", controller).replaceFirst("METHOD", action);
    }

    /**
     * Este mtodo genera la expresion para invocar a un metodo utilizando ajax.
     * 
     * @param controller
     * @param action
     * @return
     */
    public MethodExpressionAjaxBehaviorListener createAjaxBehaviorListener(final String controller,
            final String action) {

        String expression = formatExpression(controller, action);
        return new MethodExpressionAjaxBehaviorListener(
                makeMethodExpression(expression, Void.class, new Class[] { AjaxBehaviorEvent.class }));
    }

    private ExpressionFactory getExpressionFactory() {

        return getApplication().getExpressionFactory();
    }

    /**
     * @return context
     */
    public FacesContext getContext() {

        return FacesContext.getCurrentInstance();
    }

    /**
     * @return application
     */
    public Application getApplication() {

        return getContext().getApplication();
    }

    /**
     * @return elContext
     */
    public ELContext getElContext() {

        return getContext().getELContext();
    }

    /**
     * Dada una expresin del tipo
     * 
     * <pre>
     *       #{controller.bean.field}
     * </pre>
     * 
     * Retorna el {@link Field} donde se almacenara el campo field, notar que es
     * a nivel de {@link Field}, es decir, requiere que el getter y el setter,
     * tengan el mismo nombre (getField, setField), no sirve para campos que no
     * cumplan esta condicion.
     * 
     * @param beanExpression
     *            expresin con el formato de
     *            {@link #EXTRACT_FIELD_FROM_EXPRESSION_REGEX}
     * @return {@link Field} del atributo
     * @since 1.3.2
     */
    public static Field getFieldByExpression(String beanExpression) {

        // abre y cierra un parntesis, se utiliza para definir si utiliza algn
        // mtodo.
        if (beanExpression.indexOf('(') != -1 && beanExpression.indexOf(')') != -1) {
            return null;
        }
        FacesContext context = FacesContext.getCurrentInstance();
        Matcher ma = getPattern().matcher(beanExpression);
        if (ma.matches()) {
            String withoutField = ma.replaceFirst("$1$3");
            String field = ma.replaceFirst("$2");
            Object bean;
            try {
                bean = context.getApplication().getExpressionFactory()
                        .createValueExpression(context.getELContext(), withoutField, Object.class)
                        .getValue(context.getELContext());
            } catch (ELException el) {
                // TODO mejorar para tener en cuenta cuando la expresin se
                // refiere a un Vector.
                // Utilizar la expresin regular
                // (#\{.*)\.([a-zA-Z]*|[a-zA-Z]*\[[a-zA-Z\.]*\])(\})
                // See http://www.regexplanet.com/advanced/java/index.html
                LOG.info(CAN_NOT_FIND_THE_FIELD_OF_THE_EXPRESSION, beanExpression, el);
                return null;
            }
            if (bean != null) {
                Field f;
                try {
                    f = bean.getClass().getDeclaredField(field);
                } catch (Exception e) {
                    try {
                        LOG.trace("Can't get field by reflection, trying using proxies", e);
                        f = getFieldForce(field, bean.getClass());
                    } catch (Exception e2) {
                        LOG.debug(CAN_NOT_FIND_THE_FIELD_OF_THE_EXPRESSION, beanExpression, e2);
                        return null;
                    }
                }
                return f;
            }
        }
        return null;
    }

    private static Field getFieldForce(String name, Class<?> clazz) {

        if (clazz.getName().toUpperCase().contains("CGLIB")) {
            return getFieldFromCGEnhancedClass(name, clazz);
        }
        // TODO ver cuando se utiliza javassist
        return null;
    }

    private static Field getFieldFromCGEnhancedClass(String name, Class<?> clazz) {

        Class<?> real = clazz.getSuperclass();
        return ReflectionUtils.findField(real, name);
    }

    private static synchronized Pattern getPattern() {

        if (pattern == null) {
            pattern = Pattern.compile(ELHelper.EXTRACT_FIELD_FROM_EXPRESSION_REGEX);
        }
        return pattern;
    }
}