From: Robert Varga Date: Mon, 3 Aug 2020 12:02:14 +0000 (+0200) Subject: Eliminate AugmentationHolder X-Git-Tag: v7.0.0~61 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=2319630c6a8322e433010e6254e49b711f981206;p=mdsal.git Eliminate AugmentationHolder 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 --- diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/AugmentableCodecDataObject.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/AugmentableCodecDataObject.java index 5f35249013..91c64cfc8b 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/AugmentableCodecDataObject.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/AugmentableCodecDataObject.java @@ -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 DataObject type */ public abstract class AugmentableCodecDataObject> - extends CodecDataObject implements Augmentable, AugmentationHolder { + extends CodecDataObject implements Augmentable { private static final VarHandle CACHED_AUGMENTATIONS; static { diff --git a/binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/BuilderTemplate.xtend b/binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/BuilderTemplate.xtend index 450de7ccfa..0ab6e58344 100644 --- a/binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/BuilderTemplate.xtend +++ b/binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/BuilderTemplate.xtend @@ -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», «augmentTypeRef»> aug =((«augmentationHolderRef»<«typeRef»>) base).augmentations(); - if (!aug.isEmpty()) { - this.«AUGMENTATION_FIELD» = new «hashMapRef»<>(aug); - } + @SuppressWarnings("unchecked") + «JU_MAP.importedName»<«CLASS.importedName», «augmentTypeRef»> aug = base.augmentations(); + if (!aug.isEmpty()) { + this.«AUGMENTATION_FIELD» = new «hashMapRef»<>(aug); } ''' } diff --git a/binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/InterfaceTemplate.xtend b/binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/InterfaceTemplate.xtend index 2ead021a95..7780cbd510 100644 --- a/binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/InterfaceTemplate.xtend +++ b/binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/InterfaceTemplate.xtend @@ -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 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 > 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 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 > 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 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 > «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»()); diff --git a/binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/JavaFileTemplate.java b/binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/JavaFileTemplate.java index b8b3ecf23c..cec3079586 100644 --- a/binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/JavaFileTemplate.java +++ b/binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/JavaFileTemplate.java @@ -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 METHOD_COMPARATOR = new AlphabeticallyTypeMemberComparator<>(); private static final Type AUGMENTATION_RET_TYPE; diff --git a/binding/mdsal-binding-java-api-generator/src/test/java/org/opendaylight/mdsal/binding/java/api/generator/BuilderGeneratorTest.java b/binding/mdsal-binding-java-api-generator/src/test/java/org/opendaylight/mdsal/binding/java/api/generator/BuilderGeneratorTest.java index 79cbe70982..e64c018e99 100644 --- a/binding/mdsal-binding-java-api-generator/src/test/java/org/opendaylight/mdsal/binding/java/api/generator/BuilderGeneratorTest.java +++ b/binding/mdsal-binding-java-api-generator/src/test/java/org/opendaylight/mdsal/binding/java/api/generator/BuilderGeneratorTest.java @@ -90,17 +90,14 @@ public class BuilderGeneratorTest { + " hashing\n" + " * results across all implementations.\n" + " *\n" - + " * @param 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 > 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 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 > 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 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 > 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 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 > 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 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 > 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 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 > 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 index ad0c430d2e..0000000000 --- a/binding/mdsal-binding-spec-util/src/main/java/org/opendaylight/mdsal/binding/spec/reflect/AugmentationFieldGetter.java +++ /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>, Augmentation> getAugmentations(final Object input) { - return Collections.emptyMap(); - } - }; - - private static final LoadingCache, 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>, Augmentation> getAugmentations(Object input); - - static AugmentationFieldGetter getGetter(final Class clz) { - return AUGMENTATION_GETTERS.getUnchecked(clz); - } - - private static final class AugmentationGetterLoader extends CacheLoader, 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) () -> { - 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>, Augmentation> getAugmentations(final Object input) { - try { - return (Map>, Augmentation>) fieldGetter.invokeExact(input); - } catch (Throwable e) { - throw new IllegalStateException("Failed to access augmentation field on " + input, e); - } - } - } -} diff --git a/binding/mdsal-binding-spec-util/src/main/java/org/opendaylight/mdsal/binding/spec/reflect/BindingReflections.java b/binding/mdsal-binding-spec-util/src/main/java/org/opendaylight/mdsal/binding/spec/reflect/BindingReflections.java index 55df7d9237..7e465bc6eb 100644 --- a/binding/mdsal-binding-spec-util/src/main/java/org/opendaylight/mdsal/binding/spec/reflect/BindingReflections.java +++ b/binding/mdsal-binding-spec-util/src/main/java/org/opendaylight/mdsal/binding/spec/reflect/BindingReflections.java @@ -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>, 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 index b37d713ad8..0000000000 --- a/binding/mdsal-binding-spec-util/src/test/java/org/opendaylight/mdsal/binding/spec/reflect/AugmentationFieldGetterTest.java +++ /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 = 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 index de460ff45f..0000000000 --- a/binding/mdsal-binding-test-utils/src/main/java/org/opendaylight/mdsal/binding/testutils/AugmentableExtension.java +++ /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}. - * - *

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> 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); - } - } - -} diff --git a/binding/mdsal-binding-test-utils/src/main/java/org/opendaylight/mdsal/binding/testutils/XtendYangBeanGenerator.java b/binding/mdsal-binding-test-utils/src/main/java/org/opendaylight/mdsal/binding/testutils/XtendYangBeanGenerator.java index 6e87c5ab15..c9bd05972b 100644 --- a/binding/mdsal-binding-test-utils/src/main/java/org/opendaylight/mdsal/binding/testutils/XtendYangBeanGenerator.java +++ b/binding/mdsal-binding-test-utils/src/main/java/org/opendaylight/mdsal/binding/testutils/XtendYangBeanGenerator.java @@ -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>> getAugmentations(final Object bean) { + private static Optional>> getAugmentations(final Object bean) { if (bean instanceof Augmentable) { - Augmentable augmentable = (Augmentable) bean; - ClassToInstanceMap> augmentables = augmentableExtension.getAugmentations(augmentable); + ClassToInstanceMap> 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> augmentations(final Augmentable augmentable) { + return ImmutableClassToInstanceMap.copyOf(augmentable.augmentations()); + } + @Override protected CharSequence getAdditionalInitializationExpression(final Object bean, final Class builderClass) { Optional>> 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 index 1678954d66..0000000000 --- a/binding/mdsal-binding-test-utils/src/test/java/org/opendaylight/mdsal/binding/testutils/AugmentableExtensionTest.java +++ /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>, 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 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)); - } - - void put(final WriteTransaction tx, final LogicalDatastoreType store, - final Map.Entry, T> obj) { - tx.put(OPERATIONAL, obj.getKey(), obj.getValue()); - } - -} diff --git a/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/AbstractAugmentable.java b/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/AbstractAugmentable.java index a095e519f5..ab20493a96 100644 --- a/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/AbstractAugmentable.java +++ b/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/AbstractAugmentable.java @@ -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 Augmentable type */ @Beta -public abstract class AbstractAugmentable> implements Augmentable, AugmentationHolder { +public abstract class AbstractAugmentable> implements Augmentable { private final @NonNull ImmutableMap>, Augmentation> augmentations; protected AbstractAugmentable() { @@ -42,8 +40,8 @@ public abstract class AbstractAugmentable> implements A this(other.augmentations); } - @SuppressWarnings("unchecked") @Override + @SuppressWarnings("unchecked") public final > A augmentation(final Class augmentationType) { return (A) augmentations.get(requireNonNull(augmentationType)); } diff --git a/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/Augmentable.java b/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/Augmentable.java index e6eee6959c..e4575233e4 100644 --- a/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/Augmentable.java +++ b/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/Augmentable.java @@ -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 - * Base class which should implements this interface and is target - * for augmentation. + * @param Base class which should implements this interface and is target for augmentation. * @author Tony Tkacik */ public interface Augmentable { @@ -28,7 +30,18 @@ public interface Augmentable { * * @param augmentationType Type of augmentation to be returned. * @param 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 > @Nullable A augmentation(final Class augmentationType) { + return (A) augmentations().get(requireNonNull(augmentationType)); + } + + /** + * Returns map of all augmentations. + * + * @return map of all augmentations. */ - > @Nullable A augmentation(Class augmentationType); + @NonNull Map>, Augmentation> 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 index 6a69b5289f..0000000000 --- a/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/AugmentationHolder.java +++ /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 - * Base class which should is target - * for augmentations. - * @author Tony Tkacik - */ -public interface AugmentationHolder { - /** - * Returns map of all augmentations. - * - * @return map of all augmentations. - */ - @NonNull Map>, Augmentation> augmentations(); -} diff --git a/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/CodeHelpers.java b/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/CodeHelpers.java index 74a2cc0e9b..5d224d300a 100644 --- a/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/CodeHelpers.java +++ b/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/CodeHelpers.java @@ -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 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 > boolean equalsAugmentations(final @NonNull AugmentationHolder thisObj, - final @NonNull Augmentable 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>, Augmentation> 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: *