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;
* @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 {
'''
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);
}
'''
}
* 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;
}
* 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;
}
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»
'''
* 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»());
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;
* {@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;
+ " 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());
}
+ " 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());
}
+ " 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());
}
+ " * 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"
+ " * 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"
+ " * 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"
+++ /dev/null
-/*
- * 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);
- }
- }
- }
-}
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;
/**
* 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();
}
/**
+++ /dev/null
-/*
- * 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
+++ /dev/null
-/*
- * 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);
- }
- }
-
-}
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;
// 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);
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);
}
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);
+++ /dev/null
-/*
- * 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());
- }
-
-}
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() {
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));
}
*/
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;
/**
* 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> {
*
* @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();
}
+++ /dev/null
-/*
- * 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();
-}
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;
? 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>