org.tinygroup.template.rumtime.TemplateUtil.java Source code

Java tutorial

Introduction

Here is the source code for org.tinygroup.template.rumtime.TemplateUtil.java

Source

/**
 * Copyright (c) 1997-2013, www.tinygroup.org (luo_guo@icloud.com).
 * <p/>
 * Licensed under the GPL, Version 3.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p/>
 * http://www.gnu.org/licenses/gpl.html
 * <p/>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.tinygroup.template.rumtime;

import org.apache.commons.beanutils.MethodUtils;
import org.apache.commons.beanutils.PropertyUtilsBean;
import org.apache.commons.lang.StringUtils;
import org.tinygroup.beancontainer.BeanContainer;
import org.tinygroup.beancontainer.BeanContainerFactory;
import org.tinygroup.commons.tools.ArrayUtil;
import org.tinygroup.commons.tools.Enumerator;
import org.tinygroup.context.Context;
import org.tinygroup.template.*;

import java.beans.PropertyDescriptor;
import java.lang.reflect.*;
import java.math.BigDecimal;
import java.net.URI;
import java.util.*;

/**
 * ??
 * Created by luoguo on 2014/6/4.
 */
public final class TemplateUtil {
    private static Map<Class, Map<String, Method>> methodCache = new HashMap<Class, Map<String, Method>>();
    private static Map<Class, Map<String, Field>> fieldCache = new HashMap<Class, Map<String, Field>>();
    private static PropertyUtilsBean propertyUtilsBean = new PropertyUtilsBean();
    private static String[] tabCache = new String[31];
    private static boolean safeVariable = false;
    private static BeanContainer<?> container = BeanContainerFactory
            .getBeanContainer(TemplateUtil.class.getClassLoader());

    static {
        tabCache[0] = "";
        for (int i = 1; i < tabCache.length; i++) {
            tabCache[i] = String.format("%" + i * 4 + "s", "");
        }
    }

    private TemplateUtil() {
    }

    public static boolean isSafeVariable() {
        return safeVariable;
    }

    public static void setSafeVariable(boolean safeVariable) {
        TemplateUtil.safeVariable = safeVariable;
    }

    /**
     * ?
     *
     * @param object
     * @param name
     * @return
     * @throws TemplateException
     */
    public static Object getAttribute(Object object, Object name) throws TemplateException {
        try {
            if (object instanceof Map) {
                Object value = ((Map) object).get(name);
                if (value != null) {
                    return value;
                }
            }
            String fieldName = name.toString();
            Map<String, Method> stringMethodMap = methodCache.get(object.getClass());
            Method method = null;
            if (stringMethodMap != null) {
                method = stringMethodMap.get(fieldName);
            }
            if (method == null) {
                PropertyDescriptor descriptor = propertyUtilsBean.getPropertyDescriptor(object, fieldName);
                if (descriptor != null && descriptor.getReadMethod() != null) {
                    method = object.getClass().getMethod(descriptor.getReadMethod().getName());
                    method.setAccessible(true);
                    if (stringMethodMap == null) {
                        stringMethodMap = new HashMap<String, Method>();
                        methodCache.put(object.getClass(), stringMethodMap);
                    }
                    stringMethodMap.put(fieldName, method);
                }
            }
            if (method != null) {
                return method.invoke(object);
            }
            Map<String, Field> stringFieldMap = fieldCache.get(fieldName);
            Field field = null;
            if (stringFieldMap != null) {
                field = stringFieldMap.get(fieldName);
            }
            if (field == null) {
                field = object.getClass().getField(fieldName);
                if (field != null) {
                    if ((field.getModifiers() & Modifier.PUBLIC) == Modifier.PUBLIC) {
                        field.setAccessible(true);
                        if (stringFieldMap == null) {
                            stringFieldMap = new HashMap<String, Field>();
                            fieldCache.put(object.getClass(), stringFieldMap);
                        }
                        stringFieldMap.put(fieldName, field);
                    } else {
                        field = null;
                    }
                }
            }
            if (field != null) {
                return field.get(object);
            }
            throw new TemplateException(
                    object.getClass().getName() + "?" + fieldName + "?");
        } catch (Exception e) {
            throw new TemplateException(e);
        }
    }

    public static Object sp(Object object, Object name) throws TemplateException {
        if (object != null) {
            try {
                return getAttribute(object, name);
            } catch (TemplateException e) {
                if (e.getCause().getClass() == NullPointerException.class
                        || e.getCause().getClass() == NoSuchFieldException.class
                        || e.getMessage().indexOf("?") > 0) {
                    return null;
                } else {
                    throw e;
                }
            }
        }
        return null;
    }

    /**
     * ?
     *
     * @param i18nVistor
     * @param key
     * @return
     */
    public static String getI18n(I18nVisitor i18nVistor, TemplateContext context, String key) {
        if (key == null) {
            return null;
        }
        if (i18nVistor == null) {
            return key;
        } else {
            return i18nVistor.getI18nMessage(context, key);
        }
    }

    /**
     * 
     *
     * @param object
     * @param methodName
     * @param parameters
     * @return
     * @throws TemplateException
     */
    public static Object callMethod(Template template, TemplateContext context, Object object, String methodName,
            Object... parameters) throws TemplateException {
        try {
            TemplateFunction function = template.getTemplateEngine().getTemplateFunction(object, methodName);
            if (function != null) {
                return executeExtendFunction(template, context, object, function, parameters);
            } else {
                //?
                return executeClassMethod(object, methodName, parameters);
            }
        } catch (Exception e) {
            //??
            if (e instanceof InvocationTargetException) {
                InvocationTargetException e1 = (InvocationTargetException) e;
                throw new TemplateException(e1.getTargetException());
            }
            throw new TemplateException(e);
        }
    }

    public static Object executeClassMethod(Object object, String methodName, Object[] parameters)
            throws Exception {
        Method method = getMethodByName(object, methodName, parameters);
        //?
        if (method != null) {
            return method.invoke(object, parameters);
        }
        if (object instanceof StaticClassOperator) {
            return ((StaticClassOperator) object).invokeStaticMethod(methodName, parameters);
        } else {
            return MethodUtils.invokeMethod(object, methodName, parameters);
        }
    }

    private static Method getMethodByName(Object object, String methodName, Object[] parameters) {
        Method method = null;
        Map<String, Method> stringMethodMap = methodCache.get(object.getClass());
        if (stringMethodMap != null) {
            method = stringMethodMap.get(methodName);
        }
        if (method == null) {
            List<Method> methods = getMethodList(object.getClass(), methodName);
            if (methods.size() == 1) {
                method = methods.get(0);
                if (stringMethodMap == null) {
                    stringMethodMap = new HashMap<String, Method>();
                    methodCache.put(object.getClass(), stringMethodMap);
                }
                stringMethodMap.put(methodName, method);
            } else {
                for (Method method1 : methods) {
                    if (method1.getParameterTypes().length != parameters.length) {
                        continue;
                    }
                    int count = 0;
                    for (int i = 0; i < method1.getParameterTypes().length; i++) {
                        if (parameters[i] == null
                                || parameters[i].getClass().equals(method1.getParameterTypes()[i].getClass())) {
                            count++;
                        }
                    }
                    if (count == method1.getParameterTypes().length) {
                        return method1;
                    }
                }
            }
        }
        return method;
    }

    private static List<Method> getMethodList(Class clz, String methodName) {
        List<Method> methods = new ArrayList<Method>();
        for (Method method : clz.getMethods()) {
            if (method.getName().equals(methodName)) {
                methods.add(method);
            }
        }
        return methods;
    }

    private static Object executeExtendFunction(Template template, TemplateContext context, Object object,
            TemplateFunction function, Object[] parameters) throws TemplateException {
        Object[] newParameters = new Object[(parameters == null ? 1 : parameters.length) + 1];
        newParameters[0] = object;
        if (parameters != null && parameters.length > 0) {
            System.arraycopy(parameters, 0, newParameters, 1, parameters.length);
        }
        return function.execute(template, context, newParameters);
    }

    /**
     * 
     *
     * @param object
     * @param methodName
     * @param parameters
     * @return
     * @throws TemplateException
     */
    public static Object safeCallMethod(Template template, TemplateContext context, Object object,
            String methodName, Object... parameters) throws TemplateException {
        if (object != null) {
            try {
                return callMethod(template, context, object, methodName, parameters);
            } catch (TemplateException e) {
                if (e.getCause().getClass() == NoSuchMethodException.class) {
                    return null;
                } else {
                    throw e;
                }
            }
        }
        return null;
    }

    public static Class<?>[] getParameterTypes(Class clazz, String methodName) throws TemplateException {
        for (Method method : clazz.getMethods()) {
            if (method.getName().equals(methodName)) {
                return method.getParameterTypes();
            }
        }
        throw new TemplateException(clazz.getName() + "?:" + methodName);
    }

    /**
     * ?
     *
     * @param context
     * @param key
     * @return
     */
    public static Object getValueFromContext(Context context, Object key) {
        return context.get(key.toString());
    }

    /**
     * Bean
     * @param key
     * @return
     */
    public static Object getValueFromBean(Object key) {
        try {
            return container.getBean(key.toString());
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * ??
     * @param context
     * @param key
     * @return
     */
    public static Object getVariableValue(Context context, Object key) {
        Object value = getValueFromContext(context, key);
        if (value == null) {
            value = getValueFromBean(key);
        }
        return value;
    }

    /**
     * ???
     *
     * @param currentPath
     * @param newPath
     * @return
     */
    public static String getPath(String currentPath, String newPath) {
        String path = newPath;
        URI uri = URI.create(currentPath);
        path = path.replaceAll("[\\\\]", "/");
        URI newUri = uri.resolve(path);
        return newUri.getPath();
    }

    public static void dent(TemplateContext context) {
        Boolean compactMode = context.get("$compactMode");
        //?
        if (compactMode != null && compactMode) {
            return;
        }
        Integer tab = context.get("$tab");
        if (tab != null) {
            context.put("$tab", tab + 1);
        } else {
            context.put("$tab", 1);
        }
    }

    public static void indent(TemplateContext context) {
        //?
        Boolean compactMode = context.get("$compactMode");
        if (compactMode != null && compactMode) {
            return;
        }
        Integer tab = context.get("$tab");
        if (tab != null) {
            context.put("$tab", tab - 1);
        } else {
            context.put("$tab", 0);
        }
    }

    public static String getBlanks(TemplateContext context) {
        //?
        Boolean compactMode = context.get("$compactMode");
        if (compactMode != null && compactMode) {
            return null;
        }
        Integer tab = context.get("$tab");
        if (tab != null) {
            if (tab < tabCache.length) {
                return tabCache[tab];
            } else {
                return tabCache[tabCache.length - 1];
            }
        }
        return null;
    }

    /**
     * Html
     *
     * @param object
     * @return
     */
    public static String escapeHtml(Object object) {
        if (object == null) {
            return null;
        }
        return StringUtils.replaceEach(object.toString(), new String[] { "&", "\"", "<", ">" },
                new String[] { "&amp;", "&quot;", "&lt;", "&gt;" });

    }

    /**
     * ??
     *
     * @param object
     * @return
     */
    public static boolean getBooleanValue(Object object) {
        if (object == null) {
            return false;
        }
        if (object.getClass() == Boolean.class) {
            return ((Boolean) object).booleanValue();
        } else if (object.getClass() == String.class) {
            return ((String) object).length() > 0;
        } else if (object instanceof Collection) {
            return ((Collection) object).size() > 0;
        } else if (object.getClass().isArray()) {
            return ArrayUtil.arrayLength(object) > 0;
        } else if (object instanceof Iterator) {
            return ((Iterator) object).hasNext();
        } else if (object instanceof Enumerator) {
            Enumerator e = (Enumerator) object;
            return e.hasMoreElements();
        } else if (object instanceof Map) {
            Map e = (Map) object;
            return e.size() > 0;
        }
        return true;
    }

    /**
     * 
     *
     * @param object
     * @param indexObject 
     * @return
     * @throws Exception
     */
    public static Object getSafeArrayValue(Object object, Object indexObject) throws TemplateException {
        if (object == null) {
            return null;
        } else {
            try {
                return getArrayValue(object, indexObject);
            } catch (Exception e) {
                return null;
            }
        }
    }

    public static Object getArrayValue(Object object, Object indexObject) throws TemplateException {
        int index;
        try {
            if (object instanceof Map) {
                Map map = (Map) object;
                return map.get(indexObject);
            }
            if (indexObject instanceof Integer) {
                index = ((Integer) indexObject).intValue();
            } else if (indexObject instanceof Long) {
                index = ((Long) indexObject).intValue();
            } else if (indexObject instanceof Double) {
                index = ((Double) indexObject).intValue();
            } else if (indexObject instanceof Float) {
                index = ((Float) indexObject).intValue();
            } else if (indexObject instanceof Byte) {
                index = ((Byte) indexObject).intValue();
            } else if (indexObject instanceof BigDecimal) {
                index = ((BigDecimal) indexObject).intValue();
            } else {
                index = Integer.parseInt(indexObject.toString());
            }
            if (object.getClass().isArray()) {
                return Array.get(object, index);
            } else if (object instanceof Collection) {
                Collection c = (Collection) object;
                int i = 0;
                Iterator it = c.iterator();
                while (i < c.size()) {
                    Object o = it.next();
                    if (i == index) {
                        return o;
                    }
                    i++;
                }
                return null;
            } else {
                String o = object.toString();
                return o.charAt(index);
            }
        } catch (Exception e) {
            throw new IllegalArgumentException(String.format("%s%s??",
                    object.getClass().getName(), indexObject.toString()), e);
        }

        //throw new TemplateException(object.getClass().getName() + "??");
    }

    /**
     * ?
     * @param path
     * @param locale
     * @return
     */
    public static String getLocalePath(String path, Locale locale) {
        if (locale != null) {
            int pos = path.lastIndexOf(".");
            String localePath = path.substring(0, pos) + "_" + locale.getLanguage() + "_" + locale.getCountry()
                    + path.substring(pos);
            return localePath;
        }
        return path;
    }

    /**
     * 
     * @param str        ??
     * @param stripChars ?<code>null</code>
     * @return
     */
    public static String trimStart(String str, String[] stripChars) {
        if (stripChars == null || stripChars.length == 0)
            return str;

        int strLen;
        if (str != null && (strLen = str.length()) != 0) {
            int start = 0;
            while (start < strLen && isStripChar(str.charAt(start), stripChars)) {
                ++start;
            }

            return str.substring(start);
        }
        return str;
    }

    /**
     * 
     * @param str        ??
     * @param stripChars ?<code>null</code>
     * @return
     */
    public static String trimEnd(String str, String[] stripChars) {
        int end;
        if (str != null && (end = str.length()) != 0) {
            while (end != 0 && isStripChar(str.charAt(end - 1), stripChars)) {
                --end;
            }

            return str.substring(0, end);
        }
        return str;
    }

    /**
     * ??
     * @param charStr    ?
     * @param stripChars ?
     * @return
     */
    private static boolean isStripChar(char charStr, String[] stripChars) {
        for (int i = 0; i < stripChars.length; i++) {
            if (stripChars[i].indexOf(charStr) != -1)
                return true;
        }
        return false;
    }

}