package org.opendaylight.mdsal.binding.dom.codec.impl;
import java.io.IOException;
+import org.opendaylight.mdsal.binding.dom.codec.impl.LeafNodeCodecContext.OfTypeObject;
import org.opendaylight.yangtools.yang.binding.BindingSerializer;
import org.opendaylight.yangtools.yang.binding.BindingStreamEventWriter;
import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.TypeObject;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* Serializer of Binding objects to Normalized Node which uses {@link DataObjectNormalizedNodeCache} to
* {@link org.opendaylight.yangtools.yang.binding.DataObjectSerializer} to provide Binding object
* for inspection and to prevent streaming of already serialized object.
*/
-final class CachingNormalizedNodeSerializer extends ForwardingBindingStreamEventWriter implements
- BindingSerializer<Object, DataObject> {
+final class CachingNormalizedNodeSerializer extends ForwardingBindingStreamEventWriter
+ implements BindingSerializer<Object, DataObject> {
+ private static final Logger LOG = LoggerFactory.getLogger(CachingNormalizedNodeSerializer.class);
private final NormalizedNodeResult domResult;
private final NormalizedNodeWriterWithAddChild domWriter;
return domResult.getResult();
}
+ @Override
+ public void leafNode(final String localName, final Object value) throws IOException {
+ if (value instanceof TypeObject) {
+ // TypeObject is a tagging interface used for generated classes which wrap derived and restricted types.
+ // They are immutable and hence we can safely wrap them in LeafNodes and reuse them, if directed to do so.
+ final TypeObject typed = (TypeObject) value;
+ final Class<? extends TypeObject> type = typed.getClass();
+ if (cacheHolder.isCached(type)) {
+ final ValueNodeCodecContext context = ((DataObjectCodecContext<?, ?>) delegate.current())
+ .getLeafChild(localName);
+ if (context instanceof OfTypeObject) {
+ final AbstractBindingNormalizedNodeCache<TypeObject, ?> cache = cacheHolder.getCachingSerializer(
+ (OfTypeObject<?>)context);
+ if (cache != null) {
+ // We have a cache hit and are thus done
+ domWriter.addChild(cache.get(typed));
+ return;
+ }
+
+ LOG.debug("Unexpected failure to acquire cache for context {}, skipping caching", context);
+ } else {
+ LOG.debug("Context {} does not match expected TypeObject {}, skipping caching", context, typed);
+ }
+ }
+ }
+ super.leafNode(localName, value);
+ }
+
/**
* Serializes input if it is cached, returns null otherwise.
*
*/
@Override
public NormalizedNode<?, ?> serialize(final DataObject input) {
- final DataObjectNormalizedNodeCache cachingSerializer = getCacheSerializer(input.implementedInterface());
+ final AbstractBindingNormalizedNodeCache<DataObject, ?> cachingSerializer = getCacheSerializer(
+ input.implementedInterface());
if (cachingSerializer != null) {
final NormalizedNode<?, ?> domData = cachingSerializer.get(input);
domWriter.addChild(domData);
return null;
}
- private DataObjectNormalizedNodeCache getCacheSerializer(final Class<? extends DataObject> type) {
+ private AbstractBindingNormalizedNodeCache<DataObject, ?> getCacheSerializer(
+ final Class<? extends DataObject> type) {
if (cacheHolder.isCached(type)) {
final DataContainerCodecContext<?, ?> currentCtx = (DataContainerCodecContext<?, ?>) delegate.current();
if (type.equals(currentCtx.getBindingClass())) {