All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.samskivert.mustache.DefaultCollector Maven / Gradle / Ivy

There is a newer version: 1.16
Show newest version
//
// JMustache - A Java implementation of the Mustache templating language
// http://github.com/samskivert/jmustache/blob/master/LICENSE

package com.samskivert.mustache;

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

import java.util.AbstractList;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * The default collector used by JMustache.
 */
public class DefaultCollector extends BasicCollector
{
    @Override
    public Mustache.VariableFetcher createFetcher (Object ctx, String name) {
        Mustache.VariableFetcher fetcher = super.createFetcher(ctx, name);
        if (fetcher != null) return fetcher;

        // first check for a getter which provides the value
        Class cclass = ctx.getClass();
        final Method m = getMethod(cclass, name);
        if (m != null) {
            return new Mustache.VariableFetcher() {
                public Object get (Object ctx, String name) throws Exception {
                    return m.invoke(ctx);
                }
            };
        }

        // next check for a getter which provides the value
        final Field f = getField(cclass, name);
        if (f != null) {
            return new Mustache.VariableFetcher() {
                public Object get (Object ctx, String name) throws Exception {
                    return f.get(ctx);
                }
            };
        }

        // finally check for a default interface method which provides the value (this is left to
        // last because it's much more expensive and hopefully something already matched above)
        final Method im = getIfaceMethod(cclass, name);
        if (im != null) {
            return new Mustache.VariableFetcher() {
                public Object get (Object ctx, String name) throws Exception {
                    return im.invoke(ctx);
                }
            };
        }

        return null;
    }

    @Override
    public  Map createFetcherCache () {
        return new ConcurrentHashMap();
    }

    protected Method getMethod (Class clazz, String name) {
        // first check up the superclass chain
        for (Class cc = clazz; cc != null && cc != Object.class; cc = cc.getSuperclass()) {
            Method m = getMethodOn(cc, name);
            if (m != null) return m;
        }
        return null;
    }

    protected Method getIfaceMethod (Class clazz, String name) {
        // enumerate the transitive closure of all interfaces implemented by clazz
        Set> ifaces = new LinkedHashSet>();
        for (Class cc = clazz; cc != null && cc != Object.class; cc = cc.getSuperclass()) {
            addIfaces(ifaces, cc, false);
        }
        // now search those in the order that we found them
        for  (Class iface : ifaces) {
            Method m = getMethodOn(iface, name);
            if (m != null) return m;
        }
        return null;
    }

    private void addIfaces (Set> ifaces, Class clazz, boolean isIface) {
        if (isIface) ifaces.add(clazz);
        for (Class iface : clazz.getInterfaces()) addIfaces(ifaces, iface, true);
    }

    protected Method getMethodOn (Class clazz, String name) {
        Method m;
        try {
            m = clazz.getDeclaredMethod(name);
            if (!m.getReturnType().equals(void.class)) return makeAccessible(m);
        } catch (Exception e) {
            // fall through
        }

        String upperName = Character.toUpperCase(name.charAt(0)) + name.substring(1);
        try {
            m = clazz.getDeclaredMethod("get" + upperName);
            if (!m.getReturnType().equals(void.class)) return makeAccessible(m);
        } catch (Exception e) {
            // fall through
        }

        try {
            m = clazz.getDeclaredMethod("is" + upperName);
            if (m.getReturnType().equals(boolean.class) ||
                m.getReturnType().equals(Boolean.class)) return makeAccessible(m);
        } catch (Exception e) {
            // fall through
        }

        return null;
    }

    private Method makeAccessible (Method m) {
        if (!m.isAccessible()) m.setAccessible(true);
        return m;
    }

    protected Field getField (Class clazz, String name) {
        Field f;
        try {
            f = clazz.getDeclaredField(name);
            if (!f.isAccessible()) {
                f.setAccessible(true);
            }
            return f;
        } catch (Exception e) {
            // fall through
        }

        Class sclass = clazz.getSuperclass();
        if (sclass != Object.class && sclass != null) {
            return getField(clazz.getSuperclass(), name);
        }
        return null;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy