Remove JournalWriter.getLastEntry()
[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 static java.util.Objects.requireNonNull;
11
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;
34
35 /**
36  * Utility serialization/deserialization for {@link DataTreeCandidate}. Note that this utility does not maintain
37  * before-image information across serialization.
38  *
39  * @author Robert Varga
40  */
41 @Beta
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;
50
51     private DataTreeCandidateInputOutput() {
52         throw new UnsupportedOperationException();
53     }
54
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);
61             return null;
62         }
63
64         return ModifiedDataTreeCandidateNode.create(identifier, type, children);
65     }
66
67     private static Collection<DataTreeCandidateNode> readChildren(final NormalizedNodeDataInput in,
68             final ReusableStreamReceiver receiver) throws IOException {
69         final int size = in.readInt();
70         if (size == 0) {
71             return ImmutableList.of();
72         }
73
74         final Collection<DataTreeCandidateNode> ret = new ArrayList<>(size);
75         for (int i = 0; i < size; ++i) {
76             final DataTreeCandidateNode child = readNode(in, receiver);
77             if (child != null) {
78                 ret.add(child);
79             }
80         }
81         return ret;
82     }
83
84     private static DataTreeCandidateNode readNode(final NormalizedNodeDataInput in,
85             final ReusableStreamReceiver receiver) throws IOException {
86         final byte type = in.readByte();
87         switch (type) {
88             case APPEARED:
89                 return readModifiedNode(ModificationType.APPEARED, in, receiver);
90             case DELETE:
91                 return DeletedDataTreeCandidateNode.create(in.readPathArgument());
92             case DISAPPEARED:
93                 return readModifiedNode(ModificationType.DISAPPEARED, in, receiver);
94             case SUBTREE_MODIFIED:
95                 return readModifiedNode(ModificationType.SUBTREE_MODIFIED, in, receiver);
96             case UNMODIFIED:
97                 return null;
98             case WRITE:
99                 return DataTreeCandidateNodes.written(in.readNormalizedNode(receiver));
100             default:
101                 throw new IllegalArgumentException("Unhandled node type " + type);
102         }
103     }
104
105     @NonNullByDefault
106     public static final class DataTreeCandidateWithVersion implements Immutable {
107         private final DataTreeCandidate candidate;
108         private final NormalizedNodeStreamVersion version;
109
110         public DataTreeCandidateWithVersion(final DataTreeCandidate candidate,
111                 final NormalizedNodeStreamVersion version) {
112             this.candidate = requireNonNull(candidate);
113             this.version = requireNonNull(version);
114         }
115
116         public DataTreeCandidate getCandidate() {
117             return candidate;
118         }
119
120         public NormalizedNodeStreamVersion getVersion() {
121             return version;
122         }
123     }
124
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();
130
131         final DataTreeCandidateNode rootNode;
132         switch (type) {
133             case APPEARED:
134                 rootNode = ModifiedDataTreeCandidateNode.create(ModificationType.APPEARED,
135                     readChildren(reader, receiver));
136                 break;
137             case DELETE:
138                 rootNode = DeletedDataTreeCandidateNode.create();
139                 break;
140             case DISAPPEARED:
141                 rootNode = ModifiedDataTreeCandidateNode.create(ModificationType.DISAPPEARED,
142                     readChildren(reader, receiver));
143                 break;
144             case SUBTREE_MODIFIED:
145                 rootNode = ModifiedDataTreeCandidateNode.create(ModificationType.SUBTREE_MODIFIED,
146                         readChildren(reader, receiver));
147                 break;
148             case WRITE:
149                 rootNode = DataTreeCandidateNodes.written(reader.readNormalizedNode(receiver));
150                 break;
151             case UNMODIFIED:
152                 rootNode = AbstractDataTreeCandidateNode.createUnmodified();
153                 break;
154             default:
155                 throw new IllegalArgumentException("Unhandled node type " + type);
156         }
157
158         return new DataTreeCandidateWithVersion(DataTreeCandidates.newDataTreeCandidate(rootPath, rootNode),
159             reader.getVersion());
160     }
161
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);
167         }
168     }
169
170     private static void writeNode(final NormalizedNodeDataOutput out, final DataTreeCandidateNode node)
171             throws IOException {
172         switch (node.getModificationType()) {
173             case APPEARED:
174                 out.writeByte(APPEARED);
175                 out.writePathArgument(node.getIdentifier());
176                 writeChildren(out, node.getChildNodes());
177                 break;
178             case DELETE:
179                 out.writeByte(DELETE);
180                 out.writePathArgument(node.getIdentifier());
181                 break;
182             case DISAPPEARED:
183                 out.writeByte(DISAPPEARED);
184                 out.writePathArgument(node.getIdentifier());
185                 writeChildren(out, node.getChildNodes());
186                 break;
187             case SUBTREE_MODIFIED:
188                 out.writeByte(SUBTREE_MODIFIED);
189                 out.writePathArgument(node.getIdentifier());
190                 writeChildren(out, node.getChildNodes());
191                 break;
192             case WRITE:
193                 out.writeByte(WRITE);
194                 out.writeNormalizedNode(node.getDataAfter().get());
195                 break;
196             case UNMODIFIED:
197                 out.writeByte(UNMODIFIED);
198                 break;
199             default:
200                 throwUnhandledNodeType(node);
201         }
202     }
203
204     public static void writeDataTreeCandidate(final DataOutput out, final DataTreeCandidate candidate)
205             throws IOException {
206         try (NormalizedNodeDataOutput writer = PayloadVersion.current().getStreamVersion().newDataOutput(out)) {
207             writer.writeYangInstanceIdentifier(candidate.getRootPath());
208
209             final DataTreeCandidateNode node = candidate.getRootNode();
210             switch (node.getModificationType()) {
211                 case APPEARED:
212                     writer.writeByte(APPEARED);
213                     writeChildren(writer, node.getChildNodes());
214                     break;
215                 case DELETE:
216                     writer.writeByte(DELETE);
217                     break;
218                 case DISAPPEARED:
219                     writer.writeByte(DISAPPEARED);
220                     writeChildren(writer, node.getChildNodes());
221                     break;
222                 case SUBTREE_MODIFIED:
223                     writer.writeByte(SUBTREE_MODIFIED);
224                     writeChildren(writer, node.getChildNodes());
225                     break;
226                 case UNMODIFIED:
227                     writer.writeByte(UNMODIFIED);
228                     break;
229                 case WRITE:
230                     writer.writeByte(WRITE);
231                     writer.writeNormalizedNode(node.getDataAfter().get());
232                     break;
233                 default:
234                     throwUnhandledNodeType(node);
235             }
236         }
237     }
238
239     private static void throwUnhandledNodeType(final DataTreeCandidateNode node) {
240         throw new IllegalArgumentException("Unhandled node type " + node.getModificationType());
241     }
242 }