2 * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.controller.cluster.datastore.persisted;
10 import static java.util.Objects.requireNonNull;
12 import com.google.common.annotations.Beta;
13 import com.google.common.collect.ImmutableList;
14 import java.io.DataInput;
15 import java.io.DataOutput;
16 import java.io.IOException;
17 import java.util.ArrayList;
18 import java.util.Collection;
19 import org.eclipse.jdt.annotation.NonNullByDefault;
20 import org.opendaylight.yangtools.concepts.Immutable;
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.stream.ReusableStreamReceiver;
24 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidate;
25 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidateNode;
26 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidateNodes;
27 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidates;
28 import org.opendaylight.yangtools.yang.data.api.schema.tree.ModificationType;
29 import org.opendaylight.yangtools.yang.data.codec.binfmt.NormalizedNodeDataInput;
30 import org.opendaylight.yangtools.yang.data.codec.binfmt.NormalizedNodeDataOutput;
31 import org.opendaylight.yangtools.yang.data.codec.binfmt.NormalizedNodeStreamVersion;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
36 * Utility serialization/deserialization for {@link DataTreeCandidate}. Note that this utility does not maintain
37 * before-image information across serialization.
39 * @author Robert Varga
42 public final class DataTreeCandidateInputOutput {
43 private static final Logger LOG = LoggerFactory.getLogger(DataTreeCandidateInputOutput.class);
44 private static final byte DELETE = 0;
45 private static final byte SUBTREE_MODIFIED = 1;
46 private static final byte UNMODIFIED = 2;
47 private static final byte WRITE = 3;
48 private static final byte APPEARED = 4;
49 private static final byte DISAPPEARED = 5;
51 private DataTreeCandidateInputOutput() {
52 throw new UnsupportedOperationException();
55 private static DataTreeCandidateNode readModifiedNode(final ModificationType type, final NormalizedNodeDataInput in,
56 final ReusableStreamReceiver receiver) throws IOException {
57 final PathArgument identifier = in.readPathArgument();
58 final Collection<DataTreeCandidateNode> children = readChildren(in, receiver);
59 if (children.isEmpty()) {
60 LOG.debug("Modified node {} does not have any children, not instantiating it", identifier);
64 return ModifiedDataTreeCandidateNode.create(identifier, type, children);
67 private static Collection<DataTreeCandidateNode> readChildren(final NormalizedNodeDataInput in,
68 final ReusableStreamReceiver receiver) throws IOException {
69 final int size = in.readInt();
71 return ImmutableList.of();
74 final Collection<DataTreeCandidateNode> ret = new ArrayList<>(size);
75 for (int i = 0; i < size; ++i) {
76 final DataTreeCandidateNode child = readNode(in, receiver);
84 private static DataTreeCandidateNode readNode(final NormalizedNodeDataInput in,
85 final ReusableStreamReceiver receiver) throws IOException {
86 final byte type = in.readByte();
89 return readModifiedNode(ModificationType.APPEARED, in, receiver);
91 return DeletedDataTreeCandidateNode.create(in.readPathArgument());
93 return readModifiedNode(ModificationType.DISAPPEARED, in, receiver);
94 case SUBTREE_MODIFIED:
95 return readModifiedNode(ModificationType.SUBTREE_MODIFIED, in, receiver);
99 return DataTreeCandidateNodes.written(in.readNormalizedNode(receiver));
101 throw new IllegalArgumentException("Unhandled node type " + type);
106 public static final class DataTreeCandidateWithVersion implements Immutable {
107 private final DataTreeCandidate candidate;
108 private final NormalizedNodeStreamVersion version;
110 public DataTreeCandidateWithVersion(final DataTreeCandidate candidate,
111 final NormalizedNodeStreamVersion version) {
112 this.candidate = requireNonNull(candidate);
113 this.version = requireNonNull(version);
116 public DataTreeCandidate getCandidate() {
120 public NormalizedNodeStreamVersion getVersion() {
125 public static DataTreeCandidateWithVersion readDataTreeCandidate(final DataInput in,
126 final ReusableStreamReceiver receiver) throws IOException {
127 final NormalizedNodeDataInput reader = NormalizedNodeDataInput.newDataInput(in);
128 final YangInstanceIdentifier rootPath = reader.readYangInstanceIdentifier();
129 final byte type = reader.readByte();
131 final DataTreeCandidateNode rootNode;
134 rootNode = ModifiedDataTreeCandidateNode.create(ModificationType.APPEARED,
135 readChildren(reader, receiver));
138 rootNode = DeletedDataTreeCandidateNode.create();
141 rootNode = ModifiedDataTreeCandidateNode.create(ModificationType.DISAPPEARED,
142 readChildren(reader, receiver));
144 case SUBTREE_MODIFIED:
145 rootNode = ModifiedDataTreeCandidateNode.create(ModificationType.SUBTREE_MODIFIED,
146 readChildren(reader, receiver));
149 rootNode = DataTreeCandidateNodes.written(reader.readNormalizedNode(receiver));
152 rootNode = AbstractDataTreeCandidateNode.createUnmodified();
155 throw new IllegalArgumentException("Unhandled node type " + type);
158 return new DataTreeCandidateWithVersion(DataTreeCandidates.newDataTreeCandidate(rootPath, rootNode),
159 reader.getVersion());
162 private static void writeChildren(final NormalizedNodeDataOutput out,
163 final Collection<DataTreeCandidateNode> children) throws IOException {
164 out.writeInt(children.size());
165 for (DataTreeCandidateNode child : children) {
166 writeNode(out, child);
170 private static void writeNode(final NormalizedNodeDataOutput out, final DataTreeCandidateNode node)
172 switch (node.getModificationType()) {
174 out.writeByte(APPEARED);
175 out.writePathArgument(node.getIdentifier());
176 writeChildren(out, node.getChildNodes());
179 out.writeByte(DELETE);
180 out.writePathArgument(node.getIdentifier());
183 out.writeByte(DISAPPEARED);
184 out.writePathArgument(node.getIdentifier());
185 writeChildren(out, node.getChildNodes());
187 case SUBTREE_MODIFIED:
188 out.writeByte(SUBTREE_MODIFIED);
189 out.writePathArgument(node.getIdentifier());
190 writeChildren(out, node.getChildNodes());
193 out.writeByte(WRITE);
194 out.writeNormalizedNode(node.getDataAfter().get());
197 out.writeByte(UNMODIFIED);
200 throwUnhandledNodeType(node);
204 public static void writeDataTreeCandidate(final DataOutput out, final DataTreeCandidate candidate)
206 try (NormalizedNodeDataOutput writer = PayloadVersion.current().getStreamVersion().newDataOutput(out)) {
207 writer.writeYangInstanceIdentifier(candidate.getRootPath());
209 final DataTreeCandidateNode node = candidate.getRootNode();
210 switch (node.getModificationType()) {
212 writer.writeByte(APPEARED);
213 writeChildren(writer, node.getChildNodes());
216 writer.writeByte(DELETE);
219 writer.writeByte(DISAPPEARED);
220 writeChildren(writer, node.getChildNodes());
222 case SUBTREE_MODIFIED:
223 writer.writeByte(SUBTREE_MODIFIED);
224 writeChildren(writer, node.getChildNodes());
227 writer.writeByte(UNMODIFIED);
230 writer.writeByte(WRITE);
231 writer.writeNormalizedNode(node.getDataAfter().get());
234 throwUnhandledNodeType(node);
239 private static void throwUnhandledNodeType(final DataTreeCandidateNode node) {
240 throw new IllegalArgumentException("Unhandled node type " + node.getModificationType());