de.beyondjava.angularFaces.core.ELTools.java Source code

Java tutorial

Introduction

Here is the source code for de.beyondjava.angularFaces.core.ELTools.java

Source

/**
 *  (C) 2013-2014 Stephan Rauh http://www.beyondjava.net
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package de.beyondjava.angularFaces.core;

import java.lang.annotation.Annotation;
import java.lang.reflect.*;
import java.util.*;
import java.util.logging.*;

import javax.el.*;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;

import org.apache.commons.beanutils.BeanUtilsBean2;

public class ELTools {
    private static Map<String, NGBeanAttributeInfo> beanAttributeInfos = new HashMap<String, NGBeanAttributeInfo>();

    /** Caching */
    private static Map<String, Field> fields = new HashMap<String, Field>();

    private static final Logger LOGGER = Logger.getLogger("de.beyondjava.angularFaces.common.ELTools");
    /** Caching */
    private static Map<String, List<String>> propertyLists = new HashMap<String, List<String>>();

    public static ValueExpression createValueExpression(String p_expression) {
        FacesContext context = FacesContext.getCurrentInstance();
        ExpressionFactory expressionFactory = context.getApplication().getExpressionFactory();
        ELContext elContext = context.getELContext();
        ValueExpression vex = expressionFactory.createValueExpression(elContext, p_expression, Object.class);
        return vex;
    }

    /**
     * Evaluates an EL expression into an object.
     *
     * @param p_expression
     * @return
     */
    public static Object evalAsObject(String p_expression) {
        FacesContext context = FacesContext.getCurrentInstance();
        ExpressionFactory expressionFactory = context.getApplication().getExpressionFactory();
        ELContext elContext = context.getELContext();
        ValueExpression vex = expressionFactory.createValueExpression(elContext, p_expression, Object.class);
        Object result = vex.getValue(elContext);
        return result;
    }

    /**
     * Evaluates an EL expression into a string.
     *
     * @param p_expression
     * @return
     */
    public static String evalAsString(String p_expression) {
        FacesContext context = FacesContext.getCurrentInstance();
        ExpressionFactory expressionFactory = context.getApplication().getExpressionFactory();
        ELContext elContext = context.getELContext();
        ValueExpression vex = expressionFactory.createValueExpression(elContext, p_expression, String.class);
        String result = (String) vex.getValue(elContext);
        return result;
    }

    /**
     * Returns a list of String denoting every primitively typed property of a certain bean.
     *
     * @param p_expression
     *            The EL expression describing the bean. The EL expression is passed without the leading "#{" and the
     *            trailing brace "}".
     * @param p_recursive
     *            if true, the list also contains properties of nested beans.
     * @return a list of strings consisting of EL expressions without the leading "#{" and the trailing brace "}".
     */
    public static List<String> getArrayProperties(String p_expression, boolean p_recursive) {
        Object container = evalAsObject("#{" + p_expression + "}");

        Class<? extends Object> c = container == null ? null : container.getClass();
        List<String> propertyNames = new ArrayList<String>();
        if (isPrimitive(c)) {
            propertyNames.add(p_expression);
        } else {
            try {
                @SuppressWarnings("unchecked")
                Map<String, Object> description = BeanUtilsBean2.getInstance().describe(container);
                for (String o : description.keySet()) {
                    Object object = description.get(o);
                    if (object == null) {
                        String getter = "get" + o.substring(0, 1).toUpperCase() + o.substring(1);
                        Method method = container.getClass().getMethod(getter);
                        if (null != method) {
                            Object property = method.invoke(container);
                            if (null != property) {
                                if (property instanceof List) {
                                    LOGGER.info("List");
                                }
                            }
                        }
                    }
                }
            } catch (IllegalAccessException e) {
                // todo replace by a logger
                LOGGER.log(Level.SEVERE, "Couldn\"t read property list of " + p_expression, e);
            } catch (InvocationTargetException e) {
                // todo replace by a logger
                LOGGER.log(Level.SEVERE, "Couldn\"t read property list of " + p_expression, e);
            } catch (NoSuchMethodException e) {
                // todo replace by a logger
                LOGGER.log(Level.SEVERE, "Couldn\"t read property list of " + p_expression, e);
            }
        }
        return propertyNames;
    }

    public static NGBeanAttributeInfo getBeanAttributeInfos(UIComponent c) {
        String core = getCoreValueExpression(c);
        synchronized (beanAttributeInfos) {
            if (beanAttributeInfos.containsKey(c)) {
                return beanAttributeInfos.get(c);
            }
        }
        NGBeanAttributeInfo info = new NGBeanAttributeInfo(c);
        beanAttributeInfos.put(core, info);
        return info;
    }

    public static String getCoreValueExpression(UIComponent component) {
        ValueExpression valueExpression = component.getValueExpression("value");
        if (null != valueExpression) {
            String v = valueExpression.getExpressionString();
            if (null != v) {
                String model = v.replace("#{", "").replace("}", "");
                return model;
            }
        }
        return null;
    }

    /**
     * Returns a list of String denoting every primitively typed property of a certain bean.
     *
     * @param p_expression
     *            The EL expression describing the bean. The EL expression is passed without the leading "#{" and the
     *            trailing brace "}".
     * @param p_recursive
     *            if true, the list also contains properties of nested beans.
     * @return a list of strings consisting of EL expressions without the leading "#{" and the trailing brace "}".
     */
    public static List<String> getEveryProperty(String p_expression, boolean p_recursive) {
        synchronized (propertyLists) {
            if (propertyLists.containsKey(p_expression)) {
                return propertyLists.get(p_expression);
            }
        }

        Object container = evalAsObject("#{" + p_expression + "}");

        Class<? extends Object> c = container == null ? null : container.getClass();
        List<String> propertyNames = new ArrayList<String>();
        if (isPrimitive(c)) {
            propertyNames.add(p_expression);
        } else {
            try {
                @SuppressWarnings("unchecked")
                Map<String, Object> description = BeanUtilsBean2.getInstance().describe(container);
                for (String o : description.keySet()) {
                    Object object = description.get(o);
                    if (object == null) {
                        // might be an array
                    } else if (o.equals("class")) {
                        continue;
                    } else if (isPrimitive(object.getClass())) {
                        propertyNames.add(o);
                    }

                    else if (p_recursive) {
                        List<String> nested = getEveryProperty(p_expression + "." + o, p_recursive);
                        for (String n : nested) {
                            propertyNames.add(o + "." + n);
                        }
                    }
                }
                synchronized (propertyLists) {
                    propertyLists.put(p_expression, propertyNames);
                }
            } catch (IllegalAccessException e) {
                // todo replace by a logger
                LOGGER.log(Level.SEVERE, "Couldn\"t read property list of " + p_expression, e);
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                // todo replace by a logger
                LOGGER.log(Level.SEVERE, "Couldn\"t read property list of " + p_expression, e);
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                // todo replace by a logger
                LOGGER.log(Level.SEVERE, "Couldn\"t read property list of " + p_expression, e);
            }
        }
        return propertyNames;
    }

    private static Field getField(String p_expression) {
        synchronized (fields) {
            if (fields.containsKey(p_expression)) {
                return fields.get(p_expression);
            }
        }

        if (p_expression.startsWith("#{") && p_expression.endsWith("}")) {
            int delimiterPos = p_expression.lastIndexOf('.');
            if (delimiterPos < 0) {
                LOGGER.log(Level.WARNING, "There's no field to access: #{" + p_expression + "}");
                return null;
            }
            String beanExp = p_expression.substring(0, delimiterPos) + "}";
            String fieldName = p_expression.substring(delimiterPos + 1, p_expression.length() - 1);
            Object container = evalAsObject(beanExp);
            if (null == container) {
                LOGGER.severe("Can't read the bean '" + beanExp
                        + "'. Thus JSR 303 annotations can't be read, let alone used by the AngularDart client.");
                return null;
            }

            Class<? extends Object> c = container.getClass();
            while (c != null) {
                Field declaredField;
                try {
                    declaredField = c.getDeclaredField(fieldName);
                    synchronized (fields) {
                        fields.put(p_expression, declaredField);
                    }
                    return declaredField;
                } catch (NoSuchFieldException e) {
                    // let\"s try with the super class
                    c = c.getSuperclass();
                } catch (SecurityException e) {
                    LOGGER.log(Level.SEVERE, "Unable to access a field", e);
                    e.printStackTrace();
                    return null;
                }
            }
        }
        return null;
    }

    public static String getNGModel(UIComponent p_component) {
        String id = ELTools.getCoreValueExpression(p_component);
        if (id.contains(".")) {
            int index = id.lastIndexOf(".");
            id = id.substring(index + 1);
        }
        return id;
    }

    /**
     * Yields the type of the variable given by an expression.
     *
     * @param p_expression
     * @return
     */
    public static Class<?> getType(String p_expression) {
        Field declaredField = getField(p_expression);
        if (null != declaredField) {
            return declaredField.getType();
        }
        return null;
    }

    /**
     * Yields the type of the variable displayed by a component.
     *
     * @param p_component
     *            the UIComponent
     * @return
     */
    public static Class<?> getType(UIComponent p_component) {
        ValueExpression valueExpression = p_component.getValueExpression("value");
        if (valueExpression != null) {
            return getType(valueExpression.getExpressionString());
        }
        return null;
    }

    public static boolean hasValueExpression(UIComponent component) {
        ValueExpression valueExpression = component.getValueExpression("value");
        return null != valueExpression;
    }

    /**
     * Is the parameter passed a primitive type (such as int, long, etc) or a type considered primitive by most
     * programmers (such as String)?
     *
     * @param c
     * @return true if c is a de-facto-primitive
     */
    private static boolean isPrimitive(Class<? extends Object> c) {
        return (null == c) || (Class.class == c) || (String.class == c) || c.isPrimitive() || (Integer.class == c)
                || (Long.class == c) || (Short.class == c) || (Byte.class == c) || (Character.class == c)
                || (Float.class == c) || (Double.class == c) || (Void.class == c) || (Boolean.class == c);
    }

    /**
     * Which annotations are given to an object described by an EL expression?
     *
     * @param p_component
     * @return null if there are no annotations, or if they cannot be accessed
     */
    public static Annotation[] readAnnotations(String p_expression) {
        Field declaredField = getField(p_expression);
        if (null != declaredField) {
            return declaredField.getAnnotations();
        }
        return null;
    }

    /**
     * Which annotations are given to an object displayed by a JSF component?
     *
     * @param p_component
     * @return null if there are no annotations, or if they cannot be accessed
     */
    public static Annotation[] readAnnotations(UIComponent p_component) {
        ValueExpression valueExpression = p_component.getValueExpression("value");
        if (valueExpression != null) {
            return readAnnotations(valueExpression.getExpressionString());
        }
        return null;
    }

}