2 * Copyright © 2014, 2017 Red Hat, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.ovsdb.lib.schema.typed;
10 import static java.util.Objects.requireNonNull;
12 import com.google.common.collect.ImmutableMap;
13 import java.lang.reflect.InvocationHandler;
14 import java.lang.reflect.Method;
15 import java.util.Objects;
16 import org.eclipse.jdt.annotation.NonNull;
17 import org.eclipse.jdt.annotation.Nullable;
18 import org.opendaylight.ovsdb.lib.error.UnsupportedMethodException;
19 import org.opendaylight.ovsdb.lib.notation.Row;
20 import org.opendaylight.ovsdb.lib.schema.GenericTableSchema;
21 import org.opendaylight.ovsdb.lib.schema.typed.MethodDispatch.Invoker;
24 * Theory of operation: we have a set of Invoker, which are indexed by method and point to implementations we should
25 * be invoking. This mapping is data-invariant, end hence we allow rebiding to a different row (which may not be null).
27 final class TypedRowInvocationHandler implements InvocationHandler {
29 private final @NonNull ImmutableMap<Method, Invoker> invokers;
30 private final @NonNull String tableName;
31 private final @Nullable Row<GenericTableSchema> row;
33 private TypedRowInvocationHandler(final @NonNull String tableName,
34 @NonNull final ImmutableMap<Method, Invoker> invokers, final Row<GenericTableSchema> row) {
35 this.tableName = requireNonNull(tableName);
36 this.invokers = requireNonNull(invokers);
40 TypedRowInvocationHandler(final @NonNull String tableName, @NonNull final ImmutableMap<Method, Invoker> invokers) {
41 this(tableName, invokers, null);
44 TypedRowInvocationHandler bindToRow(final @Nullable Row<GenericTableSchema> newRow) {
45 return row == newRow ? this : new TypedRowInvocationHandler(tableName, invokers, newRow);
48 String getTableName() {
53 public Object invoke(final Object proxy, final Method method, final Object[] args) {
54 final Invoker invoker = invokers.get(method);
55 return invoker != null ? invoker.invokeMethod(row, proxy, args) : invokeObjectMethod(proxy, method, args);
58 // Split out to aid inlining
59 private Object invokeObjectMethod(final Object proxy, final Method method, final Object[] args) {
60 switch (method.getName()) {
62 if (args == null || args.length == 0) {
63 return row == null ? 0 : row.hashCode();
67 if (args != null && args.length == 1 && method.getParameterTypes()[0] == Object.class) {
68 // We only run equality or our proxy and only when it is proxying a TypedBaseTable
69 final Object obj = args[0];
70 return proxy == obj || proxy.getClass().isInstance(obj) && obj instanceof TypedBaseTable
71 && Objects.equals(row, ((TypedBaseTable<?>)obj).getRow());
75 if (args == null || args.length == 0) {
76 return row == null ? tableName : tableName + " : " + row.toString();
83 throw new UnsupportedMethodException("Method not supported " + method.toString());