Bump persisted PayloadVersion
[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.tree.DataTreeCandidate;
23 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidateNode;
24 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidateNodes;
25 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidates;
26 import org.opendaylight.yangtools.yang.data.api.schema.tree.ModificationType;
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,
51             final NormalizedNodeDataInput in) throws IOException {
52
53         final PathArgument identifier = in.readPathArgument();
54         final Collection<DataTreeCandidateNode> children = readChildren(in);
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) 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);
72             if (child != null) {
73                 ret.add(child);
74             }
75         }
76         return ret;
77     }
78
79     private static DataTreeCandidateNode readNode(final NormalizedNodeDataInput in) throws IOException {
80         final byte type = in.readByte();
81         switch (type) {
82             case APPEARED:
83                 return readModifiedNode(ModificationType.APPEARED, in);
84             case DELETE:
85                 return DeletedDataTreeCandidateNode.create(in.readPathArgument());
86             case DISAPPEARED:
87                 return readModifiedNode(ModificationType.DISAPPEARED, in);
88             case SUBTREE_MODIFIED:
89                 return readModifiedNode(ModificationType.SUBTREE_MODIFIED, in);
90             case UNMODIFIED:
91                 return null;
92             case WRITE:
93                 return DataTreeCandidateNodes.written(in.readNormalizedNode());
94             default:
95                 throw new IllegalArgumentException("Unhandled node type " + type);
96         }
97     }
98
99     public static DataTreeCandidate readDataTreeCandidate(final DataInput in) throws IOException {
100         final NormalizedNodeDataInput reader = NormalizedNodeInputOutput.newDataInput(in);
101         final YangInstanceIdentifier rootPath = reader.readYangInstanceIdentifier();
102         final byte type = reader.readByte();
103
104         final DataTreeCandidateNode rootNode;
105         switch (type) {
106             case APPEARED:
107                 rootNode = ModifiedDataTreeCandidateNode.create(ModificationType.APPEARED, readChildren(reader));
108                 break;
109             case DELETE:
110                 rootNode = DeletedDataTreeCandidateNode.create();
111                 break;
112             case DISAPPEARED:
113                 rootNode = ModifiedDataTreeCandidateNode.create(ModificationType.DISAPPEARED, readChildren(reader));
114                 break;
115             case SUBTREE_MODIFIED:
116                 rootNode = ModifiedDataTreeCandidateNode.create(ModificationType.SUBTREE_MODIFIED,
117                         readChildren(reader));
118                 break;
119             case WRITE:
120                 rootNode = DataTreeCandidateNodes.written(reader.readNormalizedNode());
121                 break;
122             case UNMODIFIED:
123                 rootNode = AbstractDataTreeCandidateNode.createUnmodified();
124                 break;
125             default:
126                 throw new IllegalArgumentException("Unhandled node type " + type);
127         }
128
129         return DataTreeCandidates.newDataTreeCandidate(rootPath, rootNode);
130     }
131
132     private static void writeChildren(final NormalizedNodeDataOutput out,
133             final Collection<DataTreeCandidateNode> children) throws IOException {
134         out.writeInt(children.size());
135         for (DataTreeCandidateNode child : children) {
136             writeNode(out, child);
137         }
138     }
139
140     private static void writeNode(final NormalizedNodeDataOutput out, final DataTreeCandidateNode node)
141             throws IOException {
142         switch (node.getModificationType()) {
143             case APPEARED:
144                 out.writeByte(APPEARED);
145                 out.writePathArgument(node.getIdentifier());
146                 writeChildren(out, node.getChildNodes());
147                 break;
148             case DELETE:
149                 out.writeByte(DELETE);
150                 out.writePathArgument(node.getIdentifier());
151                 break;
152             case DISAPPEARED:
153                 out.writeByte(DISAPPEARED);
154                 out.writePathArgument(node.getIdentifier());
155                 writeChildren(out, node.getChildNodes());
156                 break;
157             case SUBTREE_MODIFIED:
158                 out.writeByte(SUBTREE_MODIFIED);
159                 out.writePathArgument(node.getIdentifier());
160                 writeChildren(out, node.getChildNodes());
161                 break;
162             case WRITE:
163                 out.writeByte(WRITE);
164                 out.writeNormalizedNode(node.getDataAfter().get());
165                 break;
166             case UNMODIFIED:
167                 out.writeByte(UNMODIFIED);
168                 break;
169             default:
170                 throwUnhandledNodeType(node);
171         }
172     }
173
174     public static void writeDataTreeCandidate(final DataOutput out, final DataTreeCandidate candidate)
175             throws IOException {
176         try (NormalizedNodeDataOutput writer = NormalizedNodeInputOutput.newDataOutput(out,
177                 PayloadVersion.current().getStreamVersion())) {
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                     throwUnhandledNodeType(node);
206             }
207         }
208     }
209
210     private static void throwUnhandledNodeType(final DataTreeCandidateNode node) {
211         throw new IllegalArgumentException("Unhandled node type " + node.getModificationType());
212     }
213 }