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 * @param3421547d66a9ce591ff30a3ad4102f7f30a4764d80Igor 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