Optimize CodecDataObject dispatch
[mdsal.git] / binding / mdsal-binding-dom-codec / src / main / java / org / opendaylight / mdsal / binding / dom / codec / impl / DataObjectCodecContext.java
index 69b326d749ea35a740cbe6c6982e775b3f54f7e9..3ac825690dcaebeae17ead4053296cb9baf14b1a 100644 (file)
@@ -21,7 +21,6 @@ import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodType;
 import java.lang.reflect.Method;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Comparator;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -88,13 +87,14 @@ abstract class DataObjectCodecContext<D extends DataObject, T extends DataNodeCo
     private static final CtClass SUPERCLASS = StaticClassPool.findClass(CodecDataObject.class);
     private static final CtClass AUGMENTABLE_SUPERCLASS = StaticClassPool.findClass(
         AugmentableCodecDataObject.class);
+    private static final NodeContextSupplier[] EMPTY_METHODS = new NodeContextSupplier[0];
 
     private final ImmutableMap<String, ValueNodeCodecContext> leafChild;
     private final ImmutableMap<YangInstanceIdentifier.PathArgument, NodeContextSupplier> byYang;
-    private final ImmutableMap<String, NodeContextSupplier> byMethod;
     private final ImmutableMap<Class<?>, DataContainerCodecPrototype<?>> byStreamClass;
     private final ImmutableMap<Class<?>, DataContainerCodecPrototype<?>> byBindingArgClass;
     private final ImmutableMap<AugmentationIdentifier, Type> possibleAugmentations;
+    private final NodeContextSupplier[] byMethod;
     private final MethodHandle proxyConstructor;
 
     @SuppressWarnings("rawtypes")
@@ -105,7 +105,11 @@ abstract class DataObjectCodecContext<D extends DataObject, T extends DataNodeCo
 
     private volatile ImmutableMap<Class<?>, DataContainerCodecPrototype<?>> mismatchedAugmented = ImmutableMap.of();
 
-    DataObjectCodecContext(final DataContainerCodecPrototype<T> prototype, final Method... additionalMethods) {
+    DataObjectCodecContext(final DataContainerCodecPrototype<T> prototype) {
+        this(prototype, null);
+    }
+
+    DataObjectCodecContext(final DataContainerCodecPrototype<T> prototype, final @Nullable Method keyMethod) {
         super(prototype);
 
         final Class<D> bindingClass = getBindingClass();
@@ -146,21 +150,19 @@ abstract class DataObjectCodecContext<D extends DataObject, T extends DataNodeCo
             }
         }
 
-        final int methodCount = tmpMethodToSupplier.size();
-        final Builder<String, NodeContextSupplier> byMethodBuilder = ImmutableMap.builderWithExpectedSize(methodCount);
-
-
-        final List<Method> properties = new ArrayList<>(methodCount);
-        for (Entry<Method, NodeContextSupplier> entry : tmpMethodToSupplier.entrySet()) {
-            final Method method = entry.getKey();
-            properties.add(method);
-            byMethodBuilder.put(method.getName(), entry.getValue());
-        }
-
         // Make sure properties are alpha-sorted
+        final List<Method> properties = new ArrayList<>(tmpMethodToSupplier.keySet());
         properties.sort(METHOD_BY_ALPHABET);
+        if (!properties.isEmpty()) {
+            byMethod = new NodeContextSupplier[properties.size()];
+            int offset = 0;
+            for (Method prop : properties) {
+                byMethod[offset++] = verifyNotNull(tmpMethodToSupplier.get(prop));
+            }
+        } else {
+            byMethod = EMPTY_METHODS;
+        }
 
-        this.byMethod = byMethodBuilder.build();
         this.byYang = ImmutableMap.copyOf(byYangBuilder);
         this.byStreamClass = ImmutableMap.copyOf(byStreamClassBuilder);
         byBindingArgClassBuilder.putAll(byStreamClass);
@@ -176,19 +178,10 @@ abstract class DataObjectCodecContext<D extends DataObject, T extends DataNodeCo
         }
         reloadAllAugmentations();
 
-        final List<Method> methods;
-        if (additionalMethods.length != 0) {
-            methods = new ArrayList<>(properties.size() + 1);
-            methods.addAll(properties);
-            methods.addAll(Arrays.asList(additionalMethods));
-        } else {
-            methods = properties;
-        }
-
         final Class<?> generatedClass;
         try {
             generatedClass = prototype.getFactory().getLoader().generateSubclass(superClass, bindingClass, "codecImpl",
-                new CodecDataObjectCustomizer(properties, methods));
+                new CodecDataObjectCustomizer(properties, keyMethod));
         } catch (CannotCompileException | IOException | NotFoundException e) {
             throw new LinkageError("Failed to generated class for " + bindingClass, e);
         }
@@ -524,9 +517,8 @@ abstract class DataObjectCodecContext<D extends DataObject, T extends DataNodeCo
     }
 
     @SuppressWarnings("rawtypes")
-    @Nullable Object getBindingChildValue(final String method, final NormalizedNodeContainer domData) {
-        final NodeCodecContext childContext = verifyNotNull(byMethod.get(method),
-            "Cannot find data handler for method %s", method).get();
+    @Nullable Object getBindingChildValue(final NormalizedNodeContainer domData, final int offset) {
+        final NodeCodecContext childContext = byMethod[offset].get();
 
         @SuppressWarnings("unchecked")
         final Optional<NormalizedNode<?, ?>> domChild = domData.getChild(childContext.getDomPathArgument());