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.yangtools.yang.data.codec.binfmt;
10 import com.google.common.annotations.Beta;
11 import com.google.common.collect.ImmutableList;
12 import java.io.IOException;
13 import java.util.ArrayList;
14 import java.util.Collection;
15 import org.eclipse.jdt.annotation.NonNull;
16 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
17 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
18 import org.opendaylight.yangtools.yang.data.api.schema.stream.ReusableStreamReceiver;
19 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidate;
20 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidateNode;
21 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidateNodes;
22 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidates;
23 import org.opendaylight.yangtools.yang.data.api.schema.tree.ModificationType;
24 import org.opendaylight.yangtools.yang.data.impl.schema.ReusableImmutableNormalizedNodeStreamWriter;
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
29 * Utility serialization/deserialization for {@link DataTreeCandidate}. Note that this utility does not maintain
30 * before-image information across serialization.
32 * @author Robert Varga
35 public final class DataTreeCandidateInputOutput {
36 private static final Logger LOG = LoggerFactory.getLogger(DataTreeCandidateInputOutput.class);
37 private static final byte DELETE = 0;
38 private static final byte SUBTREE_MODIFIED = 1;
39 private static final byte UNMODIFIED = 2;
40 private static final byte WRITE = 3;
41 private static final byte APPEARED = 4;
42 private static final byte DISAPPEARED = 5;
44 private DataTreeCandidateInputOutput() {
48 public static @NonNull DataTreeCandidate readDataTreeCandidate(final NormalizedNodeDataInput in)
50 return readDataTreeCandidate(in, ReusableImmutableNormalizedNodeStreamWriter.create());
53 public static @NonNull DataTreeCandidate readDataTreeCandidate(final NormalizedNodeDataInput in,
54 final ReusableStreamReceiver receiver) throws IOException {
55 final YangInstanceIdentifier rootPath = in.readYangInstanceIdentifier();
56 final byte type = in.readByte();
58 final DataTreeCandidateNode rootNode;
61 rootNode = ModifiedDataTreeCandidateNode.create(ModificationType.APPEARED, readChildren(in, receiver));
64 rootNode = DeletedDataTreeCandidateNode.create();
67 rootNode = ModifiedDataTreeCandidateNode.create(ModificationType.DISAPPEARED,
68 readChildren(in, receiver));
70 case SUBTREE_MODIFIED:
71 rootNode = ModifiedDataTreeCandidateNode.create(ModificationType.SUBTREE_MODIFIED,
72 readChildren(in, receiver));
75 rootNode = DataTreeCandidateNodes.written(in.readNormalizedNode(receiver));
78 rootNode = UnmodifiedRootDataTreeCandidateNode.INSTANCE;
81 throw new IllegalArgumentException("Unhandled node type " + type);
84 return DataTreeCandidates.newDataTreeCandidate(rootPath, rootNode);
87 public static void writeDataTreeCandidate(final NormalizedNodeDataOutput out, final DataTreeCandidate candidate)
89 out.writeYangInstanceIdentifier(candidate.getRootPath());
91 final DataTreeCandidateNode node = candidate.getRootNode();
92 switch (node.getModificationType()) {
94 out.writeByte(APPEARED);
95 writeChildren(out, node.getChildNodes());
98 out.writeByte(DELETE);
101 out.writeByte(DISAPPEARED);
102 writeChildren(out, node.getChildNodes());
104 case SUBTREE_MODIFIED:
105 out.writeByte(SUBTREE_MODIFIED);
106 writeChildren(out, node.getChildNodes());
109 out.writeByte(UNMODIFIED);
112 out.writeByte(WRITE);
113 out.writeNormalizedNode(node.getDataAfter().get());
116 throwUnhandledNodeType(node);
120 private static DataTreeCandidateNode readModifiedNode(final ModificationType type, final NormalizedNodeDataInput in,
121 final ReusableStreamReceiver receiver) throws IOException {
122 final PathArgument identifier = in.readPathArgument();
123 final Collection<DataTreeCandidateNode> children = readChildren(in, receiver);
124 if (children.isEmpty()) {
125 LOG.debug("Modified node {} does not have any children, not instantiating it", identifier);
129 return ModifiedDataTreeCandidateNode.create(identifier, type, children);
132 private static Collection<DataTreeCandidateNode> readChildren(final NormalizedNodeDataInput in,
133 final ReusableStreamReceiver receiver) throws IOException {
134 final int size = in.readInt();
136 return ImmutableList.of();
139 final Collection<DataTreeCandidateNode> ret = new ArrayList<>(size);
140 for (int i = 0; i < size; ++i) {
141 final DataTreeCandidateNode child = readNode(in, receiver);
149 private static DataTreeCandidateNode readNode(final NormalizedNodeDataInput in,
150 final ReusableStreamReceiver receiver) throws IOException {
151 final byte type = in.readByte();
154 return readModifiedNode(ModificationType.APPEARED, in, receiver);
156 return DeletedDataTreeCandidateNode.create(in.readPathArgument());
158 return readModifiedNode(ModificationType.DISAPPEARED, in, receiver);
159 case SUBTREE_MODIFIED:
160 return readModifiedNode(ModificationType.SUBTREE_MODIFIED, in, receiver);
164 return DataTreeCandidateNodes.written(in.readNormalizedNode(receiver));
166 throw new IllegalArgumentException("Unhandled node type " + type);
170 private static void writeChildren(final NormalizedNodeDataOutput out,
171 final Collection<DataTreeCandidateNode> children) throws IOException {
172 out.writeInt(children.size());
173 for (DataTreeCandidateNode child : children) {
174 writeNode(out, child);
178 private static void writeNode(final NormalizedNodeDataOutput out, final DataTreeCandidateNode node)
180 switch (node.getModificationType()) {
182 out.writeByte(APPEARED);
183 out.writePathArgument(node.getIdentifier());
184 writeChildren(out, node.getChildNodes());
187 out.writeByte(DELETE);
188 out.writePathArgument(node.getIdentifier());
191 out.writeByte(DISAPPEARED);
192 out.writePathArgument(node.getIdentifier());
193 writeChildren(out, node.getChildNodes());
195 case SUBTREE_MODIFIED:
196 out.writeByte(SUBTREE_MODIFIED);
197 out.writePathArgument(node.getIdentifier());
198 writeChildren(out, node.getChildNodes());
201 out.writeByte(WRITE);
202 out.writeNormalizedNode(node.getDataAfter().get());
205 out.writeByte(UNMODIFIED);
208 throwUnhandledNodeType(node);
212 private static void throwUnhandledNodeType(final DataTreeCandidateNode node) {
213 throw new IllegalArgumentException("Unhandled node type " + node.getModificationType());