001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    
018    package org.apache.commons.jexl2.internal;
019    import java.util.List;
020    import java.lang.reflect.Array;
021    /**
022     * Specialized executor to get a property from a List or array.
023     * @since 2.0
024     */
025    public final class ListGetExecutor extends AbstractExecutor.Get {
026        /** The java.lang.reflect.Array.get method used as an active marker in ListGet. */
027        private static final java.lang.reflect.Method ARRAY_GET =
028                initMarker(Array.class, "get", Object.class, Integer.TYPE);
029        /** The java.util.obj.get method used as an active marker in ListGet. */
030        private static final java.lang.reflect.Method LIST_GET =
031                initMarker(List.class, "get", Integer.TYPE);
032        /** The property. */
033        private final Integer property;
034    
035        /**
036         * Creates an instance checking for the List interface or Array capability.
037         * @param is the introspector
038         * @param clazz the class to introspect
039         * @param key the key to use in obj.get(key)
040         */
041        public ListGetExecutor(Introspector is, Class<?> clazz, Integer key) {
042            super(clazz, discover(clazz));
043            property = key;
044        }
045    
046        /** {@inheritDoc} */
047        @Override
048        public Object getTargetProperty() {
049            return property;
050        }
051        
052        /**
053         * Get the property from the obj or array.
054         * @param obj the List/array.
055         * @return obj.get(key)
056         */
057        @Override
058        public Object execute(final Object obj) {
059            if (method == ARRAY_GET) {
060                return java.lang.reflect.Array.get(obj, property.intValue());
061            } else {
062                return ((List<?>) obj).get(property.intValue());
063            }
064        }
065    
066        /** {@inheritDoc} */
067        @Override
068        public Object tryExecute(final Object obj, Object key) {
069            if (obj != null && method != null
070                && objectClass.equals(obj.getClass())
071                && key instanceof Integer) {
072                if (method == ARRAY_GET) {
073                    return java.lang.reflect.Array.get(obj, ((Integer) key).intValue());
074                } else {
075                    return ((List<?>) obj).get(((Integer) key).intValue());
076                }
077            }
078            return TRY_FAILED;
079        }
080    
081    
082        /**
083         * Finds the method to perform the get on a obj of array.
084         * @param clazz the class to introspect
085         * @return a marker method, obj.get or array.get
086         */
087        static java.lang.reflect.Method discover(Class<?> clazz) {
088            //return discoverList(false, clazz, property);
089            if (clazz.isArray()) {
090                return ARRAY_GET;
091            }
092            if (List.class.isAssignableFrom(clazz)) {
093                return LIST_GET;
094            }
095            return null;
096        }
097    }