b765cabc7e418bd58f930e84788d446978f16d19
[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 DELETE:
108                 rootNode = DeletedDataTreeCandidateNode.create();
109                 break;
110             case SUBTREE_MODIFIED:
111                 rootNode = ModifiedDataTreeCandidateNode.create(readChildren(reader));
112                 break;
113             case WRITE:
114                 rootNode = DataTreeCandidateNodes.fromNormalizedNode(reader.readNormalizedNode());
115                 break;
116             default:
117                 throw new IllegalArgumentException("Unhandled node type " + type);
118         }
119
120         return DataTreeCandidates.newDataTreeCandidate(rootPath, rootNode);
121     }
122
123
124     private static void writeChildren(final NormalizedNodeDataOutput out,
125             final Collection<DataTreeCandidateNode> children) throws IOException {
126         out.writeInt(children.size());
127         for (DataTreeCandidateNode child : children) {
128             writeNode(out, child);
129         }
130     }
131
132     private static void writeNode(final NormalizedNodeDataOutput out, final DataTreeCandidateNode node)
133             throws IOException {
134         switch (node.getModificationType()) {
135             case APPEARED:
136                 out.writeByte(APPEARED);
137                 out.writePathArgument(node.getIdentifier());
138                 writeChildren(out, node.getChildNodes());
139                 break;
140             case DELETE:
141                 out.writeByte(DELETE);
142                 out.writePathArgument(node.getIdentifier());
143                 break;
144             case DISAPPEARED:
145                 out.writeByte(DISAPPEARED);
146                 out.writePathArgument(node.getIdentifier());
147                 writeChildren(out, node.getChildNodes());
148                 break;
149             case SUBTREE_MODIFIED:
150                 out.writeByte(SUBTREE_MODIFIED);
151                 out.writePathArgument(node.getIdentifier());
152                 writeChildren(out, node.getChildNodes());
153                 break;
154             case WRITE:
155                 out.writeByte(WRITE);
156                 out.writeNormalizedNode(node.getDataAfter().get());
157                 break;
158             case UNMODIFIED:
159                 out.writeByte(UNMODIFIED);
160                 break;
161             default:
162                 throw new IllegalArgumentException("Unhandled node type " + node.getModificationType());
163         }
164     }
165
166     public static void writeDataTreeCandidate(final DataOutput out, DataTreeCandidate candidate) throws IOException {
167         try (final NormalizedNodeDataOutput writer = NormalizedNodeInputOutput.newDataOutput(out)) {
168             writer.writeYangInstanceIdentifier(candidate.getRootPath());
169
170             final DataTreeCandidateNode node = candidate.getRootNode();
171             switch (node.getModificationType()) {
172                 case APPEARED:
173                     writer.writeByte(APPEARED);
174                     writeChildren(writer, node.getChildNodes());
175                     break;
176                 case DELETE:
177                     writer.writeByte(DELETE);
178                     break;
179                 case DISAPPEARED:
180                     writer.writeByte(DISAPPEARED);
181                     writeChildren(writer, node.getChildNodes());
182                     break;
183                 case SUBTREE_MODIFIED:
184                     writer.writeByte(SUBTREE_MODIFIED);
185                     writeChildren(writer, node.getChildNodes());
186                     break;
187                 case UNMODIFIED:
188                     writer.writeByte(UNMODIFIED);
189                     break;
190                 case WRITE:
191                     writer.writeByte(WRITE);
192                     writer.writeNormalizedNode(node.getDataAfter().get());
193                     break;
194                 default:
195                     throw new IllegalArgumentException("Unhandled node type " + node.getModificationType());
196             }
197         }
198     }
199 }