import com.google.common.base.Preconditions;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableMap.Builder;
import com.google.common.collect.ImmutableSortedMap;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DocumentedNode.WithStatus;
import org.opendaylight.yangtools.yang.model.util.SchemaNodeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-abstract class DataObjectCodecContext<D extends DataObject, T extends DataNodeContainer>
+abstract class DataObjectCodecContext<D extends DataObject, T extends DataNodeContainer & WithStatus>
extends DataContainerCodecContext<D, T> {
private static final Logger LOG = LoggerFactory.getLogger(DataObjectCodecContext.class);
private static final MethodType CONSTRUCTOR_TYPE = MethodType.methodType(void.class, InvocationHandler.class);
new ConcurrentHashMap<>();
private final ConcurrentMap<Class<?>, DataContainerCodecPrototype<?>> byStreamAugmented = new ConcurrentHashMap<>();
+ private volatile ImmutableMap<Class<?>, DataContainerCodecPrototype<?>> mismatchedAugmented = ImmutableMap.of();
- protected DataObjectCodecContext(final DataContainerCodecPrototype<T> prototype) {
+ DataObjectCodecContext(final DataContainerCodecPrototype<T> prototype) {
super(prototype);
this.leafChild = factory().getLeafNodes(getBindingClass(), getSchema());
}
} else {
// We are looking for instantiation via uses in other module
- final QName instantiedName = QName.create(namespace(), origDef.getQName().getLocalName());
+ final QName instantiedName = origDef.getQName().withModule(namespace());
final DataSchemaNode potential = getSchema().getDataChildByName(instantiedName);
// We check if it is really instantiated from same
// definition as class was derived
}
/*
- * It is potentially mismatched valid augmentation - we look up equivalent augmentation
- * using reflection and walk all stream child and compare augmenations classes if they are
- * equivalent.
- *
- * FIXME: Cache mapping of mismatched augmentation to real one, to speed up lookup.
+ * It is potentially mismatched valid augmentation - we look up equivalent augmentation using reflection
+ * and walk all stream child and compare augmentations classes if they are equivalent. When we find a match
+ * we'll cache it so we do not need to perform reflection operations again.
*/
+ final DataContainerCodecPrototype<?> mismatched = mismatchedAugmented.get(childClass);
+ if (mismatched != null) {
+ return mismatched;
+ }
+
@SuppressWarnings("rawtypes")
final Class<?> augTarget = BindingReflections.findAugmentationTarget((Class) childClass);
if (getBindingClass().equals(augTarget)) {
for (final DataContainerCodecPrototype<?> realChild : byStreamAugmented.values()) {
if (Augmentation.class.isAssignableFrom(realChild.getBindingClass())
&& BindingReflections.isSubstitutionFor(childClass, realChild.getBindingClass())) {
- return realChild;
+ return cacheMismatched(childClass, realChild);
}
}
}
return null;
}
+ private synchronized DataContainerCodecPrototype<?> cacheMismatched(final Class<?> childClass,
+ final DataContainerCodecPrototype<?> prototype) {
+ // Original access was unsynchronized, we need to perform additional checking
+ final ImmutableMap<Class<?>, DataContainerCodecPrototype<?>> local = mismatchedAugmented;
+ final DataContainerCodecPrototype<?> existing = local.get(childClass);
+ if (existing != null) {
+ return existing;
+ }
+
+ final Builder<Class<?>, DataContainerCodecPrototype<?>> builder = ImmutableMap.builderWithExpectedSize(
+ local.size() + 1);
+ builder.putAll(local);
+ builder.put(childClass, prototype);
+
+ mismatchedAugmented = builder.build();
+ return prototype;
+ }
+
private DataContainerCodecPrototype<?> getAugmentationPrototype(final Type value) {
final ClassLoadingStrategy loader = factory().getRuntimeContext().getStrategy();
@SuppressWarnings("rawtypes")
}
@SuppressWarnings("unchecked")
- public Map<Class<? extends Augmentation<?>>, Augmentation<?>> getAllAugmentationsFrom(
+ Map<Class<? extends Augmentation<?>>, Augmentation<?>> getAllAugmentationsFrom(
final NormalizedNodeContainer<?, PathArgument, NormalizedNode<?, ?>> data) {
@SuppressWarnings("rawtypes")
return map;
}
- public Collection<Method> getHashCodeAndEqualsMethods() {
+ Collection<Method> getHashCodeAndEqualsMethods() {
return byMethod.keySet();
}