Coverage Report - org.apache.commons.ognl.ListPropertyAccessor
 
Classes in this File Line Coverage Branch Coverage Complexity
ListPropertyAccessor
75%
72/95
62%
61/98
14.333
 
 1  
 package org.apache.commons.ognl;
 2  
 
 3  
 /*
 4  
  * Licensed to the Apache Software Foundation (ASF) under one
 5  
  * or more contributor license agreements.  See the NOTICE file
 6  
  * distributed with this work for additional information
 7  
  * regarding copyright ownership.  The ASF licenses this file
 8  
  * to you under the Apache License, Version 2.0 (the
 9  
  * "License"); you may not use this file except in compliance
 10  
  * with the License.  You may obtain a copy of the License at
 11  
  *
 12  
  *   http://www.apache.org/licenses/LICENSE-2.0
 13  
  *
 14  
  * Unless required by applicable law or agreed to in writing,
 15  
  * software distributed under the License is distributed on an
 16  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 17  
  * KIND, either express or implied.  See the License for the
 18  
  * specific language governing permissions and limitations
 19  
  * under the License.
 20  
  */
 21  
 
 22  
 import java.util.*;
 23  
 
 24  
 /**
 25  
  * Implementation of PropertyAccessor that uses numbers and dynamic subscripts as properties to index into Lists.
 26  
  *
 27  
  * @author Luke Blanshard (blanshlu@netscape.net)
 28  
  * @author Drew Davidson (drew@ognl.org)
 29  
  */
 30  4
 public class ListPropertyAccessor
 31  
     extends ObjectPropertyAccessor
 32  
     implements PropertyAccessor
 33  
 {
 34  
 
 35  
     @Override
 36  
     public Object getProperty( Map<String, Object> context, Object target, Object name )
 37  
         throws OgnlException
 38  
     {
 39  77
         List<?> list = (List<?>) target;
 40  
 
 41  77
         if ( name instanceof String )
 42  
         {
 43  
             Object result;
 44  
 
 45  29
             if ( "size".equals( name ) )
 46  
             {
 47  8
                 result = list.size();
 48  
             }
 49  
             else
 50  
             {
 51  21
                 if ( "iterator".equals( name ) )
 52  
                 {
 53  6
                     result = list.iterator();
 54  
                 }
 55  
                 else
 56  
                 {
 57  15
                     if ( "isEmpty".equals( name ) || "empty".equals( name ) )
 58  
                     {
 59  4
                         result = list.isEmpty() ? Boolean.TRUE : Boolean.FALSE;
 60  
                     }
 61  
                     else
 62  
                     {
 63  11
                         result = super.getProperty( context, target, name );
 64  
                     }
 65  
                 }
 66  
             }
 67  
 
 68  29
             return result;
 69  
         }
 70  
 
 71  48
         if ( name instanceof Number )
 72  
         {
 73  38
             return list.get( ( (Number) name ).intValue() );
 74  
         }
 75  
 
 76  10
         if ( name instanceof DynamicSubscript )
 77  
         {
 78  10
             int len = list.size();
 79  10
             switch ( ( (DynamicSubscript) name ).getFlag() )
 80  
             {
 81  
                 case DynamicSubscript.FIRST:
 82  3
                     return len > 0 ? list.get( 0 ) : null;
 83  
                 case DynamicSubscript.MID:
 84  4
                     return len > 0 ? list.get( len / 2 ) : null;
 85  
                 case DynamicSubscript.LAST:
 86  3
                     return len > 0 ? list.get( len - 1 ) : null;
 87  
                 case DynamicSubscript.ALL:
 88  0
                     return new ArrayList<Object>( list );
 89  
                 default:
 90  
                     break;
 91  
             }
 92  
         }
 93  
 
 94  0
         throw new NoSuchPropertyException( target, name );
 95  
     }
 96  
 
 97  
     @Override
 98  
     public void setProperty( Map<String, Object> context, Object target, Object name, Object value )
 99  
         throws OgnlException
 100  
     {
 101  4
         if ( name instanceof String && !( (String) name ).contains( "$" ) )
 102  
         {
 103  0
             super.setProperty( context, target, name, value );
 104  0
             return;
 105  
         }
 106  
 
 107  
         @SuppressWarnings( "unchecked" ) // check performed by the invoker
 108  4
             List<Object> list = (List<Object>) target;
 109  
 
 110  4
         if ( name instanceof Number )
 111  
         {
 112  1
             list.set( ( (Number) name ).intValue(), value );
 113  1
             return;
 114  
         }
 115  
 
 116  3
         if ( name instanceof DynamicSubscript )
 117  
         {
 118  3
             int len = list.size();
 119  3
             switch ( ( (DynamicSubscript) name ).getFlag() )
 120  
             {
 121  
                 case DynamicSubscript.FIRST:
 122  1
                     if ( len > 0 )
 123  
                     {
 124  1
                         list.set( 0, value );
 125  
                     }
 126  1
                     return;
 127  
                 case DynamicSubscript.MID:
 128  1
                     if ( len > 0 )
 129  
                     {
 130  1
                         list.set( len / 2, value );
 131  
                     }
 132  1
                     return;
 133  
                 case DynamicSubscript.LAST:
 134  1
                     if ( len > 0 )
 135  
                     {
 136  1
                         list.set( len - 1, value );
 137  
                     }
 138  1
                     return;
 139  
                 case DynamicSubscript.ALL:
 140  0
                     if ( !( value instanceof Collection ) )
 141  
                     {
 142  0
                         throw new OgnlException( "Value must be a collection" );
 143  
                     }
 144  0
                     list.clear();
 145  0
                     list.addAll( (Collection<?>) value );
 146  0
                     return;
 147  
                 default:
 148  0
                     return;
 149  
             }
 150  
         }
 151  
 
 152  0
         throw new NoSuchPropertyException( target, name );
 153  
     }
 154  
 
 155  
     @Override
 156  
     public Class<?> getPropertyClass( OgnlContext context, Object target, Object index )
 157  
     {
 158  0
         if ( index instanceof String )
 159  
         {
 160  0
             String key = ( (String) index ).replaceAll( "\"", "" );
 161  0
             if ( "size".equals( key ) )
 162  
             {
 163  0
                 return int.class;
 164  
             }
 165  0
             if ( "iterator".equals( key ) )
 166  
             {
 167  0
                 return Iterator.class;
 168  
             }
 169  0
             if ( "isEmpty".equals( key ) || "empty".equals( key ) )
 170  
             {
 171  0
                 return boolean.class;
 172  
             }
 173  0
             return super.getPropertyClass( context, target, index );
 174  
         }
 175  
 
 176  0
         if ( index instanceof Number )
 177  
         {
 178  0
             return Object.class;
 179  
         }
 180  
 
 181  0
         return null;
 182  
     }
 183  
 
 184  
     @Override
 185  
     public String getSourceAccessor( OgnlContext context, Object target, Object index )
 186  
     {
 187  37
         String indexStr = index.toString().replaceAll( "\"", "" );
 188  
 
 189  37
         if ( String.class.isInstance( index ) )
 190  
         {
 191  37
             if ( "size".equals( indexStr ) )
 192  
             {
 193  4
                 context.setCurrentAccessor( List.class );
 194  4
                 context.setCurrentType( int.class );
 195  4
                 return ".size()";
 196  
             }
 197  33
             if ( "iterator".equals( indexStr ) )
 198  
             {
 199  4
                 context.setCurrentAccessor( List.class );
 200  4
                 context.setCurrentType( Iterator.class );
 201  4
                 return ".iterator()";
 202  
             }
 203  29
             if ( "isEmpty".equals( indexStr ) || "empty".equals( indexStr ) )
 204  
             {
 205  2
                 context.setCurrentAccessor( List.class );
 206  2
                 context.setCurrentType( boolean.class );
 207  2
                 return ".isEmpty()";
 208  
             }
 209  
         }
 210  
 
 211  
         // TODO: This feels really inefficient, must be some better way
 212  
         // check if the index string represents a method on a custom class implementing java.util.List instead..
 213  27
         return getSourceBeanMethod( context, target, index, indexStr, false );
 214  
     }
 215  
 
 216  
     @Override
 217  
     public String getSourceSetter( OgnlContext context, Object target, Object index )
 218  
     {
 219  18
         String indexStr = index.toString().replaceAll( "\"", "" );
 220  
 
 221  
         // TODO: This feels really inefficient, must be some better way
 222  
         // check if the index string represents a method on a custom class implementing java.util.List instead..
 223  
         /*
 224  
          * System.out.println("Listpropertyaccessor setter using index: " + index + " and current object: " +
 225  
          * context.getCurrentObject() + " number is current object? " +
 226  
          * Number.class.isInstance(context.getCurrentObject()));
 227  
          */
 228  
 
 229  18
         return getSourceBeanMethod( context, target, index, indexStr, true );
 230  
     }
 231  
 
 232  
     private String getSourceBeanMethod( OgnlContext context, Object target, Object index, String indexStr,
 233  
                                         boolean isSetter )
 234  
     {
 235  45
         Object currentObject = context.getCurrentObject();
 236  45
         Class<?> currentType = context.getCurrentType();
 237  45
         if ( currentObject != null && !Number.class.isInstance( currentObject ) )
 238  
         {
 239  
             try
 240  
             {
 241  10
                 if ( isSetter )
 242  
                 {
 243  6
                     if ( OgnlRuntime.getWriteMethod( target.getClass(), indexStr ) != null
 244  
                         || !currentType.isPrimitive() )
 245  
                     {
 246  6
                         return super.getSourceSetter( context, target, index );
 247  
                     }
 248  
                 }
 249  
                 else
 250  
                 {
 251  4
                     if ( OgnlRuntime.getReadMethod( target.getClass(), indexStr ) != null )
 252  
                     {
 253  2
                         return super.getSourceAccessor( context, target, index );
 254  
                     }
 255  
                 }
 256  
             }
 257  6
             catch ( Throwable t )
 258  
             {
 259  6
                 throw OgnlOps.castToRuntime( t );
 260  2
             }
 261  
         }
 262  
 
 263  
         /*
 264  
          * if (String.class.isInstance(index)) { context.setCurrentAccessor(List.class); return ""; }
 265  
          */
 266  
 
 267  37
         context.setCurrentAccessor( List.class );
 268  
 
 269  
         // need to convert to primitive for list index access
 270  
 
 271  37
         if ( !currentType.isPrimitive() && Number.class.isAssignableFrom( currentType ) )
 272  
         {
 273  3
             indexStr += "." + OgnlRuntime.getNumericValueGetter( currentType );
 274  
         }
 275  34
         else if ( currentObject != null && Number.class.isAssignableFrom( currentObject.getClass() )
 276  
             && !currentType.isPrimitive() )
 277  
         {
 278  
             // means it needs to be cast first as well
 279  
 
 280  1
             String toString = String.class.isInstance( index ) && currentType != Object.class ? "" : ".toString()";
 281  
 
 282  1
             indexStr = "org.apache.commons.ognl.OgnlOps#getIntValue(" + indexStr + toString + ")";
 283  
         }
 284  
 
 285  37
         context.setCurrentType( Object.class );
 286  
 
 287  37
         return isSetter ? ".set(" + indexStr + ", $3)" : ".get(" + indexStr + ")";
 288  
     }
 289  
 
 290  
 }