Use ReusableNormalizedNodeReceiver
[controller.git] / opendaylight / md-sal / sal-distributed-datastore / src / main / java / org / opendaylight / controller / cluster / datastore / persisted / DataTreeCandidateInputOutput.java
1 /*
2  * Copyright (c) 2016 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.controller.cluster.datastore.persisted;
9
10 import com.google.common.annotations.Beta;
11 import com.google.common.collect.ImmutableList;
12 import java.io.DataInput;
13 import java.io.DataOutput;
14 import java.io.IOException;
15 import java.util.ArrayList;
16 import java.util.Collection;
17 import org.opendaylight.controller.cluster.datastore.node.utils.stream.NormalizedNodeDataInput;
18 import org.opendaylight.controller.cluster.datastore.node.utils.stream.NormalizedNodeDataOutput;
19 import org.opendaylight.controller.cluster.datastore.node.utils.stream.NormalizedNodeInputOutput;
20 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
21 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
22 import org.opendaylight.yangtools.yang.data.api.schema.stream.ReusableStreamReceiver;
23 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidate;
24 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidateNode;
25 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidateNodes;
26 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidates;
27 import org.opendaylight.yangtools.yang.data.api.schema.tree.ModificationType;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30
31 /**
32  * Utility serialization/deserialization for {@link DataTreeCandidate}. Note that this utility does not maintain
33  * before-image information across serialization.
34  *
35  * @author Robert Varga
36  */
37 @Beta
38 public final class DataTreeCandidateInputOutput {
39     private static final Logger LOG = LoggerFactory.getLogger(DataTreeCandidateInputOutput.class);
40     private static final byte DELETE = 0;
41     private static final byte SUBTREE_MODIFIED = 1;
42     private static final byte UNMODIFIED = 2;
43     private static final byte WRITE = 3;
44     private static final byte APPEARED = 4;
45     private static final byte DISAPPEARED = 5;
46
47     private DataTreeCandidateInputOutput() {
48         throw new UnsupportedOperationException();
49     }
50
51     private static DataTreeCandidateNode readModifiedNode(final ModificationType type, final NormalizedNodeDataInput in,
52             final ReusableStreamReceiver receiver) throws IOException {
53         final PathArgument identifier = in.readPathArgument();
54         final Collection<DataTreeCandidateNode> children = readChildren(in, receiver);
55         if (children.isEmpty()) {
56             LOG.debug("Modified node {} does not have any children, not instantiating it", identifier);
57             return null;
58         }
59
60         return ModifiedDataTreeCandidateNode.create(identifier, type, children);
61     }
62
63     private static Collection<DataTreeCandidateNode> readChildren(final NormalizedNodeDataInput in,
64             final ReusableStreamReceiver receiver) throws IOException {
65         final int size = in.readInt();
66         if (size == 0) {
67             return ImmutableList.of();
68         }
69
70         final Collection<DataTreeCandidateNode> ret = new ArrayList<>(size);
71         for (int i = 0; i < size; ++i) {
72             final DataTreeCandidateNode child = readNode(in, receiver);
73             if (child != null) {
74                 ret.add(child);
75             }
76         }
77         return ret;
78     }
79
80     private static DataTreeCandidateNode readNode(final NormalizedNodeDataInput in,
81             final ReusableStreamReceiver receiver) throws IOException {
82         final byte type = in.readByte();
83         switch (type) {
84             case APPEARED:
85                 return readModifiedNode(ModificationType.APPEARED, in, receiver);
86             case DELETE:
87                 return DeletedDataTreeCandidateNode.create(in.readPathArgument());
88             case DISAPPEARED:
89                 return readModifiedNode(ModificationType.DISAPPEARED, in, receiver);
90             case SUBTREE_MODIFIED:
91                 return readModifiedNode(ModificationType.SUBTREE_MODIFIED, in, receiver);
92             case UNMODIFIED:
93                 return null;
94             case WRITE:
95                 return DataTreeCandidateNodes.written(in.readNormalizedNode(receiver));
96             default:
97                 throw new IllegalArgumentException("Unhandled node type " + type);
98         }
99     }
100
101     public static DataTreeCandidate readDataTreeCandidate(final DataInput in, final ReusableStreamReceiver receiver)
102             throws IOException {
103         final NormalizedNodeDataInput reader = NormalizedNodeInputOutput.newDataInput(in);
104         final YangInstanceIdentifier rootPath = reader.readYangInstanceIdentifier();
105         final byte type = reader.readByte();
106
107         final DataTreeCandidateNode rootNode;
108         switch (type) {
109             case APPEARED:
110                 rootNode = ModifiedDataTreeCandidateNode.create(ModificationType.APPEARED,
111                     readChildren(reader, receiver));
112                 break;
113             case DELETE:
114                 rootNode = DeletedDataTreeCandidateNode.create();
115                 break;
116             case DISAPPEARED:
117                 rootNode = ModifiedDataTreeCandidateNode.create(ModificationType.DISAPPEARED,
118                     readChildren(reader, receiver));
119                 break;
120             case SUBTREE_MODIFIED:
121                 rootNode = ModifiedDataTreeCandidateNode.create(ModificationType.SUBTREE_MODIFIED,
122                         readChildren(reader, receiver));
123                 break;
124             case WRITE:
125                 rootNode = DataTreeCandidateNodes.written(reader.readNormalizedNode(receiver));
126                 break;
127             case UNMODIFIED:
128                 rootNode = AbstractDataTreeCandidateNode.createUnmodified();
129                 break;
130             default:
131                 throw new IllegalArgumentException("Unhandled node type " + type);
132         }
133
134         return DataTreeCandidates.newDataTreeCandidate(rootPath, rootNode);
135     }
136
137     private static void writeChildren(final NormalizedNodeDataOutput out,
138             final Collection<DataTreeCandidateNode> children) throws IOException {
139         out.writeInt(children.size());
140         for (DataTreeCandidateNode child : children) {
141             writeNode(out, child);
142         }
143     }
144
145     private static void writeNode(final NormalizedNodeDataOutput out, final DataTreeCandidateNode node)
146             throws IOException {
147         switch (node.getModificationType()) {
148             case APPEARED:
149                 out.writeByte(APPEARED);
150                 out.writePathArgument(node.getIdentifier());
151                 writeChildren(out, node.getChildNodes());
152                 break;
153             case DELETE:
154                 out.writeByte(DELETE);
155                 out.writePathArgument(node.getIdentifier());
156                 break;
157             case DISAPPEARED:
158                 out.writeByte(DISAPPEARED);
159                 out.writePathArgument(node.getIdentifier());
160                 writeChildren(out, node.getChildNodes());
161                 break;
162             case SUBTREE_MODIFIED:
163                 out.writeByte(SUBTREE_MODIFIED);
164                 out.writePathArgument(node.getIdentifier());
165                 writeChildren(out, node.getChildNodes());
166                 break;
167             case WRITE:
168                 out.writeByte(WRITE);
169                 out.writeNormalizedNode(node.getDataAfter().get());
170                 break;
171             case UNMODIFIED:
172                 out.writeByte(UNMODIFIED);
173                 break;
174             default:
175                 throwUnhandledNodeType(node);
176         }
177     }
178
179     public static void writeDataTreeCandidate(final DataOutput out, final DataTreeCandidate candidate)
180             throws IOException {
181         try (NormalizedNodeDataOutput writer = NormalizedNodeInputOutput.newDataOutput(out,
182                 PayloadVersion.current().getStreamVersion())) {
183             writer.writeYangInstanceIdentifier(candidate.getRootPath());
184
185             final DataTreeCandidateNode node = candidate.getRootNode();
186             switch (node.getModificationType()) {
187                 case APPEARED:
188                     writer.writeByte(APPEARED);
189                     writeChildren(writer, node.getChildNodes());
190                     break;
191                 case DELETE:
192                     writer.writeByte(DELETE);
193                     break;
194                 case DISAPPEARED:
195                     writer.writeByte(DISAPPEARED);
196                     writeChildren(writer, node.getChildNodes());
197                     break;
198                 case SUBTREE_MODIFIED:
199                     writer.writeByte(SUBTREE_MODIFIED);
200                     writeChildren(writer, node.getChildNodes());
201                     break;
202                 case UNMODIFIED:
203                     writer.writeByte(UNMODIFIED);
204                     break;
205                 case WRITE:
206                     writer.writeByte(WRITE);
207                     writer.writeNormalizedNode(node.getDataAfter().get());
208                     break;
209                 default:
210                     throwUnhandledNodeType(node);
211             }
212         }
213     }
214
215     private static void throwUnhandledNodeType(final DataTreeCandidateNode node) {
216         throw new IllegalArgumentException("Unhandled node type " + node.getModificationType());
217     }
218 }