Package org.eclipse.jst.jsf.validation.internal.el.operators

Source Code of org.eclipse.jst.jsf.validation.internal.el.operators.BracketOperator

/*******************************************************************************
* Copyright (c) 2001, 2007 Oracle Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*     Oracle Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jst.jsf.validation.internal.el.operators;

import org.eclipse.core.resources.IFile;
import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jst.jsf.common.internal.types.LiteralType;
import org.eclipse.jst.jsf.common.internal.types.SignatureBasedType;
import org.eclipse.jst.jsf.common.internal.types.TypeCoercer;
import org.eclipse.jst.jsf.common.internal.types.TypeCoercionException;
import org.eclipse.jst.jsf.common.internal.types.TypeConstants;
import org.eclipse.jst.jsf.common.internal.types.TypeTransformer;
import org.eclipse.jst.jsf.common.internal.types.ValueType;
import org.eclipse.jst.jsf.context.symbol.IObjectSymbol;
import org.eclipse.jst.jsf.context.symbol.ISymbol;
import org.eclipse.jst.jsf.context.symbol.internal.util.IObjectSymbolBasedValueType;
import org.eclipse.jst.jsf.designtime.DesignTimeApplicationManager;
import org.eclipse.jst.jsf.designtime.el.AbstractDTPropertyResolver;
import org.eclipse.jst.jsf.designtime.resolver.ISymbolContextResolver;
import org.eclipse.jst.jsf.validation.internal.el.diagnostics.DiagnosticFactory;

/**
* Handles the operator 'bracket' where bracket(expr-a, id-b) == 'expr-a[id-b]' in EL syntax
*
* @author cbateman
*
*/
public class BracketOperator extends MemberAccessorOperator
{
    private static final String OPERATOR_NAME_ARRAY_ACCESSOR = "array ('[]') accessor"; //$NON-NLS-1$

    /**
     * @param diagnosticFactory
     * @param file
     * @param resolver
     */
    public BracketOperator(final DiagnosticFactory diagnosticFactory, final IFile file, final ISymbolContextResolver resolver)
    {
        super(file, diagnosticFactory, resolver);
    }

  protected SignatureBasedType handlePerformObjectSymbolValue(
      IObjectSymbolBasedValueType firstArg, ValueType secondArg)
  {
        // per JSP.2.3.4 step 5.2, if value-a is a list or array access
        if (firstArg.isInstanceOf(TypeConstants.TYPE_LIST)
                || Signature.getArrayCount(firstArg.getSignature()) > 0)
        {
            return handlePerformNumericPropertyAccessorBase(firstArg, secondArg);
        }

        // per JSP.2.3.4 step 5, if value-a is a map or if it is not
        // a list or array (and therefore a bean), treat it as named property accessed object
        // if firstArg is a map then we must treat the access like a map.get(secondArg)

        // if we don't have a literal value with which to derive value-b, then
        // we can't get a property
        if (secondArg instanceof LiteralType)
        {
          return handlePerformNamedPropertyAccessorBase(firstArg, (LiteralType)secondArg);
        }

        return null;
  }
 
  protected Diagnostic validateObjectSymbolValue(IObjectSymbolBasedValueType firstArg,
      ValueType secondArg)
  {
        // per JSP.2.3.4 step 5.2, if value-a is a list or array access
        if (firstArg.isInstanceOf(TypeConstants.TYPE_LIST)
                || firstArg.getSymbol().getTypeDescriptor().isArray())
        {
            return validateNumericPropertyAccessorBase(firstArg, secondArg);
        }

        // per JSP.2.3.4 step 5, if value-a is a map or if it is not
        // a list or array (and therefore a bean), treat it as named property accessed object
        // if firstArg is a map then we must treat the access like a map.get(secondArg)
    if (secondArg instanceof LiteralType)
    {
      return validateNamedPropertyAccessorBase(firstArg, (LiteralType) secondArg);
    }
        // otherwise, there's nothing we can guarantee
        return Diagnostic.OK_INSTANCE;
  }
 
  private Diagnostic validateNumericPropertyAccessorBase(IObjectSymbolBasedValueType firstArg,
                              ValueType secondArg)
  {
        try
        {
          // secondArg must successfully coerce to integer
          TypeCoercer.coerceToNumber(TypeTransformer.transformBoxPrimitives(secondArg.getSignature()));
         
          if (secondArg instanceof LiteralType)
          {
                // this will throw a TypeCoercionExceptino if it won't
                // coerce
                Integer integerValue =
                    (Integer) ((LiteralType)secondArg).coerceToNumber(Integer.class);

            if (integerValue.intValue() < 0)
                {
                return _diagnosticFactory.create_POSSIBLE_ARRAY_INDEX_OUT_OF_BOUNDS(integerValue);
                }
          }
            else
            {
                // if the argument is a non-literal string, we can't verify
                // that the coercion to integer won't throw an exception
                // at runtime
                if (TypeCoercer.typeIsString(secondArg.getSignature()))
                {
                    return _diagnosticFactory.create_UNARY_OP_STRING_CONVERSION_NOT_GUARANTEED(OPERATOR_NAME_ARRAY_ACCESSOR);
                }
            }
           
            // TODO: attempt to detect ArrayIndexOutOfBoundsException
            return Diagnostic.OK_INSTANCE;
        }
        catch (TypeCoercionException e)
        {
          return _diagnosticFactory.create_BINARY_OP_COULD_NOT_MAKE_NUMERIC_COERCION(OPERATOR_NAME_ARRAY_ACCESSOR);
        }
  }
   
    private SignatureBasedType handlePerformNumericPropertyAccessorBase(IObjectSymbolBasedValueType firstArg,
                                                            ValueType secondArg)
    {
        AbstractDTPropertyResolver propResolver = getPropertyResolver();
        int index = 0;
        if (secondArg instanceof LiteralType)
        {
            try {
                index = ((LiteralType)secondArg).coerceToNumber(Integer.class).intValue();
            } catch (TypeCoercionException e) {
                // suppress, just use index = 0
                // this maybe should be an assertion...
            }
        }
       
        final ISymbol symbol =
            propResolver.getProperty(firstArg.getSymbol(), index);
       
        if (symbol instanceof IObjectSymbol)
        {
            return IObjectSymbolBasedValueType.getInstance(symbol);
        }
       
        // if can't be resolved, return null
        return null;
    }

    @Override
    protected String getOperatorName()
    {
        return Messages.getString("BracketOperator.Name"); //$NON-NLS-1$
    }

    /**
     * @return the property resolver for the current source file
     */
    private AbstractDTPropertyResolver getPropertyResolver()
    {
        final DesignTimeApplicationManager manager =
            DesignTimeApplicationManager.getInstance(_file.getProject());

        if (manager != null)
        {
            return manager.getPropertyResolver();
        }

        return null;
    }
}
TOP

Related Classes of org.eclipse.jst.jsf.validation.internal.el.operators.BracketOperator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.