--- /dev/null
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.javav2.dom.codec.impl.cache;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Preconditions;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import java.util.Set;
+import javax.annotation.Nonnull;
+import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.context.base.DataContainerCodecContext;
+import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode;
+
+/**
+ * Abstract Holder of Binding to Normalized Node caches indexed by
+ * {@link DataContainerCodecContext} to which cache is associated.
+ *
+ */
+@Beta
+public abstract class AbstractBindingNormalizedNodeCacheHolder {
+
+ private final Set<Class<? extends TreeNode>> cachedValues;
+ private final LoadingCache<DataContainerCodecContext<?, ?>, BindingNormalizedNodeCache> caches = CacheBuilder
+ .newBuilder().build(new CacheLoader<DataContainerCodecContext<?, ?>, BindingNormalizedNodeCache>() {
+
+ @Override
+ public BindingNormalizedNodeCache load(@Nonnull final DataContainerCodecContext<?, ?> key)
+ throws Exception {
+ return new BindingNormalizedNodeCache(AbstractBindingNormalizedNodeCacheHolder.this, key);
+ }
+
+ });
+
+ protected AbstractBindingNormalizedNodeCacheHolder(@Nonnull final Set<Class<? extends TreeNode>> cacheSpec) {
+ cachedValues = Preconditions.checkNotNull(cacheSpec);
+ }
+
+ public BindingNormalizedNodeCache getCachingSerializer(final DataContainerCodecContext<?, ?> childCtx) {
+ if (isCached(childCtx.getBindingClass())) {
+ return caches.getUnchecked(childCtx);
+ }
+ return null;
+ }
+
+ /**
+ * Check if specific type is cached.
+ *
+ * @param type
+ * - type for check
+ * @return true if type is cached, false otherwise
+ */
+ public boolean isCached(final Class<? extends TreeNode> type) {
+ return cachedValues.contains(type);
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.javav2.dom.codec.impl.cache;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Preconditions;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import javax.annotation.Nonnull;
+import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.context.base.DataContainerCodecContext;
+import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.serializer.CachingNormalizedNodeSerializer;
+import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+/**
+ * Cached NormalizedNode representation of TreeNode.
+ */
+@Beta
+public class BindingNormalizedNodeCache extends CacheLoader<TreeNode, NormalizedNode<?, ?>> {
+
+ @SuppressWarnings("rawtypes")
+ private final DataContainerCodecContext subtreeRoot;
+ private final AbstractBindingNormalizedNodeCacheHolder cacheHolder;
+ private final LoadingCache<TreeNode, NormalizedNode<?, ?>> cache =
+ CacheBuilder.newBuilder().weakValues().build(this);
+
+ public BindingNormalizedNodeCache(@Nonnull final AbstractBindingNormalizedNodeCacheHolder cacheHolder,
+ @Nonnull final DataContainerCodecContext<?, ?> subtreeRoot) {
+ this.cacheHolder = Preconditions.checkNotNull(cacheHolder, "cacheHolder");
+ this.subtreeRoot = Preconditions.checkNotNull(subtreeRoot, "subtreeRoot");
+ }
+
+ @Override
+ public NormalizedNode<?, ?> load(@Nonnull final TreeNode key) throws Exception {
+ return CachingNormalizedNodeSerializer.serializeUsingStreamWriter(cacheHolder, subtreeRoot, key);
+ }
+
+ /**
+ * Returns cached NormalizedNode representation of TreeNode.
+ *
+ * If representation is not cached, serializes TreeNode and updates cache
+ * with representation.
+ *
+ * @param obj
+ * - binding object to be deserialized
+ * @return NormalizedNode representation of binding object
+ */
+ public NormalizedNode<?, ?> get(final TreeNode obj) {
+ return cache.getUnchecked(obj);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.javav2.dom.codec.impl.cache;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Preconditions;
+import java.util.Set;
+import javax.annotation.Nonnull;
+import org.opendaylight.mdsal.binding.javav2.dom.codec.api.codecs.BindingNormalizedNodeCachingCodec;
+import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.context.base.DataContainerCodecContext;
+import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.serializer.CachingNormalizedNodeSerializer;
+import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+/**
+ * Caching codec.
+ *
+ * @param <D>
+ * - type of tree node
+ */
+@Beta
+public class CachingNormalizedNodeCodec<D extends TreeNode> extends AbstractBindingNormalizedNodeCacheHolder
+ implements BindingNormalizedNodeCachingCodec<D> {
+
+ private final DataContainerCodecContext<D, ?> context;
+
+ public CachingNormalizedNodeCodec(final DataContainerCodecContext<D, ?> subtreeRoot,
+ final Set<Class<? extends TreeNode>> cacheSpec) {
+ super(cacheSpec);
+ this.context = Preconditions.checkNotNull(subtreeRoot);
+ }
+
+ @Nonnull
+ @Override
+ public D deserialize(@Nonnull final NormalizedNode<?, ?> data) {
+ return context.deserialize(data);
+ }
+
+ @Nonnull
+ @Override
+ public NormalizedNode<?, ?> serialize(@Nonnull final D data) {
+ return CachingNormalizedNodeSerializer.serialize(this, context, data);
+ }
+
+ @Override
+ public void close() {
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.javav2.dom.codec.impl.codecs;
+
+import com.google.common.annotations.Beta;
+import javax.annotation.Nonnull;
+import org.opendaylight.mdsal.binding.javav2.dom.codec.api.codecs.BindingNormalizedNodeCachingCodec;
+import org.opendaylight.mdsal.binding.javav2.dom.codec.api.codecs.BindingNormalizedNodeCodec;
+import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+/**
+ * Non caching codec.
+ *
+ * @param <D>
+ * - type of tree node
+ */
+@Beta
+public class NonCachingCodec<D extends TreeNode> implements BindingNormalizedNodeCachingCodec<D> {
+
+ private final BindingNormalizedNodeCodec<D> delegate;
+
+ public NonCachingCodec(final BindingNormalizedNodeCodec<D> delegate) {
+ this.delegate = delegate;
+ }
+
+ @Nonnull
+ @Override
+ public D deserialize(@Nonnull final NormalizedNode<?, ?> data) {
+ return delegate.deserialize(data);
+ }
+
+ @Nonnull
+ @Override
+ public NormalizedNode<?, ?> serialize(@Nonnull final D data) {
+ return delegate.serialize(data);
+ }
+
+ @Override
+ public void close() {
+ }
+
+}
import com.google.common.annotations.Beta;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableCollection;
+import com.google.common.collect.ImmutableSet;
import java.io.IOException;
import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.opendaylight.mdsal.binding.javav2.dom.codec.api.codecs.BindingNormalizedNodeCachingCodec;
import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.MissingSchemaException;
+import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.cache.CachingNormalizedNodeCodec;
+import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.codecs.NonCachingCodec;
import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.serializer.BindingToNormalizedStreamWriter;
import org.opendaylight.mdsal.binding.javav2.spec.base.TreeArgument;
import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode;
import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNormalizedNodeStreamWriter;
import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeResult;
-import sun.reflect.generics.reflectiveObjects.NotImplementedException;
@Beta
public abstract class DataContainerCodecContext<D extends TreeNode, T> extends NodeCodecContext<D> {
@Override
public BindingNormalizedNodeCachingCodec<D> createCachingCodec(
@Nonnull final ImmutableCollection<Class<? extends TreeNode>> cacheSpecifier) {
-
- //TODO: implement in cache-related patches to come
- throw new NotImplementedException();
+ if (cacheSpecifier.isEmpty()) {
+ return new NonCachingCodec<D>(this);
+ }
+ return new CachingNormalizedNodeCodec<D>(this, ImmutableSet.copyOf(cacheSpecifier));
}
BindingStreamEventWriter createWriter(final NormalizedNodeStreamWriter domWriter) {
--- /dev/null
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.javav2.dom.codec.impl.serializer;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Throwables;
+import java.io.IOException;
+import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.cache.AbstractBindingNormalizedNodeCacheHolder;
+import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.cache.BindingNormalizedNodeCache;
+import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.context.base.DataContainerCodecContext;
+import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode;
+import org.opendaylight.mdsal.binding.javav2.spec.runtime.BindingSerializer;
+import org.opendaylight.mdsal.binding.javav2.spec.runtime.BindingStreamEventWriter;
+import org.opendaylight.mdsal.binding.javav2.spec.runtime.TreeNodeSerializer;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeResult;
+
+/**
+ * Serializer of Binding objects to Normalized Node which uses
+ * {@link BindingNormalizedNodeCache} to cache already serialized values.
+ *
+ * This serializer implements {@link BindingStreamEventWriter} along with
+ * {@link BindingSerializer}.
+ *
+ * {@link BindingSerializer} interface is used by generated implementations of
+ * {@link TreeNodeSerializer} to provide Binding object for inspection and to
+ * prevent streaming of already serialized object.
+ */
+@Beta
+public final class CachingNormalizedNodeSerializer extends ForwardingBindingStreamEventWriter
+ implements BindingSerializer<Object, TreeNode> {
+
+ private final NormalizedNodeResult domResult;
+ private final NormalizedNodeWithAddChildWriter domWriter;
+ private final BindingToNormalizedStreamWriter delegate;
+ private final AbstractBindingNormalizedNodeCacheHolder cacheHolder;
+
+ private CachingNormalizedNodeSerializer(final AbstractBindingNormalizedNodeCacheHolder cacheHolder,
+ final DataContainerCodecContext<?, ?> subtreeRoot) {
+ this.cacheHolder = cacheHolder;
+ this.domResult = new NormalizedNodeResult();
+ this.domWriter = new NormalizedNodeWithAddChildWriter(domResult);
+ this.delegate = BindingToNormalizedStreamWriter.create(subtreeRoot, domWriter);
+ }
+
+ @Override
+ protected BindingStreamEventWriter delegate() {
+ return delegate;
+ }
+
+ private NormalizedNode<?, ?> build() {
+ return domResult.getResult();
+ }
+
+ /**
+ * Serializes input if it is cached, returns null otherwise.
+ *
+ * If input is cached it uses
+ * {@link NormalizedNodeWithAddChildWriter#addChild(NormalizedNode)} to
+ * provide already serialized value to underlying NormalizedNodeWriter in
+ * order to reuse value instead of creating new one using Normalized Node
+ * stream APIs.
+ *
+ * Note that this optional is serialization of child node invoked from
+ * {@link TreeNodeSerializer}, which may opt-out from streaming of data when
+ * non-null result is returned.
+ */
+ @Override
+ public NormalizedNode<?, ?> serialize(final TreeNode input) {
+ final BindingNormalizedNodeCache cachingSerializer = getCacheSerializer(input.getClass());
+ if (cachingSerializer != null) {
+ final NormalizedNode<?, ?> domData = cachingSerializer.get(input);
+ domWriter.addChild(domData);
+ return domData;
+ }
+ return null;
+ }
+
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ private BindingNormalizedNodeCache getCacheSerializer(final Class type) {
+ if (cacheHolder.isCached(type)) {
+ final DataContainerCodecContext<?, ?> currentCtx = (DataContainerCodecContext<?, ?>) delegate.current();
+ if (type.equals(currentCtx.getBindingClass())) {
+ return cacheHolder.getCachingSerializer(currentCtx);
+ }
+ return cacheHolder.getCachingSerializer(currentCtx.streamChild(type));
+ }
+ return null;
+ }
+
+ /**
+ * Serializes supplied data using stream writer with child cache enabled or
+ * using cache directly if cache is avalaible also for supplied Codec node.
+ *
+ * @param cacheHolder
+ * - Binding to Normalized Node Cache holder
+ * @param subtreeRoot
+ * - codec Node for provided data object
+ * @param data
+ * - data to be serialized
+ * @return Normalized Node representation of data
+ */
+ public static NormalizedNode<?, ?> serialize(final AbstractBindingNormalizedNodeCacheHolder cacheHolder,
+ final DataContainerCodecContext<?, ?> subtreeRoot, final TreeNode data) {
+ final BindingNormalizedNodeCache cache = cacheHolder.getCachingSerializer(subtreeRoot);
+ if (cache != null) {
+ return cache.get(data);
+ }
+ return serializeUsingStreamWriter(cacheHolder, subtreeRoot, data);
+ }
+
+ /**
+ * Serializes supplied data using stream writer with child cache enabled.
+ *
+ * @param cacheHolder
+ * - binding to Normalized Node Cache holder
+ * @param subtreeRoot
+ * - codec Node for provided data object
+ * @param data
+ * - data to be serialized
+ * @return Normalized Node representation of data
+ */
+ public static NormalizedNode<?, ?> serializeUsingStreamWriter(
+ final AbstractBindingNormalizedNodeCacheHolder cacheHolder,
+ final DataContainerCodecContext<?, ?> subtreeRoot, final TreeNode data) {
+ final CachingNormalizedNodeSerializer writer = new CachingNormalizedNodeSerializer(cacheHolder, subtreeRoot);
+ try {
+ subtreeRoot.eventStreamSerializer().serialize(data, writer);
+ return writer.build();
+ } catch (final IOException e) {
+ throw Throwables.propagate(e);
+ }
+ }
+}
\ No newline at end of file