//  Copyright 2004 The Apache Software Foundation
//
// Licensed 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.

package org.apache.tapestry.binding;

import java.util.Map;

import ognl.Ognl;
import ognl.OgnlException;
import ognl.TypeConverter;

import org.apache.tapestry.BindingException;
import org.apache.tapestry.IComponent;
import org.apache.tapestry.ILocation;
import org.apache.tapestry.IResourceResolver;
import org.apache.tapestry.Tapestry;
import org.apache.tapestry.spec.BeanLifecycle;
import org.apache.tapestry.spec.IBeanSpecification;
import org.apache.tapestry.spec.IApplicationSpecification;
import org.apache.tapestry.util.StringSplitter;
import org.apache.tapestry.util.prop.OgnlUtils;

/**
 *  Implements a dynamic binding, based on getting and fetching
 *  values using JavaBeans property access.  This is built
 *  upon the <a href="http://www.ognl.org">OGNL</a> library.
 *
 *  <p><b>Optimization of the Expression</b>
 * 
 *  <p>There's a lot of room for optimization here because we can
 *  count on some portions of the expression to be
 *  effectively static.  Note that we type the root object as
 *  {@link IComponent}.  We have some expectations that
 *  certain properties of the root (and properties reachable from the root)
 *  will be constant for the lifetime of the binding.  For example, 
 *  components never change thier page or container.  This means
 *  that certain property prefixes can be optimized:
 *
 *  <ul>
 *  <li>page
 *  <li>container
 *  <li>components.<i>name</i>
 *  </ul>
 *
 *  <p>This means that once an ExpressionBinding has been triggered, 
 *  the {@link #toString()} method may return different values for the root
 *  component and the expression than was originally set.
 * 
 *  <p><b>Identifying Invariants</b>
 * 
 *  <p>Most expressions are fully dynamic; they must be
 *  resolved each time they are accessed.  This can be somewhat inefficient.
 *  Tapestry can identify certain paths as invariant:
 * 
 *  <ul>
 *  <li>A component within the page hierarchy 
 *  <li>An {@link org.apache.tapestry.IAsset} from then assets map (property <code>assets</code>)
 *  <li>A {@link org.apache.tapestry.IActionListener}
 *  from the listener map (property <code>listeners</code>)
 *  <li>A bean with a {@link org.apache.tapestry.spec.BeanLifecycle#PAGE}
 *  lifecycle (property <code>beans</code>)
 *  <li>A binding (property <code>bindings</code>)
 *  </ul>
 * 
 *  <p>
 *  These optimizations have some inherent dangers; they assume that
 *  the components have not overidden the specified properties;
 *  the last one (concerning helper beans) assumes that the
 *  component does inherit from {@link org.apache.tapestry.AbstractComponent}.
 *  If this becomes a problem in the future, it may be necessary to
 *  have the component itself involved in these determinations.
 *  
 *  @author Howard Lewis Ship
 *  @version $Id$
 *  @since 2.2
 * 
 **/

public class ExpressionBinding extends AbstractBinding
{
    /**
     *  The root object against which the nested property name is evaluated.
     *
     **/

    private IComponent _root;

    /**
     *  The OGNL expression, as a string.
     *
     **/

    private String _expression;

    /**
     *  If true, then the binding is invariant, and cachedValue
     *  is the ultimate value.
     * 
     **/

    private boolean _invariant = false;

    /**
     *  Stores the cached value for the binding, if invariant
     *  is true.
     * 
     **/

    private Object _cachedValue;

    /**
     *   Parsed OGNL expression.
     * 
     **/

    private Object _parsedExpression;

    /**
     *  Flag set once the binding has initialized.
     *  _cachedValue, _invariant and _final value
     *  for _expression
     *  are not valid until after initialization.
     * 
     * 
     **/

    private boolean _initialized;

    private IResourceResolver _resolver;

    /**
     *  The OGNL context for this binding.  It is retained
     *  for the lifespan of the binding once created.
     * 
     **/

    private Map _context;

    /**
     *  Creates a {@link ExpressionBinding} from the root object
     *  and an OGNL expression.
     * 
     **/

    public ExpressionBinding(
        IResourceResolver resolver,
        IComponent root,
        String expression,
        ILocation location)
    {
        super(location);

        _resolver = resolver;
        _root = root;
        _expression = expression;
    }

    public String getExpression()
    {
        return _expression;
    }

    public IComponent getRoot()
    {
        return _root;
    }

    /**
     *  Gets the value of the property path, with the assistance of a 
     *  OGNL.
     *
     *  @throws BindingException if an exception is thrown accessing the property.
     *
     **/

    public Object getObject()
    {
        initialize();

        if (_invariant)
            return _cachedValue;

        return resolveProperty();
    }

    private Object resolveProperty()
    {
        try
        {
            return Ognl.getValue(_parsedExpression, getOgnlContext(), _root);
        }
        catch (OgnlException t)
        {
            throw new BindingException(
                Tapestry.format(
                    "ExpressionBinding.unable-to-resolve-expression",
                    _expression,
                    _root),
                this,
                t);
        }
    }

    /**
     *  Creates an OGNL context used to get or set a value.
     *  We may extend this in the future to set additional
     *  context variables (such as page, request cycle and engine).
     *  An optional type converter will be added to the OGNL context
     *  if it is specified as an application extension with the name
     *  {@link Tapestry#OGNL_TYPE_CONVERTER}.
     * 
     **/

    private Map getOgnlContext()
    {
        if (_context == null)
            _context = Ognl.createDefaultContext(_root, _resolver);

        if (_root.getPage() != null)
        {
            if (_root.getPage().getEngine() != null)
            {
                IApplicationSpecification appSpec = _root.getPage().getEngine().getSpecification();

                if (appSpec != null && appSpec.checkExtension(Tapestry.OGNL_TYPE_CONVERTER))
                {
                    TypeConverter typeConverter =
                        (TypeConverter) appSpec.getExtension(
                            Tapestry.OGNL_TYPE_CONVERTER,
                            TypeConverter.class);

                    Ognl.setTypeConverter(_context, typeConverter);
                }
            }
        }

        return _context;
    }

    /**
     *  Returns true if the binding is expected to always 
     *  return the same value.
     * 
     * 
     **/

    public boolean isInvariant()
    {
        initialize();

        return _invariant;
    }

    public void setBoolean(boolean value)
    {
        setObject(value ? Boolean.TRUE : Boolean.FALSE);
    }

    public void setInt(int value)
    {
        setObject(new Integer(value));
    }

    public void setDouble(double value)
    {
        setObject(new Double(value));
    }

    public void setString(String value)
    {
        setObject(value);
    }

    /**
     *  Sets up the helper object, but also optimizes the property path
     *  and determines if the binding is invarant.
     *
     **/

    private void initialize()
    {
        if (_initialized)
            return;

        _initialized = true;

        try
        {
            _parsedExpression = OgnlUtils.getParsedExpression(_expression);
        }
        catch (Exception ex)
        {
            throw new BindingException(ex.getMessage(), this, ex);
        }

        if (checkForConstant())
            return;

        try
        {
            if (!Ognl.isSimpleNavigationChain(_parsedExpression, getOgnlContext()))
                return;
        }
        catch (OgnlException ex)
        {
            throw new BindingException(ex.getMessage(), this, ex);
        }

        // Split the expression into individual property names.
        // We then optimize what we can from the expression.  This will
        // shorten the expression and, in some cases, eliminate
        // it.  We also check to see if the binding can be an invariant.

        String[] split = new StringSplitter('.').splitToArray(_expression);

        int count = optimizeRootObject(split);

        // We'ver removed some or all of the initial elements of split
        // but have to account for anthing left over.

        if (count == split.length)
        {
            // The property path was something like "page" or "component.foo"
            // and was completely eliminated.

            _expression = null;
            _parsedExpression = null;

            _invariant = true;
            _cachedValue = _root;

            return;
        }

        _expression = reassemble(count, split);
        _parsedExpression = OgnlUtils.getParsedExpression(_expression);

        checkForInvariant(count, split);
    }

    /**
     *  Looks for common prefixes on the expression (provided pre-split) that
     *  are recognized as references to other components.
     * 
     *  @return the number of leading elements of the split expression that
     *  have been removed.
     * 
     **/

    private int optimizeRootObject(String[] split)
    {
        int i;

        for (i = 0; i < split.length; i++)
        {

            if (split[i].equals("page"))
            {
                _root = _root.getPage();
                continue;
            }

            if (split[i].equals("container"))
            {
                _root = _root.getContainer();
                continue;
            }

            // Here's the tricky one ... if its of the form
            // "components.foo" we can get the named component
            // directly.

            if (split[i].equals("components") && i + 1 < split.length)
            {
                _root = _root.getComponent(split[i + 1]);
                i++;
                continue;
            }

            // Not a recognized prefix, break the loop

            break;
        }

        return i;
    }

    private boolean checkForConstant()
    {
        try
        {
            if (Ognl.isConstant(_parsedExpression, getOgnlContext()))
            {
                _invariant = true;

                _cachedValue = resolveProperty();

                return true;
            }
        }
        catch (OgnlException ex)
        {
            throw new BindingException(
                Tapestry.format(
                    "ExpressionBinding.unable-to-resolve-expression",
                    _expression,
                    _root),
                this,
                ex);
        }

        return false;
    }

    /**
     *  Reassembles the remainder of the split property path
     *  from the start point.
     * 
     **/

    private String reassemble(int start, String[] split)
    {
        int count = split.length - start;

        if (count == 0)
            return null;

        if (count == 1)
            return split[split.length - 1];

        StringBuffer buffer = new StringBuffer();

        for (int i = start; i < split.length; i++)
        {
            if (i > start)
                buffer.append('.');

            buffer.append(split[i]);
        }

        return buffer.toString();
    }

    /**
     *  Checks to see if the binding can be converted to an invariant.
     * 
     **/

    private void checkForInvariant(int start, String[] split)
    {
        // For now, all of our conditions are two properties
        // from a root component.

        if (split.length - start != 2)
            return;

        try
        {
            if (!Ognl.isSimpleNavigationChain(_parsedExpression, getOgnlContext()))
                return;
        }
        catch (OgnlException ex)
        {
            throw new BindingException(
                Tapestry.format(
                    "ExpressionBinding.unable-to-resolve-expression",
                    _expression,
                    _root),
                this,
                ex);
        }

        String first = split[start];

        if (first.equals("listeners"))
        {
            _invariant = true;

            // Could cast to AbstractComponent, get listenersMap, etc.,
            // but this is easier.

            _cachedValue = resolveProperty();
            return;
        }

        if (first.equals("assets"))
        {
            String name = split[start + 1];

            _invariant = true;
            _cachedValue = _root.getAsset(name);
            return;
        }

        if (first.equals("beans"))
        {
            String name = split[start + 1];

            IBeanSpecification bs = _root.getSpecification().getBeanSpecification(name);

            if (bs == null || bs.getLifecycle() != BeanLifecycle.PAGE)
                return;

            // Again, could cast to AbstractComponent, but this
            // is easier.

            _invariant = true;
            _cachedValue = resolveProperty();
            return;
        }

        if (first.equals("bindings"))
        {
            String name = split[start + 1];

            _invariant = true;
            _cachedValue = _root.getBinding(name);
            return;
        }

        // Not a recognized pattern for conversion
        // to invariant.
    }

    /**
     *  Updates the property for the binding to the given value.  
     *
     *  @throws BindingException if the property can't be updated (typically
     *  due to an security problem, or a missing mutator method).
     *  @throws BindingException if the binding is invariant.
     **/

    public void setObject(Object value)
    {
        initialize();

        if (_invariant)
            throw createReadOnlyBindingException(this);

        try
        {
            Ognl.setValue(_parsedExpression, getOgnlContext(), _root, value);
        }
        catch (OgnlException ex)
        {
            throw new BindingException(
                Tapestry.format(
                    "ExpressionBinding.unable-to-update-expression",
                    _expression,
                    _root,
                    value),
                this,
                ex);
        }
    }

    /**
     *  Returns the a String representing the property path.  This includes
     *  the {@link IComponent#getExtendedId() extended id} of the root component
     *  and the property path ... once the binding is used, these may change
     *  due to optimization of the property path.
     *
     **/

    public String toString()
    {
        StringBuffer buffer = new StringBuffer();

        buffer.append("ExpressionBinding[");
        buffer.append(_root.getExtendedId());

        if (_expression != null)
        {
            buffer.append(' ');
            buffer.append(_expression);
        }

        if (_invariant)
        {
            buffer.append(" cachedValue=");
            buffer.append(_cachedValue);
        }

        buffer.append(']');

        return buffer.toString();
    }

}