    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    package org.apache.commons.jexl2.internal;
    018
    019    import java.lang.reflect.InvocationTargetException;
    020
    021    /**
    022     * Specialized executor to set a property of an object.
    023     * <p>Duck as in duck-typing for an interface like:
    024     * <code>
    025     * interface Set {
    026     *      Object set(Object property, Object value);
    027     * }
    028     * </code>
    029     * </p>
    030     * @since 2.0
    031     */
    032    public final class DuckSetExecutor extends AbstractExecutor.Set {
    033        /** The property. */
    034        private final Object property;
    035
    036        /**
    037         * Creates an instance.
    038         *@param is the introspector
    039         *@param clazz the class to find the set method from
    040         *@param key the key to use as 1st argument to the set method
    041         *@param value the value to use as 2nd argument to the set method
    042         */
    043        public DuckSetExecutor(Introspector is, Class<?> clazz, Object key, Object value) {
    044            super(clazz, discover(is, clazz, key, value));
    045            property = key;
    046        }
    047
    048        /** {@inheritDoc} */
    049        @Override
    050        public Object getTargetProperty() {
    051            return property;
    052        }
    053
    054        /** {@inheritDoc} */
    055        @Override
    056        public Object execute(Object obj, Object value)
    057                throws IllegalAccessException, InvocationTargetException {
    058            Object[] pargs = {property, value};
    059            if (method != null) {
    060                method.invoke(obj, pargs);
    061            }
    062            return value;
    063        }
    064
    065        /** {@inheritDoc} */
    066        @Override
    067        public Object tryExecute(Object obj, Object key, Object value) {
    068            if (obj != null && method !=  null
    069                // ensure method name matches the property name
    070                && property.equals(key)
    071                && objectClass.equals(obj.getClass())) {
    072                try {
    073                    Object[] args = {property, value};
    074                    method.invoke(obj, args);
    075                    return value;
    076                } catch (InvocationTargetException xinvoke) {
    077                    return TRY_FAILED; // fail
    078                } catch (IllegalAccessException xill) {
    079                    return TRY_FAILED;// fail
    080                }
    081            }
    082            return TRY_FAILED;
    083        }
    084
    085        /**
    086         * Discovers the method for a {@link DuckSet}.
    087         *@param is the introspector
    088         *@param clazz the class to find the set method from
    089         *@param key the key to use as 1st argument to the set method
    090         *@param value the value to use as 2nd argument to the set method
    091         *@return the method if found, null otherwise
    092         */
    093        private static java.lang.reflect.Method discover(Introspector is,
    094                Class<?> clazz, Object key, Object value) {
    095            return is.getMethod(clazz, "set", makeArgs(key, value));
    096        }
    097    }