Eliminate AugmentationHolder 24/91824/4
authorRobert Varga <robert.varga@pantheon.tech>
Mon, 3 Aug 2020 12:02:14 +0000 (14:02 +0200)
committerRobert Varga <nite@hq.sk>
Mon, 3 Aug 2020 17:55:08 +0000 (17:55 +0000)
This makes interacting with Augmentables a lot simpler at the expense
of not supporting weird Reflection-based tricks like 'we will load
the interpretation behind your back'.

JIRA: MDSAL-577
Change-Id: Ib97ed323cf8fbec55a06188691610a31a1267bea
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
15 files changed:
binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/AugmentableCodecDataObject.java
binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/BuilderTemplate.xtend
binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/InterfaceTemplate.xtend
binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/JavaFileTemplate.java
binding/mdsal-binding-java-api-generator/src/test/java/org/opendaylight/mdsal/binding/java/api/generator/BuilderGeneratorTest.java
binding/mdsal-binding-spec-util/src/main/java/org/opendaylight/mdsal/binding/spec/reflect/AugmentationFieldGetter.java [deleted file]
binding/mdsal-binding-spec-util/src/main/java/org/opendaylight/mdsal/binding/spec/reflect/BindingReflections.java
binding/mdsal-binding-spec-util/src/test/java/org/opendaylight/mdsal/binding/spec/reflect/AugmentationFieldGetterTest.java [deleted file]
binding/mdsal-binding-test-utils/src/main/java/org/opendaylight/mdsal/binding/testutils/AugmentableExtension.java [deleted file]
binding/mdsal-binding-test-utils/src/main/java/org/opendaylight/mdsal/binding/testutils/XtendYangBeanGenerator.java
binding/mdsal-binding-test-utils/src/test/java/org/opendaylight/mdsal/binding/testutils/AugmentableExtensionTest.java [deleted file]
binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/AbstractAugmentable.java
binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/Augmentable.java
binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/AugmentationHolder.java [deleted file]
binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/CodeHelpers.java

index 5f352490135f1726dd139b9fa92c4ad64961584e..91c64cfc8b012972e985aee13df47d018dbbcdf6 100644 (file)
@@ -16,7 +16,6 @@ import java.util.Optional;
 import org.eclipse.jdt.annotation.Nullable;
 import org.opendaylight.yangtools.yang.binding.Augmentable;
 import org.opendaylight.yangtools.yang.binding.Augmentation;
-import org.opendaylight.yangtools.yang.binding.AugmentationHolder;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
@@ -29,7 +28,7 @@ import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
  * @param <T> DataObject type
  */
 public abstract class AugmentableCodecDataObject<T extends DataObject & Augmentable<T>>
-        extends CodecDataObject<T> implements Augmentable<T>, AugmentationHolder<T> {
+        extends CodecDataObject<T> implements Augmentable<T> {
     private static final VarHandle CACHED_AUGMENTATIONS;
 
     static {
index 450de7ccfa33b923926d7704e43dd6b2b4f44a9a..0ab6e58344e67b03e206750c0936e0ccdafddab5 100644 (file)
@@ -499,17 +499,13 @@ class BuilderTemplate extends AbstractBuilderTemplate {
     '''
 
     override protected generateCopyAugmentation(Type implType) {
-        val augmentationHolderRef = AUGMENTATION_HOLDER.importedName
-        val typeRef = targetType.importedName
         val hashMapRef = JU_HASHMAP.importedName
         val augmentTypeRef = augmentType.importedName
         return '''
-            if (base instanceof «augmentationHolderRef») {
-                @SuppressWarnings("unchecked")
-                «JU_MAP.importedName»<«CLASS.importedName»<? extends «augmentTypeRef»>, «augmentTypeRef»> aug =((«augmentationHolderRef»<«typeRef»>) base).augmentations();
-                if (!aug.isEmpty()) {
-                    this.«AUGMENTATION_FIELD» = new «hashMapRef»<>(aug);
-                }
+            @SuppressWarnings("unchecked")
+            «JU_MAP.importedName»<«CLASS.importedName»<? extends «augmentTypeRef»>, «augmentTypeRef»> aug = base.augmentations();
+            if (!aug.isEmpty()) {
+                this.«AUGMENTATION_FIELD» = new «hashMapRef»<>(aug);
             }
         '''
     }
index 2ead021a95d9a7dde5a758eec068ac1d841ffb7b..7780cbd510f5a290d4dba1ef9863bd0061ba111e 100644 (file)
@@ -230,26 +230,18 @@ class InterfaceTemplate extends BaseTemplate {
              * Implementations of this interface are encouraged to defer to this method to get consistent hashing
              * results across all implementations.
              *
-             «IF augmentable»
-             * @param <T$$> implementation type, which has to also implement «AUGMENTATION_HOLDER.importedName» interface
-             *              contract.
-             «ENDIF»
              * @param obj Object for which to generate hashCode() result.
              * @return Hash code value of data modeled by this interface.
              * @throws «NPE.importedName» if {@code obj} is null
              */
-            «IF augmentable»
-                static <T$$ extends «type.fullyQualifiedName» & «AUGMENTATION_HOLDER.importedName»<?>> int «BINDING_HASHCODE_NAME»(final @«NONNULL.importedName» T$$ obj) {
-            «ELSE»
-                static int «BINDING_HASHCODE_NAME»(final «type.fullyQualifiedNonNull» obj) {
-            «ENDIF»
+            static int «BINDING_HASHCODE_NAME»(final «type.fullyQualifiedNonNull» obj) {
                 final int prime = 31;
                 int result = 1;
                 «FOR property : typeAnalysis.value»
                     result = prime * result + «property.importedUtilClass».hashCode(obj.«property.getterMethodName»());
                 «ENDFOR»
                 «IF augmentable»
-                    result = prime * result + «CODEHELPERS.importedName».hashAugmentations(obj);
+                    result = prime * result + obj.augmentations().hashCode();
                 «ENDIF»
                 return result;
             }
@@ -264,20 +256,12 @@ class InterfaceTemplate extends BaseTemplate {
              * Implementations of this interface are encouraged to defer to this method to get consistent equality
              * results across all implementations.
              *
-             «IF augmentable»
-             * @param <T$$> implementation type, which has to also implement «AUGMENTATION_HOLDER.importedName» interface
-             *              contract.
-             «ENDIF»
              * @param thisObj Object acting as the receiver of equals invocation
              * @param obj Object acting as argument to equals invocation
              * @return True if thisObj and obj are considered equal
              * @throws «NPE.importedName» if {@code thisObj} is null
              */
-            «IF augmentable»
-            static <T$$ extends «type.fullyQualifiedName» & «AUGMENTATION_HOLDER.importedName»<«type.fullyQualifiedName»>> boolean «BINDING_EQUALS_NAME»(final @«NONNULL.importedName» T$$ thisObj, final «Types.objectType().importedName» obj) {
-            «ELSE»
             static boolean «BINDING_EQUALS_NAME»(final «type.fullyQualifiedNonNull» thisObj, final «Types.objectType().importedName» obj) {
-            «ENDIF»
                 if (thisObj == obj) {
                     return true;
                 }
@@ -290,7 +274,7 @@ class InterfaceTemplate extends BaseTemplate {
                         return false;
                     }
                 «ENDFOR»
-                return «IF augmentable»«CODEHELPERS.importedName».equalsAugmentations(thisObj, other)«ELSE»true«ENDIF»;
+                return «IF augmentable»thisObj.augmentations().equals(other.augmentations())«ELSE»true«ENDIF»;
             }
         «ENDIF»
     '''
@@ -302,19 +286,11 @@ class InterfaceTemplate extends BaseTemplate {
          * Implementations of this interface are encouraged to defer to this method to get consistent string
          * representations across all implementations.
          *
-         «IF augmentable»
-         * @param <T$$> implementation type, which has to also implement «AUGMENTATION_HOLDER.importedName» interface
-         *              contract.
-         «ENDIF»
          * @param obj Object for which to generate toString() result.
          * @return {@link «STRING.importedName»} value of data modeled by this interface.
          * @throws «NPE.importedName» if {@code obj} is null
          */
-        «IF augmentable»
-        static <T$$ extends «type.fullyQualifiedName» & «AUGMENTATION_HOLDER.importedName»<«type.fullyQualifiedName»>> «STRING.importedName» «BINDING_TO_STRING_NAME»(final @«NONNULL.importedName» T$$ obj) {
-        «ELSE»
         static «STRING.importedName» «BINDING_TO_STRING_NAME»(final «type.fullyQualifiedNonNull» obj) {
-        «ENDIF»
             final «MoreObjects.importedName».ToStringHelper helper = «MoreObjects.importedName».toStringHelper("«type.name»");
             «FOR property : typeAnalysis.value»
                 «CODEHELPERS.importedName».appendValue(helper, "«property.name»", obj.«property.getterName»());
index b8b3ecf23c68474688f702a664a0af1aae4d7da4..cec30795866d613d06c439294d4d44a609d42d0e 100644 (file)
@@ -43,7 +43,6 @@ import org.opendaylight.mdsal.binding.model.api.Type;
 import org.opendaylight.mdsal.binding.model.util.Types;
 import org.opendaylight.mdsal.binding.spec.naming.BindingMapping;
 import org.opendaylight.yangtools.yang.binding.Augmentable;
-import org.opendaylight.yangtools.yang.binding.AugmentationHolder;
 import org.opendaylight.yangtools.yang.binding.CodeHelpers;
 
 
@@ -110,10 +109,6 @@ class JavaFileTemplate {
      * {@code org.opendaylight.yangtools.yang.binding.CodeHelpers} as a JavaTypeName.
      */
     static final @NonNull JavaTypeName CODEHELPERS = JavaTypeName.create(CodeHelpers.class);
-    /**
-     * {@code org.opendaylight.yangtools.yang.binding.AugmentationHolder} as a JavaTypeName.
-     */
-    static final @NonNull JavaTypeName AUGMENTATION_HOLDER = JavaTypeName.create(AugmentationHolder.class);
 
     private static final Comparator<MethodSignature> METHOD_COMPARATOR = new AlphabeticallyTypeMemberComparator<>();
     private static final Type AUGMENTATION_RET_TYPE;
index 79cbe70982680c2fac3110fc5033a422e9fb962d..e64c018e99a781e7737119fa374016d2b4ad6983 100644 (file)
@@ -90,17 +90,14 @@ public class BuilderGeneratorTest {
                 + " hashing\n"
                 + " * results across all implementations.\n"
                 + " *\n"
-                + " * @param <T$$> implementation type, which has to also implement AugmentationHolder interface\n"
-                + " *              contract.\n"
                 + " * @param obj Object for which to generate hashCode() result.\n"
                 + " * @return Hash code value of data modeled by this interface.\n"
                 + " * @throws NullPointerException if {@code obj} is null\n"
                 + " */\n"
-                + "static <T$$ extends test.test & AugmentationHolder<?>> int bindingHashCode(final @NonNull T$$ obj) {"
-                + "\n"
+                + "static int bindingHashCode(final test.@NonNull test obj) {\n"
                 + "    final int prime = 31;\n"
                 + "    int result = 1;\n"
-                + "    result = prime * result + CodeHelpers.hashAugmentations(obj);\n"
+                + "    result = prime * result + obj.augmentations().hashCode();\n"
                 + "    return result;\n"
                 + "}\n", genHashCode(mockAugment(mockGenType(TEST))).toString());
     }
@@ -113,18 +110,15 @@ public class BuilderGeneratorTest {
                 + " hashing\n"
                 + " * results across all implementations.\n"
                 + " *\n"
-                + " * @param <T$$> implementation type, which has to also implement AugmentationHolder interface\n"
-                + " *              contract.\n"
                 + " * @param obj Object for which to generate hashCode() result.\n"
                 + " * @return Hash code value of data modeled by this interface.\n"
                 + " * @throws NullPointerException if {@code obj} is null\n"
                 + " */\n"
-                + "static <T$$ extends test.test & AugmentationHolder<?>> int bindingHashCode(final @NonNull T$$ obj) {"
-                + "\n"
+                + "static int bindingHashCode(final test.@NonNull test obj) {\n"
                 + "    final int prime = 31;\n"
                 + "    int result = 1;\n"
                 + "    result = prime * result + Objects.hashCode(obj.getTest());\n"
-                + "    result = prime * result + CodeHelpers.hashAugmentations(obj);\n"
+                + "    result = prime * result + obj.augmentations().hashCode();\n"
                 + "    return result;\n"
                 + "}\n", genHashCode(mockAugment(mockGenType("get" + TEST))).toString());
     }
@@ -137,19 +131,16 @@ public class BuilderGeneratorTest {
                 + " hashing\n"
                 + " * results across all implementations.\n"
                 + " *\n"
-                + " * @param <T$$> implementation type, which has to also implement AugmentationHolder interface\n"
-                + " *              contract.\n"
                 + " * @param obj Object for which to generate hashCode() result.\n"
                 + " * @return Hash code value of data modeled by this interface.\n"
                 + " * @throws NullPointerException if {@code obj} is null\n"
                 + " */\n"
-                + "static <T$$ extends test.test & AugmentationHolder<?>> int bindingHashCode(final @NonNull T$$ obj) {"
-                + "\n"
+                + "static int bindingHashCode(final test.@NonNull test obj) {\n"
                 + "    final int prime = 31;\n"
                 + "    int result = 1;\n"
                 + "    result = prime * result + Objects.hashCode(obj.getTest1());\n"
                 + "    result = prime * result + Objects.hashCode(obj.getTest2());\n"
-                + "    result = prime * result + CodeHelpers.hashAugmentations(obj);\n"
+                + "    result = prime * result + obj.augmentations().hashCode();\n"
                 + "    return result;\n"
                 + "}\n", genHashCode(mockAugment(mockGenTypeMoreMeth("get" + TEST))).toString());
     }
@@ -217,14 +208,11 @@ public class BuilderGeneratorTest {
                 + " * Implementations of this interface are encouraged to defer to this method to get consistent string"
                 + "\n * representations across all implementations.\n"
                 + " *\n"
-                + " * @param <T$$> implementation type, which has to also implement AugmentationHolder interface\n"
-                + " *              contract.\n"
                 + " * @param obj Object for which to generate toString() result.\n"
                 + " * @return {@link String} value of data modeled by this interface.\n"
                 + " * @throws NullPointerException if {@code obj} is null\n"
                 + " */\n"
-                + "static <T$$ extends test.test & AugmentationHolder<test.test>> String bindingToString(final @NonNull"
-                + " T$$ obj) {\n"
+                + "static String bindingToString(final test.@NonNull test obj) {\n"
                 + "    final MoreObjects.ToStringHelper helper = MoreObjects.toStringHelper(\"test\");\n"
                 + "    CodeHelpers.appendValue(helper, \"augmentation\", obj.augmentations().values());\n"
                 + "    return helper.toString();\n"
@@ -238,14 +226,11 @@ public class BuilderGeneratorTest {
                 + " * Implementations of this interface are encouraged to defer to this method to get consistent string"
                 + "\n * representations across all implementations.\n"
                 + " *\n"
-                + " * @param <T$$> implementation type, which has to also implement AugmentationHolder interface\n"
-                + " *              contract.\n"
                 + " * @param obj Object for which to generate toString() result.\n"
                 + " * @return {@link String} value of data modeled by this interface.\n"
                 + " * @throws NullPointerException if {@code obj} is null\n"
                 + " */\n"
-                + "static <T$$ extends test.test & AugmentationHolder<test.test>> String bindingToString(final @NonNull"
-                + " T$$ obj) {\n"
+                + "static String bindingToString(final test.@NonNull test obj) {\n"
                 + "    final MoreObjects.ToStringHelper helper = MoreObjects.toStringHelper(\"test\");\n"
                 + "    CodeHelpers.appendValue(helper, \"test\", obj.gettest());\n"
                 + "    CodeHelpers.appendValue(helper, \"augmentation\", obj.augmentations().values());\n"
@@ -260,14 +245,11 @@ public class BuilderGeneratorTest {
                 + " * Implementations of this interface are encouraged to defer to this method to get consistent string"
                 + "\n * representations across all implementations.\n"
                 + " *\n"
-                + " * @param <T$$> implementation type, which has to also implement AugmentationHolder interface\n"
-                + " *              contract.\n"
                 + " * @param obj Object for which to generate toString() result.\n"
                 + " * @return {@link String} value of data modeled by this interface.\n"
                 + " * @throws NullPointerException if {@code obj} is null\n"
                 + " */\n"
-                + "static <T$$ extends test.test & AugmentationHolder<test.test>> String bindingToString(final @NonNull"
-                + " T$$ obj) {\n"
+                + "static String bindingToString(final test.@NonNull test obj) {\n"
                 + "    final MoreObjects.ToStringHelper helper = MoreObjects.toStringHelper(\"test\");\n"
                 + "    CodeHelpers.appendValue(helper, \"test1\", obj.gettest1());\n"
                 + "    CodeHelpers.appendValue(helper, \"test2\", obj.gettest2());\n"
diff --git a/binding/mdsal-binding-spec-util/src/main/java/org/opendaylight/mdsal/binding/spec/reflect/AugmentationFieldGetter.java b/binding/mdsal-binding-spec-util/src/main/java/org/opendaylight/mdsal/binding/spec/reflect/AugmentationFieldGetter.java
deleted file mode 100644 (file)
index ad0c430..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.mdsal.binding.spec.reflect;
-
-import static java.util.Objects.requireNonNull;
-
-import com.google.common.cache.CacheBuilder;
-import com.google.common.cache.CacheLoader;
-import com.google.common.cache.LoadingCache;
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodHandles;
-import java.lang.invoke.MethodHandles.Lookup;
-import java.lang.invoke.MethodType;
-import java.lang.reflect.Field;
-import java.security.AccessController;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
-import java.util.Collections;
-import java.util.Map;
-import org.opendaylight.mdsal.binding.spec.naming.BindingMapping;
-import org.opendaylight.yangtools.yang.binding.Augmentation;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-abstract class AugmentationFieldGetter {
-
-    private static final Logger LOG = LoggerFactory.getLogger(AugmentationFieldGetter.class);
-
-    private static final AugmentationFieldGetter DUMMY = new AugmentationFieldGetter() {
-        @Override
-        Map<Class<? extends Augmentation<?>>, Augmentation<?>> getAugmentations(final Object input) {
-            return Collections.emptyMap();
-        }
-    };
-
-    private static final LoadingCache<Class<?>, AugmentationFieldGetter> AUGMENTATION_GETTERS =
-            CacheBuilder.newBuilder().weakKeys().build(new AugmentationGetterLoader());
-
-    /**
-     * Retrieves augmentations from supplied object.
-     *
-     * @param input Input Data object, from which augmentations should be extracted
-     * @return Map of Augmentation class to augmentation
-     */
-    abstract Map<Class<? extends Augmentation<?>>, Augmentation<?>> getAugmentations(Object input);
-
-    static AugmentationFieldGetter getGetter(final Class<? extends Object> clz) {
-        return AUGMENTATION_GETTERS.getUnchecked(clz);
-    }
-
-    private static final class AugmentationGetterLoader extends CacheLoader<Class<?>, AugmentationFieldGetter> {
-        private static final MethodType GETTER_TYPE = MethodType.methodType(Map.class, Object.class);
-        private static final Lookup LOOKUP = MethodHandles.lookup();
-
-        @Override
-        public AugmentationFieldGetter load(final Class<?> key) throws IllegalAccessException {
-            final Field field;
-            try {
-                field = AccessController.doPrivileged((PrivilegedExceptionAction<Field>) () -> {
-                    final Field f = key.getDeclaredField(BindingMapping.AUGMENTATION_FIELD);
-                    f.setAccessible(true);
-                    return f;
-                });
-            } catch (PrivilegedActionException e) {
-                LOG.warn("Failed to acquire augmentation field {}, ignoring augmentations in class {}",
-                    BindingMapping.AUGMENTATION_FIELD, key, e);
-                return DUMMY;
-            }
-            if (!Map.class.isAssignableFrom(field.getType())) {
-                LOG.warn("Class {} field {} is not a Map, ignoring augmentations", key,
-                    BindingMapping.AUGMENTATION_FIELD);
-                return DUMMY;
-            }
-
-            return new ReflectionAugmentationFieldGetter(LOOKUP.unreflectGetter(field).asType(GETTER_TYPE));
-        }
-    }
-
-    private static final class ReflectionAugmentationFieldGetter extends AugmentationFieldGetter {
-        private final MethodHandle fieldGetter;
-
-        ReflectionAugmentationFieldGetter(final MethodHandle mh) {
-            this.fieldGetter = requireNonNull(mh);
-        }
-
-        @Override
-        @SuppressWarnings("checkstyle:illegalCatch")
-        Map<Class<? extends Augmentation<?>>, Augmentation<?>> getAugmentations(final Object input) {
-            try {
-                return (Map<Class<? extends Augmentation<?>>, Augmentation<?>>) fieldGetter.invokeExact(input);
-            } catch (Throwable e) {
-                throw new IllegalStateException("Failed to access augmentation field on " + input, e);
-            }
-        }
-    }
-}
index 55df7d92372dc7c601f272f0c30fbe6372664f12..7e465bc6ebfbedbba59be3e088ef675f50155e84 100644 (file)
@@ -43,7 +43,6 @@ import org.opendaylight.yangtools.util.ClassLoaderUtils;
 import org.opendaylight.yangtools.yang.binding.Action;
 import org.opendaylight.yangtools.yang.binding.Augmentable;
 import org.opendaylight.yangtools.yang.binding.Augmentation;
-import org.opendaylight.yangtools.yang.binding.AugmentationHolder;
 import org.opendaylight.yangtools.yang.binding.BaseIdentity;
 import org.opendaylight.yangtools.yang.binding.ChildOf;
 import org.opendaylight.yangtools.yang.binding.DataContainer;
@@ -605,16 +604,14 @@ public final class BindingReflections {
     /**
      * Extracts augmentation from Binding DTO field using reflection.
      *
-     * @param input
-     *            Instance of DataObject which is augmentable and may contain
-     *            augmentation
+     * @param input Instance of DataObject which is augmentable and may contain augmentation
      * @return Map of augmentations if read was successful, otherwise empty map.
+     * @deprecated Use {@link Augmentable#augmentations()} instead.
      */
+    @SuppressWarnings("unchecked")
+    @Deprecated(forRemoval = true)
     public static Map<Class<? extends Augmentation<?>>, Augmentation<?>> getAugmentations(final Augmentable<?> input) {
-        if (input instanceof AugmentationHolder) {
-            return ((AugmentationHolder) input).augmentations();
-        }
-        return AugmentationFieldGetter.getGetter(input.getClass()).getAugmentations(input);
+        return (Map) input.augmentations();
     }
 
     /**
diff --git a/binding/mdsal-binding-spec-util/src/test/java/org/opendaylight/mdsal/binding/spec/reflect/AugmentationFieldGetterTest.java b/binding/mdsal-binding-spec-util/src/test/java/org/opendaylight/mdsal/binding/spec/reflect/AugmentationFieldGetterTest.java
deleted file mode 100644 (file)
index b37d713..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.mdsal.binding.spec.reflect;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.mockito.Mockito.mock;
-import static org.opendaylight.mdsal.binding.spec.reflect.AugmentationFieldGetter.getGetter;
-
-import java.util.HashMap;
-import java.util.Map;
-import org.junit.Test;
-import org.opendaylight.yangtools.yang.binding.Augmentation;
-
-public class AugmentationFieldGetterTest {
-
-    @Test
-    public void getGetterTest() throws Exception {
-        assertTrue(getGetter(Object.class).getAugmentations(null).isEmpty());
-        assertTrue(getGetter(TestAugmentationWrongTypeClass.class).getAugmentations(null).isEmpty());
-
-        final AugmentationFieldGetter augmentationFieldGetter = getGetter(TestAugmentationClass.class);
-        final Augmentation<?> augmentation = mock(Augmentation.class);
-        final TestAugmentationClass testAugmentationClass = new TestAugmentationClass();
-
-        testAugmentationClass.addAugmentation(augmentation, augmentation);
-        assertNotNull(augmentationFieldGetter.getAugmentations(testAugmentationClass));
-        assertEquals(1, augmentationFieldGetter.getAugmentations(testAugmentationClass).size());
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void getWrongGetterTest() throws Exception {
-        final AugmentationFieldGetter augmentationFieldGetter = getGetter(TestAugmentationClass.class);
-        augmentationFieldGetter.getAugmentations("");
-        fail("Expected IllegalStateException");
-    }
-
-    @Test
-    public void getNoGetterTest() throws Exception {
-        assertTrue(getGetter(Object.class).getAugmentations(null).isEmpty());
-    }
-
-    private final class TestAugmentationClass {
-        private final Map<Augmentation<?>, Augmentation<?>> augmentation = new HashMap<>();
-
-        void addAugmentation(final Augmentation<?> key, final Augmentation<?> value) {
-            augmentation.put(key, value);
-        }
-    }
-
-    private final class TestAugmentationWrongTypeClass {
-        private String augmentation;
-    }
-}
\ No newline at end of file
diff --git a/binding/mdsal-binding-test-utils/src/main/java/org/opendaylight/mdsal/binding/testutils/AugmentableExtension.java b/binding/mdsal-binding-test-utils/src/main/java/org/opendaylight/mdsal/binding/testutils/AugmentableExtension.java
deleted file mode 100644 (file)
index de460ff..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 2016 Red Hat, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.mdsal.binding.testutils;
-
-import com.google.common.collect.ClassToInstanceMap;
-import com.google.common.collect.ImmutableClassToInstanceMap;
-import org.eclipse.xtext.xbase.lib.util.ReflectExtensions;
-import org.opendaylight.yangtools.yang.binding.Augmentable;
-import org.opendaylight.yangtools.yang.binding.Augmentation;
-import org.opendaylight.yangtools.yang.binding.AugmentationHolder;
-
-/**
- * Adds an {@link #getAugmentations(Augmentable)} method to {@link Augmentable}.
- *
- * <p>Note that the generated *Impl classes in the *Builder do not implement
- * {@link AugmentationReader}, only the LazyDataObject (package local) does.
- *
- * @see Augmentable
- * @see AugmentationReader
- *
- * @author Michael Vorburger
- */
-// package-local: no need to expose this, consider it an implementation detail; public API is the AssertDataObjects
-// FIXME: 5.0.0: this is a duplication of BindingReflections.getAugmentations() ... but why?
-class AugmentableExtension {
-
-    private static final ReflectExtensions REFLECT_EXTENSIONS = new ReflectExtensions();
-
-    public ClassToInstanceMap<Augmentation<?>> getAugmentations(final Augmentable<?> augmentable) {
-        if (augmentable instanceof AugmentationHolder) {
-            AugmentationHolder<?> augmentationHolder = (AugmentationHolder<?>) augmentable;
-            return ImmutableClassToInstanceMap.copyOf(augmentationHolder.augmentations());
-        }
-
-        try {
-            return ImmutableClassToInstanceMap.copyOf(REFLECT_EXTENSIONS.get(augmentable, "augmentation"));
-        } catch (ClassCastException | SecurityException | NoSuchFieldException | IllegalArgumentException
-                | IllegalAccessException e) {
-            throw new IllegalArgumentException("TODO Implement getAugmentations() for an Augmentable which "
-                    + "is neither a (Proxy of an) AugmentationReader nor has an internal field named "
-                    + "'augmentation': " + augmentable.getClass(), e);
-        }
-    }
-
-}
index 6e87c5ab1527902188ec9fa7c17534a7232778e1..c9bd05972be27b4a6b3003594e0da50a7ddae031 100644 (file)
@@ -9,6 +9,7 @@ package org.opendaylight.mdsal.binding.testutils;
 
 import ch.vorburger.xtendbeans.XtendBeanGenerator;
 import com.google.common.collect.ClassToInstanceMap;
+import com.google.common.collect.ImmutableClassToInstanceMap;
 import com.google.common.collect.Iterables;
 import java.util.Comparator;
 import java.util.Optional;
@@ -38,8 +39,6 @@ import org.opendaylight.yangtools.yang.binding.DataObject;
 // package-local: no need to expose this, consider it an implementation detail; public API is the AssertDataObjects
 class XtendYangBeanGenerator extends XtendBeanGenerator {
 
-    private final AugmentableExtension augmentableExtension = new AugmentableExtension();
-
     @Override
     public String getExpression(final Object bean) {
         final String beanText = super.getExpression(bean);
@@ -85,10 +84,9 @@ class XtendYangBeanGenerator extends XtendBeanGenerator {
         return Iterables.filter(properties, property -> !property.getName().equals("key"));
     }
 
-    private Optional<ClassToInstanceMap<Augmentation<?>>> getAugmentations(final Object bean) {
+    private static Optional<ClassToInstanceMap<Augmentation<?>>> getAugmentations(final Object bean) {
         if (bean instanceof Augmentable<?>) {
-            Augmentable<?> augmentable = (Augmentable<?>) bean;
-            ClassToInstanceMap<Augmentation<?>> augmentables = augmentableExtension.getAugmentations(augmentable);
+            ClassToInstanceMap<Augmentation<?>> augmentables = augmentations((Augmentable<?>) bean);
             if (!augmentables.isEmpty()) {
                 return Optional.of(augmentables);
             }
@@ -96,6 +94,10 @@ class XtendYangBeanGenerator extends XtendBeanGenerator {
         return Optional.empty();
     }
 
+    private static ClassToInstanceMap<Augmentation<?>> augmentations(final Augmentable<?> augmentable) {
+        return ImmutableClassToInstanceMap.copyOf(augmentable.augmentations());
+    }
+
     @Override
     protected CharSequence getAdditionalInitializationExpression(final Object bean, final Class<?> builderClass) {
         Optional<ClassToInstanceMap<Augmentation<?>>> optional = getAugmentations(bean);
diff --git a/binding/mdsal-binding-test-utils/src/test/java/org/opendaylight/mdsal/binding/testutils/AugmentableExtensionTest.java b/binding/mdsal-binding-test-utils/src/test/java/org/opendaylight/mdsal/binding/testutils/AugmentableExtensionTest.java
deleted file mode 100644 (file)
index 1678954..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 2016 Red Hat, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.mdsal.binding.testutils;
-
-import static org.opendaylight.mdsal.common.api.LogicalDatastoreType.OPERATIONAL;
-
-import ch.vorburger.xtendbeans.AssertBeans;
-import java.util.Map;
-import org.junit.Test;
-import org.opendaylight.mdsal.binding.api.ReadTransaction;
-import org.opendaylight.mdsal.binding.api.WriteTransaction;
-import org.opendaylight.mdsal.binding.dom.adapter.test.AbstractDataBrokerTest;
-import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.Top;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.two.level.list.TopLevelList;
-import org.opendaylight.yangtools.yang.binding.Augmentation;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-
-/**
- * Test for {@link AugmentableExtension}.
- *
- * @author Michael Vorburger
- */
-public class AugmentableExtensionTest extends AbstractDataBrokerTest {
-
-    private final AugmentableExtension augmentableExtension = new AugmentableExtension();
-
-    @Test
-    public void testAugmentableExtensionOnYangObjectByBuilder() {
-        TopLevelList topLevelList = ExampleYangObjects.topLevelList().getValue();
-        Map<Class<? extends Augmentation<?>>, Augmentation<?>> augmentations = augmentableExtension
-                .getAugmentations(topLevelList);
-        AssertBeans.assertEqualByText("#{\n"
-                + "    org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test"
-                +        ".augment.rev140709.TreeComplexUsesAugment -> (new TreeComplexUsesAugmentBuilder => [\n"
-                + "        containerWithUses = (new ContainerWithUsesBuilder => [\n"
-                + "            leafFromGrouping = \"foo\"\n"
-                + "        ]).build()\n"
-                + "    ]).build()\n"
-                + "}", augmentations);
-    }
-
-    @Test
-    public void testAugmentableExtensionWithDataBroker() throws Exception {
-        WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
-        put(writeTx, OPERATIONAL, ExampleYangObjects.topLevelList());
-        writeTx.commit().get();
-
-        ReadTransaction readTx = getDataBroker().newReadOnlyTransaction();
-        InstanceIdentifier<Top> id = InstanceIdentifier.create(Top.class);
-        Top actualTop = readTx.read(OPERATIONAL, id).get().get();
-        AssertBeans.assertEqualByText("#{\n}", augmentableExtension.getAugmentations(actualTop));
-
-        TopLevelList topLevelList = actualTop.nonnullTopLevelList().values().iterator().next();
-        AssertDataObjects.assertEqualByText("#{\n"
-                + "    TreeComplexUsesAugment -> new TreeComplexUsesAugmentBuilder >> [\n"
-                + "        containerWithUses = new ContainerWithUsesBuilder >> [\n"
-                + "            leafFromGrouping = \"foo\"\n"
-                + "        ]\n"
-                + "    ]\n"
-                + "}", augmentableExtension.getAugmentations(topLevelList));
-    }
-
-    <T extends DataObject> void put(final WriteTransaction tx, final LogicalDatastoreType store,
-            final Map.Entry<InstanceIdentifier<T>, T> obj) {
-        tx.put(OPERATIONAL, obj.getKey(), obj.getValue());
-    }
-
-}
index a095e519f51d57b671d8cc6482336118e6401854..ab20493a96d9571e3482429750f3fc7c3f080ff0 100644 (file)
@@ -15,14 +15,12 @@ import java.util.Map;
 import org.eclipse.jdt.annotation.NonNull;
 
 /**
- * Abstract base class for implementing immutable {@link Augmentable} classes. This class is provided as a convenience,
- * combining {@link AugmentationHolder} and providing {@link Augmentable#augmentation(Class)} implementation on top of
- * held augmentations.
+ * Abstract base class for implementing immutable {@link Augmentable} classes. This class is provided as a convenience.
  *
  * @param <T> Augmentable type
  */
 @Beta
-public abstract class AbstractAugmentable<T extends Augmentable<T>> implements Augmentable<T>, AugmentationHolder<T> {
+public abstract class AbstractAugmentable<T extends Augmentable<T>> implements Augmentable<T> {
     private final @NonNull ImmutableMap<Class<? extends Augmentation<T>>, Augmentation<T>> augmentations;
 
     protected AbstractAugmentable() {
@@ -42,8 +40,8 @@ public abstract class AbstractAugmentable<T extends Augmentable<T>> implements A
         this(other.augmentations);
     }
 
-    @SuppressWarnings("unchecked")
     @Override
+    @SuppressWarnings("unchecked")
     public final <A extends Augmentation<T>> A augmentation(final Class<A> augmentationType) {
         return (A) augmentations.get(requireNonNull(augmentationType));
     }
index e6eee6959cc9dd10913a3b7c96e3bba129ad79e0..e4575233e43b9f8062705bfc4f14fcadfd14da84 100644 (file)
@@ -7,6 +7,10 @@
  */
 package org.opendaylight.yangtools.yang.binding;
 
+import static java.util.Objects.requireNonNull;
+
+import java.util.Map;
+import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.jdt.annotation.Nullable;
 
 /**
@@ -17,9 +21,7 @@ import org.eclipse.jdt.annotation.Nullable;
  * This interface uses extended version of ExtensibleInterface pattern which also adds marker interface for
  * augmentations (extensions) - {@link Augmentable}.
  *
- * @param <T>
- *            Base class which should implements this interface and is target
- *            for augmentation.
+ * @param <T> Base class which should implements this interface and is target for augmentation.
  * @author Tony Tkacik
  */
 public interface Augmentable<T> {
@@ -28,7 +30,18 @@ public interface Augmentable<T> {
      *
      * @param augmentationType Type of augmentation to be returned.
      * @param <A> Type capture for augmentation type
-     * @return instance of augmentation.
+     * @return instance of augmentation, or null if the augmentationType is not present.
+     * @throws NullPointerException if augmentationType is null
+     */
+    @SuppressWarnings("unchecked")
+    default <A extends Augmentation<T>> @Nullable A augmentation(final Class<A> augmentationType) {
+        return (A) augmentations().get(requireNonNull(augmentationType));
+    }
+
+    /**
+     * Returns map of all augmentations.
+     *
+     * @return map of all augmentations.
      */
-    <A extends Augmentation<T>> @Nullable A augmentation(Class<A> augmentationType);
+    @NonNull Map<Class<? extends Augmentation<T>>, Augmentation<T>> augmentations();
 }
diff --git a/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/AugmentationHolder.java b/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/AugmentationHolder.java
deleted file mode 100644 (file)
index 6a69b52..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.yangtools.yang.binding;
-
-import java.util.Map;
-import org.eclipse.jdt.annotation.NonNull;
-
-/**
- * Augmentable (extensible) object which could carry additional data defined by third-party extension, without
- * introducing conflict between various extension.
- *
- * @param <T>
- *            Base class which should is target
- *            for augmentations.
- * @author Tony Tkacik
- */
-public interface AugmentationHolder<T> {
-    /**
-     * Returns map of all augmentations.
-     *
-     * @return map of all augmentations.
-     */
-    @NonNull Map<Class<? extends Augmentation<T>>, Augmentation<T>> augmentations();
-}
index 74a2cc0e9bee7fdc251f5049fd9b2a6b0e87df5c..5d224d300a55f41f627bd58220a356eb1de20b48 100644 (file)
@@ -20,7 +20,6 @@ import java.math.BigInteger;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
-import java.util.Map.Entry;
 import java.util.Objects;
 import java.util.regex.Pattern;
 import org.eclipse.jdt.annotation.NonNull;
@@ -395,43 +394,6 @@ public final class CodeHelpers {
             ? requiredClass.cast(obj) : null;
     }
 
-    /**
-     * Utility method for comparing two augmentable objects' augmentations.
-     *
-     * @param <T> Augmentable type
-     * @param thisObj The object representing 'this'
-     * @param other The object representing 'obj'
-     * @return True if both object's augmentations are equal
-     * @throws NullPointerException if any argument is null
-     */
-    public static <T extends Augmentable<T>> boolean equalsAugmentations(final @NonNull AugmentationHolder<T> thisObj,
-            final @NonNull Augmentable<T> other) {
-        if (other instanceof AugmentationHolder) {
-            // Simple case: other object is also an AugmentationHolder
-            return thisObj.augmentations().equals(((AugmentationHolder<?>) other).augmentations());
-        }
-
-        // Hard case: compare our augments with presence there...
-        for (Entry<Class<? extends Augmentation<T>>, Augmentation<T>> e : thisObj.augmentations().entrySet()) {
-            if (!e.getValue().equals(other.augmentation(e.getKey()))) {
-                return false;
-            }
-        }
-        // .. and give the other one the chance to do the same
-        return other.equals(thisObj);
-    }
-
-    /**
-     * Utility for extracting augmentations from an implementation of {@link AugmentationHolder} interface.
-     *
-     * @param obj Implementation object
-     * @return hash code of augmentations
-     * @throws NullPointerException if obj is null
-     */
-    public static int hashAugmentations(final @NonNull AugmentationHolder<?> obj) {
-        return obj.augmentations().hashCode();
-    }
-
     /**
      * The constant '31' is the result of folding this code:
      * <pre>