Bug 7521: Convert byte[] to ShardManagerSnapshot in DatastoreSnapshot
[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 java.io.DataInput;
12 import java.io.DataOutput;
13 import java.io.IOException;
14 import java.util.ArrayList;
15 import java.util.Collection;
16 import java.util.Collections;
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.controller.cluster.datastore.node.utils.stream.NormalizedNodeInputStreamReader;
21 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
22 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
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,
52             final NormalizedNodeDataInput in) throws IOException {
53
54         final PathArgument identifier = in.readPathArgument();
55         final Collection<DataTreeCandidateNode> children = readChildren(in);
56         if (children.isEmpty()) {
57             LOG.debug("Modified node {} does not have any children, not instantiating it", identifier);
58             return null;
59         } else {
60             return ModifiedDataTreeCandidateNode.create(identifier, type, children);
61         }
62     }
63
64     private static Collection<DataTreeCandidateNode> readChildren(final NormalizedNodeDataInput in) throws IOException {
65         final int size = in.readInt();
66         if (size != 0) {
67             final Collection<DataTreeCandidateNode> ret = new ArrayList<>(size);
68             for (int i = 0; i < size; ++i) {
69                 final DataTreeCandidateNode child = readNode(in);
70                 if (child != null) {
71                     ret.add(child);
72                 }
73             }
74             return ret;
75         } else {
76             return Collections.emptyList();
77         }
78     }
79
80     private static DataTreeCandidateNode readNode(final NormalizedNodeDataInput in) throws IOException {
81         final byte type = in.readByte();
82         switch (type) {
83             case APPEARED:
84                 return readModifiedNode(ModificationType.APPEARED, in);
85             case DELETE:
86                 return DeletedDataTreeCandidateNode.create(in.readPathArgument());
87             case DISAPPEARED:
88                 return readModifiedNode(ModificationType.DISAPPEARED, in);
89             case SUBTREE_MODIFIED:
90                 return readModifiedNode(ModificationType.SUBTREE_MODIFIED, in);
91             case UNMODIFIED:
92                 return null;
93             case WRITE:
94                 return DataTreeCandidateNodes.fromNormalizedNode(in.readNormalizedNode());
95             default:
96                 throw new IllegalArgumentException("Unhandled node type " + type);
97         }
98     }
99
100     public static DataTreeCandidate readDataTreeCandidate(final DataInput in) throws IOException {
101         final NormalizedNodeDataInput reader = new NormalizedNodeInputStreamReader(in);
102         final YangInstanceIdentifier rootPath = reader.readYangInstanceIdentifier();
103         final byte type = reader.readByte();
104
105         final DataTreeCandidateNode rootNode;
106         switch (type) {
107             case APPEARED:
108                 rootNode = ModifiedDataTreeCandidateNode.create(ModificationType.APPEARED, readChildren(reader));
109                 break;
110             case DELETE:
111                 rootNode = DeletedDataTreeCandidateNode.create();
112                 break;
113             case DISAPPEARED:
114                 rootNode = ModifiedDataTreeCandidateNode.create(ModificationType.DISAPPEARED, readChildren(reader));
115                 break;
116             case SUBTREE_MODIFIED:
117                 rootNode = ModifiedDataTreeCandidateNode.create(ModificationType.SUBTREE_MODIFIED,
118                         readChildren(reader));
119                 break;
120             case WRITE:
121                 rootNode = DataTreeCandidateNodes.fromNormalizedNode(reader.readNormalizedNode());
122                 break;
123             case UNMODIFIED:
124                 rootNode = AbstractDataTreeCandidateNode.createUnmodified();
125                 break;
126             default:
127                 throw new IllegalArgumentException("Unhandled node type " + type);
128         }
129
130         return DataTreeCandidates.newDataTreeCandidate(rootPath, rootNode);
131     }
132
133
134     private static void writeChildren(final NormalizedNodeDataOutput out,
135             final Collection<DataTreeCandidateNode> children) throws IOException {
136         out.writeInt(children.size());
137         for (DataTreeCandidateNode child : children) {
138             writeNode(out, child);
139         }
140     }
141
142     private static void writeNode(final NormalizedNodeDataOutput out, final DataTreeCandidateNode node)
143             throws IOException {
144         switch (node.getModificationType()) {
145             case APPEARED:
146                 out.writeByte(APPEARED);
147                 out.writePathArgument(node.getIdentifier());
148                 writeChildren(out, node.getChildNodes());
149                 break;
150             case DELETE:
151                 out.writeByte(DELETE);
152                 out.writePathArgument(node.getIdentifier());
153                 break;
154             case DISAPPEARED:
155                 out.writeByte(DISAPPEARED);
156                 out.writePathArgument(node.getIdentifier());
157                 writeChildren(out, node.getChildNodes());
158                 break;
159             case SUBTREE_MODIFIED:
160                 out.writeByte(SUBTREE_MODIFIED);
161                 out.writePathArgument(node.getIdentifier());
162                 writeChildren(out, node.getChildNodes());
163                 break;
164             case WRITE:
165                 out.writeByte(WRITE);
166                 out.writeNormalizedNode(node.getDataAfter().get());
167                 break;
168             case UNMODIFIED:
169                 out.writeByte(UNMODIFIED);
170                 break;
171             default:
172                 throw new IllegalArgumentException("Unhandled node type " + node.getModificationType());
173         }
174     }
175
176     public static void writeDataTreeCandidate(final DataOutput out, DataTreeCandidate candidate) throws IOException {
177         try (NormalizedNodeDataOutput writer = NormalizedNodeInputOutput.newDataOutput(out)) {
178             writer.writeYangInstanceIdentifier(candidate.getRootPath());
179
180             final DataTreeCandidateNode node = candidate.getRootNode();
181             switch (node.getModificationType()) {
182                 case APPEARED:
183                     writer.writeByte(APPEARED);
184                     writeChildren(writer, node.getChildNodes());
185                     break;
186                 case DELETE:
187                     writer.writeByte(DELETE);
188                     break;
189                 case DISAPPEARED:
190                     writer.writeByte(DISAPPEARED);
191                     writeChildren(writer, node.getChildNodes());
192                     break;
193                 case SUBTREE_MODIFIED:
194                     writer.writeByte(SUBTREE_MODIFIED);
195                     writeChildren(writer, node.getChildNodes());
196                     break;
197                 case UNMODIFIED:
198                     writer.writeByte(UNMODIFIED);
199                     break;
200                 case WRITE:
201                     writer.writeByte(WRITE);
202                     writer.writeNormalizedNode(node.getDataAfter().get());
203                     break;
204                 default:
205                     throw new IllegalArgumentException("Unhandled node type " + node.getModificationType());
206             }
207         }
208     }
209 }