package org.apache.velocity.tools.generic;

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * 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.    
 */

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map;

import org.apache.velocity.tools.ClassUtils;
import org.apache.velocity.tools.Scope;
import org.apache.velocity.tools.config.DefaultKey;
import org.apache.velocity.tools.config.ValidScope;

/**
 * <p>
 * This is a simple tools class to allow easy access to static fields in a class,
 * such as string constants from within a template.  Velocity will not introspect
 * for class fields (and won't in the future :), but writing setter/getter methods
 * to do this is a pain,  so use this if you really have to access fields.</p>
 *
 * <p>Example uses in a template:</p>
 * <pre>
 *   ## here we access a constant in a class include in the configuration
 *     $field.COUNTER_NAME
 *
 *   ## here we dynamically lookup a class' fields to find another constant
 *     $field.in("org.com.SomeClass").ANOTHER_CONSTANT
 *
 *   ## here we pass an object instance in (an Integer in this case) and
 *   ## retrieve a static constant from that instance's class
 *     $field.in(0).MIN_VALUE
 *
 *   ## by default, once we've searched a class' fields, those fields stay
 *   ## available in the tool (change this by storeDynamicLookups="false")
 *   ## so here we get another constant from the Integer class
 *     $field.MAX_VALUE
 * </pre>
 * <p>Example tools.xml config:</p>
 * <pre>
 * &lt;tools&gt;
 *   &lt;toolbox scope="application"&gt;
 *     &lt;tool class="org.apache.velocity.tools.generic.FieldTool"
 *              include="org.apache.velocity.runtime.RuntimeConstants,com.org.MyConstants"/&gt;
 *   &lt;/toolbox&gt;
 * &lt;/tools&gt;
 * </pre>
 *
 * <p>
 * Right now, this tool only gives access to <code>public static</code> fields.
 * It seems that anything else is too dangerous.  This is for convenient access
 * to 'constants'.  If you have fields that aren't <code>static</code>,
 * handle them by explicitly placing them into the context or writing a getter
 * method.
 *
 * @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a>
 * @author Nathan Bubna
 * @since VelocityTools 2.0
 * @version $Id: FieldTool.java 463298 2006-10-12 16:10:32Z henning $
 */

@DefaultKey("field")
@ValidScope(Scope.APPLICATION)
public class FieldTool extends SafeConfig
{
    /**
     * The key used for specifying which classes should be inspected
     * for public static methods to be made available.
     */
    public static final String INCLUDE_KEY = "include";

    /**
     * The key used for specifying whether or not the tool should store
     * fields in classes dynamically looked up from within a template.
     * The default value is true.
     */
    public static final String STORE_DYNAMIC_KEY = "storeDynamicLookups";

    protected HashMap storage = new HashMap();
    protected boolean storeDynamicLookups = true;

    protected void configure(ValueParser values)
    {
        // retrieve any classnames to be inspected and inspect them
        // *before* setting the storeDynamicLookups property!
        String[] classnames = values.getStrings(INCLUDE_KEY);
        if (classnames != null)
        {
            for (String classname : classnames)
            {
                // make sure we get results for each classname
                // since these come from the configuration, it's
                // an error if they're invalid
                if (in(classname) == null)
                {
                    // shame that ClassNotFoundException is checked...
                    throw new RuntimeException("Could not find "+classname+" in the classpath");
                }
            }
        }

        // find out whether or not we should store dynamic lookups
        this.storeDynamicLookups =
            values.getBoolean(STORE_DYNAMIC_KEY, this.storeDynamicLookups);
    }


    /**
     * Returns the value for the specified field name as found
     * in the stored {@link Map} of field names to values (or placeholders).
     * Returns {@code null} if there is no matching field.
     * @param name field name
     * @return field value
     */
    public Object get(String name)
    {
        Object o = storage.get(name);
        // if it was not a final field, get the current value
        if (o instanceof MutableField)
        {
            return ((MutableField)o).getValue();
        }
        // if we have no value and the name looks like a path
        else if (o == null && name.indexOf('.') > 0)
        {
            // treat the name as a full fieldpath
            try
            {
                return ClassUtils.getFieldValue(name);
            }
            catch (Exception e)
            {
                getLog().debug("Unable to retrieve value of field at {}", name, e);
            }
        }
        // otherwise, we should have stored the value directly
        return o;
    }

    /**
     * Returns a {@link FieldToolSub} holding a {@link Map}
     * of all the public static field names to values (or a placeholder
     * if the value is not final) for the specified class(name). If the
     * {@link Class} with the specified name cannot be loaded, this will
     * return {@code null}, rather than throw an exception.
     *
     * @param classname target class name
     * @return {@link FieldToolSub} object
     * @see #in(Class clazz)
     */
    public FieldToolSub in(String classname)
    {
        try
        {
            return in(ClassUtils.getClass(classname));
        }
        catch (ClassNotFoundException cnfe)
        {
            return null;
        }
    }

    /**
     * Returns a {@link FieldToolSub} holding a {@link Map}
     * of all the public static field names to values (or a placeholder
     * if the value is not final) for the {@link Class} of the
     * specified Object.
     * @param instance target instance
     * @return {@link FieldToolSub} object
     * @see #in(Class clazz)
     */
    public FieldToolSub in(Object instance)
    {
        if (instance == null)
        {
            return null;
        }
        return in(instance.getClass());
    }

    /**
     * Returns a {@link FieldToolSub} holding a {@link Map}
     * of all the public static field names to values (or a placeholder
     * if the value is not final) for the specified {@link Class}.
     * @param clazz target class
     * @return {@link FieldToolSub} object
     */
    public FieldToolSub in(Class clazz)
    {
        if (clazz == null)
        {
            return null;
        }

        Map<String,Object> results = inspect(clazz);
        if (storeDynamicLookups && !results.isEmpty())
        {
            storage.putAll(results);
        }
        return new FieldToolSub(results);
    }


    /**
     * Looks for all public, static fields in the specified class and
     * stores their value (if final) or else a {@link MutableField} for
     * in a {@link Map} under the fields' names.  This will never return
     * null, only an empty Map if there are no public static fields.
     * @param clazz target class
     * @return fields map
     */
    protected Map<String,Object> inspect(Class clazz)
    {
        Map<String,Object> results = new HashMap<String,Object>();
        for(Field field : clazz.getFields())
        {
            // ignore anything non-public or non-static
            int mod = field.getModifiers();
            if (Modifier.isStatic(mod) && Modifier.isPublic(mod))
            {
                // make it easy to debug key collisions
                if (getLog().isDebugEnabled() && results.containsKey(field.getName()))
                {
                    getLog().debug("{} is being overridden by {}", field.getName(), clazz.getName());
                }
                // if the field is final
                if (Modifier.isFinal(mod))
                {
                    // just get the value now
                    results.put(field.getName(), retrieve(field, clazz));
                }
                else
                {
                    // put a wrapper with easy access
                    results.put(field.getName(),
                                new MutableField(field, clazz));
                }
            }
        }
        return results;
    }

    /**
     * Retrieves and returns the value of the specified {@link Field}
     * in the specified {@link Class}. Returns {@code null} in case of failure.
     * 
     * @param field target field
     * @param clazz target class
     * @return field value
     */
    protected Object retrieve(Field field, Class clazz)
    {
        try
        {
            return field.get(clazz);
        }
        catch(IllegalAccessException iae)
        {
            getLog().warn("IllegalAccessException while trying to access {}", field.getName(), iae);
            return null;
        }
    }



    /**
     * Holds a {@link Map} of results for a particular class.
     * This exists simply to enable the $field.in("class.Name").FOO
     * syntax, even when storeDynamicLookups is set to false.
     * NOTE: we can't simply return the results Map when the in()
     * methods are called, because the Map contains placeholders
     * for any mutable fields found. We want to put off reading non-final
     * field values to the last moment, in case their values change.
     */
    public static class FieldToolSub
    {
        private final Map<String,Object> results;

        public FieldToolSub(Map<String,Object> results)
        {
            if (results == null)
            {
                throw new NullPointerException("Cannot create sub with null field results map");
            }
            this.results = results;
        }

        public Object get(String name)
        {
            Object o = results.get(name);
            // if it was not a final field, get the current value
            if (o instanceof MutableField)
            {
                return ((MutableField)o).getValue();
            }
            // otherwise, we should have stored the value directly
            return o;
        }

        /**
         * Return the toString() value of the internal results Map for this sub.
         */
        public String toString()
        {
            return results.toString();
        }
    }



    /**
     * Holds a {@link Field} and {@link Class} reference for later
     * retrieval of the value of a field that is not final and may
     * change at different lookups.
     */
    public class MutableField
    {
        private final Class clazz;
        private final Field field;

        public MutableField(Field f, Class c)
        {
            if (f == null || c == null)
            {
                throw new NullPointerException("Both Class and Field must NOT be null");
            }

            field = f;
            clazz = c;
        }

        public Object getValue()
        {
            return retrieve(field, clazz);
        }
    }

}
