View Javadoc

    1   /*
    2    * Copyright 2002,2004 The Apache Software Foundation.
    3    *
    4    * Licensed under the Apache License, Version 2.0 (the "License");
    5    * you may not use this file except in compliance with the License.
    6    * You may obtain a copy of the License at
    7    *
    8    *      http://www.apache.org/licenses/LICENSE-2.0
    9    *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16
    17  package org.apache.commons.jexl.parser;
    18
    19  import org.apache.commons.jexl.JexlContext;
    20  import org.apache.commons.jexl.util.Coercion;
    21  import org.apache.commons.jexl.util.Introspector;
    22  import org.apache.commons.jexl.util.introspection.Info;
    23  import org.apache.commons.jexl.util.introspection.VelPropertyGet;
    24
    25  import java.util.List;
    26  import java.util.Map;
    27  import java.lang.reflect.Array;
    28
    29
    30  /***
    31   *  Like an ASTIdentifier, but with array access allowed
    32   *
    33   *    $foo[2]
    34   *
    35   *  @author <a href="mailto:geirm@apache.org">Geir Magnusson Jr.</a>
    36   *  @version $Id: ASTArrayAccess.java,v 1.7 2004/08/22 07:42:35 dion Exp $
    37   */
    38  public class ASTArrayAccess extends SimpleNode
    39  {
    40      /*** dummy velocity info */
    41      private static Info DUMMY = new Info("", 1, 1);
    42
    43      public ASTArrayAccess(int id)
    44      {
    45          super(id);
    46      }
    47
    48      public ASTArrayAccess(Parser p, int id)
    49      {
    50          super(p, id);
    51      }
    52
    53
    54      /*** Accept the visitor. **/
    55      public Object jjtAccept(ParserVisitor visitor, Object data)
    56      {
    57          return visitor.visit(this, data);
    58      }
    59
    60      /*
    61       * evaluate array access upon a base object
    62       *
    63       *   foo.bar[2]
    64       *
    65       *  makes me rethink the array operator :)
    66       */
    67      public Object execute(Object obj, JexlContext jc)
    68               throws Exception
    69       {
    70           ASTIdentifier base = (ASTIdentifier) jjtGetChild(0);
    71
    72           obj = base.execute(obj,jc);
    73
    74           /*
    75            * ignore the first child - it's our identifier
    76            */
    77           for(int i=1; i<jjtGetNumChildren(); i++)
    78           {
    79               Object loc = ((SimpleNode) jjtGetChild(i)).value(jc);
    80
    81               if(loc==null)
    82                   return null;
    83
    84               obj = evaluateExpr(obj, loc);
    85           }
    86
    87           return obj;
    88       }
    89
    90      /***
    91       *  return the value of this node
    92       */
    93      public Object value(JexlContext jc)
    94          throws Exception
    95      {
    96          /*
    97           * get the base ASTIdentifier
    98           */
    99
    100         ASTIdentifier base = (ASTIdentifier) jjtGetChild(0);
    101
    102         Object o = base.value(jc);
    103
    104         /*
    105          * ignore the first child - it's our identifier
    106          */
    107         for(int i=1; i<jjtGetNumChildren(); i++)
    108         {
    109             Object loc = ((SimpleNode) jjtGetChild(i)).value(jc);
    110
    111             if(loc==null)
    112                 return null;
    113
    114             o = evaluateExpr(o, loc);
    115         }
    116
    117         return o;
    118     }
    119
    120     public static Object evaluateExpr(Object o, Object loc)
    121         throws Exception
    122     {
    123         /*
    124          * following the JSTL EL rules
    125          */
    126
    127         if (o == null)
    128             return null;
    129
    130         if (loc == null)
    131             return null;
    132
    133         if (o instanceof Map)
    134         {
    135             if (!((Map)o).containsKey(loc))
    136                 return null;
    137
    138             return ((Map)o).get(loc);
    139         }
    140         else if (o instanceof List)
    141         {
    142             int idx = Coercion.coerceInteger(loc).intValue();
    143
    144             try
    145             {
    146                 return ((List)o).get(idx);
    147             }
    148             catch(IndexOutOfBoundsException iobe)
    149             {
    150                 return null;
    151             }
    152         }
    153         else if (o.getClass().isArray())
    154         {
    155             int idx = Coercion.coerceInteger(loc).intValue();
    156
    157             try
    158             {
    159                 return Array.get(o, idx);
    160             }
    161             catch(ArrayIndexOutOfBoundsException aiobe)
    162             {
    163                 return null;
    164             }
    165         }
    166         else
    167         {
    168             /*
    169              *  "Otherwise (a JavaBean object)..."  huh? :)
    170              */
    171
    172             String s = loc.toString();
    173
    174             VelPropertyGet vg = Introspector.getUberspect().getPropertyGet(o, s, DUMMY);
    175
    176             if (vg != null)
    177             {
    178                 return vg.invoke(o);
    179             }
    180         }
    181
    182         throw new Exception("Unsupported object type for array [] accessor");
    183     }
    184
    185     public String getIdentifierString()
    186     {
    187         return ((ASTIdentifier) jjtGetChild(0)).getIdentifierString();
    188     }
    189 }