121547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin/*
221547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin * Copyright (C) 2014 The Android Open Source Project
321547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin *
421547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin * Licensed under the Apache License, Version 2.0 (the "License");
521547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin * you may not use this file except in compliance with the License.
621547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin * You may obtain a copy of the License at
721547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin *
821547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin *      http://www.apache.org/licenses/LICENSE-2.0
921547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin *
1021547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin * Unless required by applicable law or agreed to in writing, software
1121547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin * distributed under the License is distributed on an "AS IS" BASIS,
1221547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1321547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin * See the License for the specific language governing permissions and
1421547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin * limitations under the License.
1521547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin */
1621547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkinpackage android.hardware.camera2.dispatch;
1721547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin
1821547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkinimport java.lang.reflect.Method;
1921547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin
2021547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkinimport static com.android.internal.util.Preconditions.*;
2121547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin
2221547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin/**
2321547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin * A dispatcher that replaces one argument with another; replaces any argument at an index
2421547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin * with another argument.
2521547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin *
2621547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin * <p>For example, we can override an {@code void onSomething(int x)} calls to have {@code x} always
2721547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin * equal to 1. Or, if using this with a duck typing dispatcher, we could even overwrite {@code x} to
2821547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin * be something
2921547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin * that's not an {@code int}.</p>
3021547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin *
3121547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin * @param <T>
3221547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin *          source dispatch type, whose methods with {@link #dispatch} will be called
3321547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin * @param 
3421547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin *          argument replacement type, args in {@link #dispatch} matching {@code argumentIndex}
3521547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin *          will be overriden to objects of this type
3621547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin */
3721547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkinpublic class ArgumentReplacingDispatcher<T, TArg> implements Dispatchable<T> {
3821547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin
3921547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin    private final Dispatchable<T> mTarget;
4021547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin    private final int mArgumentIndex;
4121547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin    private final TArg mReplaceWith;
4221547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin
4321547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin    /**
4421547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin     * Create a new argument replacing dispatcher; dispatches are forwarded to {@code target}
4521547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin     * after the argument is replaced.
4621547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin     *
4721547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin     * <p>For example, if a method {@code onAction(T1 a, Integer b, T2 c)} is invoked, and we wanted
4821547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin     * to replace all occurrences of {@code b} with {@code 0xDEADBEEF}, we would set
4921547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin     * {@code argumentIndex = 1} and {@code replaceWith = 0xDEADBEEF}.</p>
5021547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin     *
5121547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin     * <p>If a method dispatched has less arguments than {@code argumentIndex}, it is
5221547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin     * passed through with the arguments unchanged.</p>
5321547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin     *
5421547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin     * @param target destination dispatch type, methods will be redirected to this dispatcher
5521547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin     * @param argumentIndex the numeric index of the argument {@code >= 0}
5621547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin     * @param replaceWith arguments matching {@code argumentIndex} will be replaced with this object
5721547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin     */
5821547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin    public ArgumentReplacingDispatcher(Dispatchable<T> target, int argumentIndex,
5921547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin            TArg replaceWith) {
6021547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin        mTarget = checkNotNull(target, "target must not be null");
6121547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin        mArgumentIndex = checkArgumentNonnegative(argumentIndex,
6221547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin                "argumentIndex must not be negative");
6321547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin        mReplaceWith = checkNotNull(replaceWith, "replaceWith must not be null");
6421547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin    }
6521547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin
6621547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin    @Override
6721547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin    public Object dispatch(Method method, Object[] args) throws Throwable {
6821547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin
6921547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin        if (args.length > mArgumentIndex) {
7021547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin            args = arrayCopy(args); // don't change in-place since it can affect upstream dispatches
7121547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin            args[mArgumentIndex] = mReplaceWith;
7221547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin        }
7321547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin
7421547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin        return mTarget.dispatch(method, args);
7521547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin    }
7621547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin
7721547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin    private static Object[] arrayCopy(Object[] array) {
7821547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin        int length = array.length;
7921547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin        Object[] newArray = new Object[length];
8021547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin        for (int i = 0; i < length; ++i) {
8121547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin            newArray[i] = array[i];
8221547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin        }
8321547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin        return newArray;
8421547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin    }
8521547d66a9ce591ff30a3ad4102f7f30a4764d80Igor Murashkin}
86