*/
package org.opendaylight.yangtools.binding.data.codec.impl;
+import org.opendaylight.yangtools.yang.binding.AugmentationHolder;
+
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.base.Throwables;
byBindingArgClassBuilder.putAll(byStreamClass);
this.byBindingArgClass = ImmutableMap.copyOf(byBindingArgClassBuilder);
- final Class<?> proxyClass = Proxy.getProxyClass(getBindingClass().getClassLoader(), new Class[] { getBindingClass() });
+ final Class<?> proxyClass = Proxy.getProxyClass(getBindingClass().getClassLoader(), new Class[] { getBindingClass(), AugmentationHolder.class });
try {
proxyConstructor = LOOKUP.findConstructor(proxyClass, CONSTRUCTOR_TYPE).asType(DATAOBJECT_TYPE);
} catch (NoSuchMethodException | IllegalAccessException e) {
@SuppressWarnings("unchecked")
@Override
public <DV extends DataObject> Optional<DataContainerCodecContext<DV, ?>> possibleStreamChild(
- Class<DV> childClass) {
+ final Class<DV> childClass) {
final DataContainerCodecPrototype<?> childProto = byStreamClass.get(childClass);
if(childProto != null) {
return Optional.<DataContainerCodecContext<DV,?>>of((DataContainerCodecContext<DV,?>) childProto.get());
}
@Override
- public InstanceIdentifier.PathArgument deserializePathArgument(YangInstanceIdentifier.PathArgument arg) {
+ public InstanceIdentifier.PathArgument deserializePathArgument(final YangInstanceIdentifier.PathArgument arg) {
Preconditions.checkArgument(getDomPathArgument().equals(arg));
return bindingArg();
}
@Override
- public YangInstanceIdentifier.PathArgument serializePathArgument(InstanceIdentifier.PathArgument arg) {
+ public YangInstanceIdentifier.PathArgument serializePathArgument(final InstanceIdentifier.PathArgument arg) {
Preconditions.checkArgument(bindingArg().equals(arg));
return getDomPathArgument();
}
private static final String EQUALS = "equals";
private static final String GET_AUGMENTATION = "getAugmentation";
private static final String HASHCODE = "hashCode";
+ private static final String AUGMENTATIONS = "augmentations";
private static final Object NULL_VALUE = new Object();
private final ConcurrentHashMap<Method, Object> cachedData = new ConcurrentHashMap<>();
return bindingToString();
} else if (HASHCODE.equals(name)) {
return bindingHashCode();
+ } else if (AUGMENTATIONS.equals(name)) {
+ return getAugmentationsImpl();
}
return getBindingData(method);
} else if (GET_AUGMENTATION.equals(method.getName())) {
*/
package org.opendaylight.yangtools.binding.data.codec.test;
+import static org.junit.Assert.assertEquals;
+
+import com.google.common.base.Optional;
+import java.util.Collections;
import javassist.ClassPool;
import org.junit.Test;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.RpcComplexUsesAugment;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import java.util.Collections;
-
-import static org.junit.Assert.assertEquals;
-
public class AugmentationSubstitutionTest extends AbstractBindingRuntimeTest {
@Override
public void setup() {
super.setup();
- JavassistUtils utils = JavassistUtils.forClassPool(ClassPool.getDefault());
+ final JavassistUtils utils = JavassistUtils.forClassPool(ClassPool.getDefault());
registry = new BindingNormalizedNodeCodecRegistry(StreamWriterGenerator.create(utils));
registry.onBindingRuntimeContextUpdated(getRuntimeContext());
}
@Test
public void augmentationInGroupingSubstituted() {
- TopLevelList baRpc = new TopLevelListBuilder()
+ final TopLevelList baRpc = new TopLevelListBuilder()
.setKey(TOP_FOO_KEY)
.addAugmentation(RpcComplexUsesAugment.class, new RpcComplexUsesAugmentBuilder(createComplexData()).build())
.build();
- TopLevelList baTree = new TopLevelListBuilder()
+ final TopLevelList baTree = new TopLevelListBuilder()
.setKey(TOP_FOO_KEY)
.addAugmentation(TreeComplexUsesAugment.class, new TreeComplexUsesAugmentBuilder(createComplexData()).build())
.build();
- NormalizedNode<?, ?> domTreeEntry = registry.toNormalizedNode(BA_TOP_LEVEL_LIST, baTree).getValue();
- NormalizedNode<?, ?> domRpcEntry = registry.toNormalizedNode(BA_TOP_LEVEL_LIST, baRpc).getValue();
+ final NormalizedNode<?, ?> domTreeEntry = registry.toNormalizedNode(BA_TOP_LEVEL_LIST, baTree).getValue();
+ final NormalizedNode<?, ?> domRpcEntry = registry.toNormalizedNode(BA_TOP_LEVEL_LIST, baRpc).getValue();
assertEquals(domTreeEntry, domRpcEntry);
}
+ @Test
+ public void copyBuilderWithAugmenationsTest() {
+ final TopLevelList manuallyConstructed = new TopLevelListBuilder()
+ .setKey(TOP_FOO_KEY)
+ .addAugmentation(TreeComplexUsesAugment.class, new TreeComplexUsesAugmentBuilder(createComplexData()).build())
+ .build();
+ final NormalizedNode<?, ?> domTreeEntry = registry.toNormalizedNode(BA_TOP_LEVEL_LIST, manuallyConstructed).getValue();
+ final TopLevelList deserialized = registry.deserializeFunction(BA_TOP_LEVEL_LIST).apply(Optional.<NormalizedNode<?, ?>>of(domTreeEntry)).get();
+ assertEquals(manuallyConstructed, deserialized);
+ final TopLevelList copiedFromDeserialized = new TopLevelListBuilder(deserialized).build();
+ assertEquals(manuallyConstructed, copiedFromDeserialized);
+ }
+
private RpcComplexUsesAugment createComplexData() {
return new RpcComplexUsesAugmentBuilder()
.setContainerWithUses(new ContainerWithUsesBuilder()
import org.opendaylight.yangtools.yang.binding.DataObject
import org.opendaylight.yangtools.yang.binding.Identifiable
import org.opendaylight.yangtools.concepts.Builder
+import org.opendaylight.yangtools.yang.binding.AugmentationHolder
/**
* Template for generating JAVA builder classes.
this.«field.fieldName» = base.«field.getterMethodName»();
«ENDFOR»
«IF augmentField != null»
- «IF !impl»if (base instanceof «type.name»«IMPL») {«ENDIF»
- «IF !impl»«type.name»«IMPL» _impl = («type.name»«IMPL») base;«ENDIF»
- «val prop = if (impl) "base" else "_impl"»
- «IF impl»
- switch («prop».«augmentField.name».size()) {
- case 0:
- this.«augmentField.name» = «Collections.importedName».emptyMap();
- break;
- case 1:
- final «Map.importedName».Entry<«Class.importedName»<? extends «augmentField.returnType.importedName»>, «augmentField.returnType.importedName»> e = «prop».«augmentField.name».entrySet().iterator().next();
- this.«augmentField.name» = «Collections.importedName».<«Class.importedName»<? extends «augmentField.returnType.importedName»>, «augmentField.returnType.importedName»>singletonMap(e.getKey(), e.getValue());
- break;
- default :
- this.«augmentField.name» = new «HashMap.importedName»<>(«prop».«augmentField.name»);
- }
- «ELSE»
- this.«augmentField.name» = new «HashMap.importedName»<>(«prop».«augmentField.name»);
- «ENDIF»
- «IF !impl»}«ENDIF»
+ «IF impl»
+ switch (base.«augmentField.name».size()) {
+ case 0:
+ this.«augmentField.name» = «Collections.importedName».emptyMap();
+ break;
+ case 1:
+ final «Map.importedName».Entry<«Class.importedName»<? extends «augmentField.returnType.importedName»>, «augmentField.returnType.importedName»> e = base.«augmentField.name».entrySet().iterator().next();
+ this.«augmentField.name» = «Collections.importedName».<«Class.importedName»<? extends «augmentField.returnType.importedName»>, «augmentField.returnType.importedName»>singletonMap(e.getKey(), e.getValue());
+ break;
+ default :
+ this.«augmentField.name» = new «HashMap.importedName»<>(base.«augmentField.name»);
+ }
+ «ELSE»
+ if (base instanceof «type.name»«IMPL») {
+ «type.name»«IMPL» impl = («type.name»«IMPL») base;
+ this.«augmentField.name» = new «HashMap.importedName»<>(impl.«augmentField.name»);
+ } else if (base instanceof «AugmentationHolder.importedName») {
+ @SuppressWarnings("unchecked")
+ «AugmentationHolder.importedName»<«type.importedName»> casted =(«AugmentationHolder.importedName»<«type.importedName»>) base;
+ this.«augmentField.name» = new «HashMap.importedName»<>(casted.augmentations());
+ }
+ «ENDIF»
«ENDIF»
}
'''
--- /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;
+
+/**
+ *
+ * Augmentable (extensible) object which could carry additional data defined by
+ * third-party extension, without introducing conflict between various
+ * extension.
+ *
+ *
+ * @author Tony Tkacik
+ * @param <T>
+ * Base class which should is target
+ * for augmentations.
+ */
+public interface AugmentationHolder<T> {
+
+ /**
+ * Returns map of all augmentations.
+ *
+ * @return map of all augmentations.
+ */
+ Map<Class<? extends Augmentation<T>>,Augmentation<T>> augmentations();
+}
/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ * 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
+ * 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.util;
+import org.opendaylight.yangtools.yang.binding.AugmentationHolder;
+
import com.google.common.base.Preconditions;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
}
};
- /**
- *
- * Retrieves augmentations from supplied object
- *
- * @param input Input Data object, from which augmentations should be extracted
- * @return Map of Augmentation class to augmentation
- */
- protected abstract Map<Class<? extends Augmentation<?>>, Augmentation<?>> getAugmentations(final Object input);
+ private static final AugmentationFieldGetter AUGMENTATION_HOLDER_GETTER = new AugmentationFieldGetter() {
- private static final LoadingCache<Class<?>, AugmentationFieldGetter> AUGMENTATION_GETTERS =
- CacheBuilder.newBuilder().weakKeys().softValues().build(new AugmentationGetterLoader());
+ @Override
+ @SuppressWarnings({"unchecked", "rawtypes"})
+ protected Map<Class<? extends Augmentation<?>>, Augmentation<?>> getAugmentations(final Object input) {
+ return (Map) ((AugmentationHolder<?>) input).augmentations();
+ }
+ };
+
+ /**
+ *
+ * Retrieves augmentations from supplied object
+ *
+ * @param input Input Data object, from which augmentations should be extracted
+ * @return Map of Augmentation class to augmentation
+ */
+ protected abstract Map<Class<? extends Augmentation<?>>, Augmentation<?>> getAugmentations(final Object input);
+
+ private static final LoadingCache<Class<?>, AugmentationFieldGetter> AUGMENTATION_GETTERS = CacheBuilder
+ .newBuilder().weakKeys().softValues().build(new AugmentationGetterLoader());
public static AugmentationFieldGetter getGetter(final Class<? extends Object> clz) {
+ if(AugmentationHolder.class.isAssignableFrom(clz)) {
+ return AUGMENTATION_HOLDER_GETTER;
+ }
return AUGMENTATION_GETTERS.getUnchecked(clz);
}
}
}
-
}