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.data.api.schema.AugmentationNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
-import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+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")
- final Entry<AugmentationIdentifier, AugmentationSchema> augSchema = factory().getRuntimeContext()
+ final Entry<AugmentationIdentifier, AugmentationSchemaNode> augSchema = factory().getRuntimeContext()
.getResolvedAugmentationSchema(getSchema(), augClass);
return DataContainerCodecPrototype.from(augClass, augSchema.getKey(), augSchema.getValue(), factory());
}
Object getBindingChildValue(final Method method, final NormalizedNodeContainer domData) {
final NodeCodecContext<?> childContext = byMethod.get(method).get();
@SuppressWarnings("unchecked")
- final Optional<NormalizedNode<?, ?>> domChild = domData.getChild(childContext.getDomPathArgument());
+ final java.util.Optional<NormalizedNode<?, ?>> domChild = domData.getChild(childContext.getDomPathArgument());
if (domChild.isPresent()) {
return childContext.deserializeObject(domChild.get());
} else if (childContext instanceof LeafNodeCodecContext) {
}
@SuppressWarnings("unchecked")
- public Map<Class<? extends Augmentation<?>>, Augmentation<?>> getAllAugmentationsFrom(
+ Map<Class<? extends Augmentation<?>>, Augmentation<?>> getAllAugmentationsFrom(
final NormalizedNodeContainer<?, PathArgument, NormalizedNode<?, ?>> data) {
@SuppressWarnings("rawtypes")
}
}
for (final DataContainerCodecPrototype<?> value : byStreamAugmented.values()) {
- final Optional<NormalizedNode<?, ?>> augData = data.getChild(value.getYangArg());
+ final java.util.Optional<NormalizedNode<?, ?>> augData = data.getChild(value.getYangArg());
if (augData.isPresent()) {
map.put(value.getBindingClass(), value.get().deserializeObject(augData.get()));
}
return map;
}
- public Collection<Method> getHashCodeAndEqualsMethods() {
+ Collection<Method> getHashCodeAndEqualsMethods() {
return byMethod.keySet();
}