BUG-8004: handle implicit RPC input
[mdsal.git] / binding / mdsal-binding-dom-codec / src / main / java / org / opendaylight / yangtools / binding / data / codec / impl / CachingNormalizedNodeSerializer.java
1 /*
2  * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.yangtools.binding.data.codec.impl;
9
10 import com.google.common.base.Throwables;
11 import java.io.IOException;
12 import org.opendaylight.yangtools.yang.binding.BindingSerializer;
13 import org.opendaylight.yangtools.yang.binding.BindingStreamEventWriter;
14 import org.opendaylight.yangtools.yang.binding.DataObject;
15 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
16 import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeResult;
17
18 /**
19  * Serializer of Binding objects to Normalized Node which uses {@link BindingNormalizedNodeCache} to
20  * cache already serialized values.
21  *
22  * This serializer implements {@link BindingStreamEventWriter} along with {@link BindingSerializer}.
23  *
24  * {@link BindingSerializer} interface is used by generated implementations of
25  * {@link org.opendaylight.yangtools.yang.binding.DataObjectSerializer} to provide Binding object
26  * for inspection and to prevent streaming of already serialized object.
27  *
28  */
29 final class CachingNormalizedNodeSerializer extends ForwardingBindingStreamEventWriter implements
30         BindingSerializer<Object, DataObject> {
31
32     private final NormalizedNodeResult domResult;
33     private final NormalizedNodeWriterWithAddChild domWriter;
34     private final BindingToNormalizedStreamWriter delegate;
35     private final AbstractBindingNormalizedNodeCacheHolder cacheHolder;
36
37     CachingNormalizedNodeSerializer(final AbstractBindingNormalizedNodeCacheHolder cacheHolder,
38             final DataContainerCodecContext<?, ?> subtreeRoot) {
39         this.cacheHolder = cacheHolder;
40         this.domResult = new NormalizedNodeResult();
41         this.domWriter = new NormalizedNodeWriterWithAddChild(domResult);
42         this.delegate = BindingToNormalizedStreamWriter.create(subtreeRoot, domWriter);
43     }
44
45     @Override
46     protected BindingStreamEventWriter delegate() {
47         return delegate;
48     }
49
50     NormalizedNode<?, ?> build() {
51         return domResult.getResult();
52     }
53
54     /**
55      * Serializes input if it is cached, returns null otherwise.
56      *
57      * If input is cached it uses {@link NormalizedNodeWriterWithAddChild#addChild(NormalizedNode)}
58      * to provide already serialized value to underlying NormalizedNodeWriter in order to reuse
59      * value instead of creating new one using Normalized Node stream APIs.
60      *
61      * Note that this optional is serialization of child node invoked from
62      * {@link org.opendaylight.yangtools.yang.binding.DataObjectSerializer}, which may opt-out from
63      * streaming of data when non-null result is returned.
64      */
65     @Override
66     public NormalizedNode<?, ?> serialize(final DataObject input) {
67         final BindingNormalizedNodeCache cachingSerializer = getCacheSerializer(input.getImplementedInterface());
68         if (cachingSerializer != null) {
69             final NormalizedNode<?, ?> domData = cachingSerializer.get(input);
70             domWriter.addChild(domData);
71             return domData;
72         }
73         return null;
74     }
75
76     @SuppressWarnings({"rawtypes", "unchecked"})
77     private BindingNormalizedNodeCache getCacheSerializer(final Class type) {
78         if (cacheHolder.isCached(type)) {
79             final DataContainerCodecContext<?, ?> currentCtx = (DataContainerCodecContext<?, ?>) delegate.current();
80             if (type.equals(currentCtx.getBindingClass())) {
81                 return cacheHolder.getCachingSerializer(currentCtx);
82             }
83             return cacheHolder.getCachingSerializer(currentCtx.streamChild(type));
84         }
85         return null;
86     }
87
88     /**
89      * Serializes supplied data using stream writer with child cache enabled or using cache directly
90      * if cache is avalaible also for supplied Codec node.
91      *
92      * @param cacheHolder Binding to Normalized Node Cache holder
93      * @param subtreeRoot Codec Node for provided data object
94      * @param data Data to be serialized
95      * @return Normalized Node representation of data.
96      */
97     static NormalizedNode<?, ?> serialize(final AbstractBindingNormalizedNodeCacheHolder cacheHolder,
98             final DataContainerCodecContext<?, ?> subtreeRoot, final DataObject data) {
99         final BindingNormalizedNodeCache cache = cacheHolder.getCachingSerializer(subtreeRoot);
100         if (cache != null) {
101             return cache.get(data);
102         }
103         return serializeUsingStreamWriter(cacheHolder, subtreeRoot, data);
104     }
105
106     /**
107      * Serializes supplied data using stream writer with child cache enabled.
108      *
109      * @param cacheHolder Binding to Normalized Node Cache holder
110      * @param subtreeRoot Codec Node for provided data object
111      * @param data Data to be serialized
112      * @return Normalized Node representation of data.
113      */
114     static NormalizedNode<?, ?> serializeUsingStreamWriter(final AbstractBindingNormalizedNodeCacheHolder cacheHolder,
115             final DataContainerCodecContext<?, ?> subtreeRoot, final DataObject data) {
116         final CachingNormalizedNodeSerializer writer = new CachingNormalizedNodeSerializer(cacheHolder, subtreeRoot);
117         try {
118             subtreeRoot.eventStreamSerializer().serialize(data, writer);
119             return writer.build();
120         } catch (final IOException e) {
121             throw Throwables.propagate(e);
122         }
123     }
124 }