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