Switch default output stream version
[controller.git] / opendaylight / md-sal / sal-clustering-commons / src / main / java / org / opendaylight / controller / cluster / datastore / node / utils / stream / SodiumNormalizedNodeInputStreamReader.java
1 /*
2  * Copyright (c) 2019 PANTHEON.tech, s.r.o. 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.node.utils.stream;
9
10 import static com.google.common.base.Verify.verify;
11
12 import java.io.DataInput;
13 import java.io.IOException;
14 import java.util.ArrayList;
15 import java.util.List;
16 import org.opendaylight.controller.cluster.datastore.node.utils.QNameFactory;
17 import org.opendaylight.yangtools.yang.common.QName;
18 import org.opendaylight.yangtools.yang.common.QNameModule;
19 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
20 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
21
22 final class SodiumNormalizedNodeInputStreamReader extends LithiumNormalizedNodeInputStreamReader {
23     private final ArrayList<NodeIdentifier> codedNodeIdentifiers = new ArrayList<>();
24     private final List<AugmentationIdentifier> codedAugments = new ArrayList<>();
25     private final List<QNameModule> codedModules = new ArrayList<>();
26     private final List<QName> codedQNames = new ArrayList<>();
27
28     SodiumNormalizedNodeInputStreamReader(final DataInput input) {
29         super(input);
30     }
31
32     @Override
33     public NormalizedNodeStreamVersion getVersion() throws IOException {
34         return NormalizedNodeStreamVersion.SODIUM;
35     }
36
37     @Override
38     public QName readQName() throws IOException {
39         final byte valueType = readByte();
40         switch (valueType) {
41             case TokenTypes.IS_QNAME_CODE:
42                 return codedQName(readInt());
43             case TokenTypes.IS_QNAME_VALUE:
44                 return rawQName();
45             default:
46                 throw new IOException("Unhandled QName value type " + valueType);
47         }
48     }
49
50     @Override
51     AugmentationIdentifier readAugmentationIdentifier() throws IOException {
52         final byte valueType = readByte();
53         switch (valueType) {
54             case TokenTypes.IS_AUGMENT_CODE:
55                 return codedAugmentId(readInt());
56             case TokenTypes.IS_AUGMENT_VALUE:
57                 return rawAugmentId();
58             default:
59                 throw new IOException("Unhandled QName value type " + valueType);
60         }
61     }
62
63     @Override
64     NodeIdentifier readNodeIdentifier() throws IOException {
65         // NodeIdentifier rides on top of QName, with this method really saying 'interpret next QName as NodeIdentifier'
66         // to do that we inter-mingle with readQName()
67         final byte valueType = readByte();
68         switch (valueType) {
69             case TokenTypes.IS_QNAME_CODE:
70                 return codedNodeIdentifier(readInt());
71             case TokenTypes.IS_QNAME_VALUE:
72                 return rawNodeIdentifier();
73             default:
74                 throw new IOException("Unhandled QName value type " + valueType);
75         }
76     }
77
78     private QNameModule readModule() throws IOException {
79         final byte valueType = readByte();
80         switch (valueType) {
81             case TokenTypes.IS_MODULE_CODE:
82                 return codedModule(readInt());
83             case TokenTypes.IS_MODULE_VALUE:
84                 return rawModule();
85             default:
86                 throw new IOException("Unhandled QName value type " + valueType);
87         }
88     }
89
90     private NodeIdentifier codedNodeIdentifier(final int code) throws IOException {
91         final NodeIdentifier existing = codedNodeIdentifiers.size() > code ? codedNodeIdentifiers.get(code) : null;
92         return existing != null ? existing : storeNodeIdentifier(code, codedQName(code));
93     }
94
95     private NodeIdentifier rawNodeIdentifier() throws IOException {
96         // Capture size before it incremented
97         final int code = codedQNames.size();
98         return storeNodeIdentifier(code, rawQName());
99     }
100
101     private NodeIdentifier storeNodeIdentifier(final int code, final QName qname) {
102         final NodeIdentifier ret = NodeIdentifier.create(qname);
103         final int size = codedNodeIdentifiers.size();
104
105         if (code >= size) {
106             // Null-fill others
107             codedNodeIdentifiers.ensureCapacity(code + 1);
108             for (int i = size; i < code; ++i) {
109                 codedNodeIdentifiers.add(null);
110             }
111
112             codedNodeIdentifiers.add(ret);
113         } else {
114             final NodeIdentifier check = codedNodeIdentifiers.set(code, ret);
115             verify(check == null);
116         }
117
118         return ret;
119     }
120
121     private QName codedQName(final int code) throws IOException {
122         try {
123             return codedQNames.get(code);
124         } catch (IndexOutOfBoundsException e) {
125             throw new IOException("QName code " + code + " was not found", e);
126         }
127     }
128
129     private QName rawQName() throws IOException {
130         final String localName = readCodedString();
131         final QNameModule module = readModule();
132         final QName qname = QNameFactory.create(module, localName);
133         codedQNames.add(qname);
134         return qname;
135     }
136
137     private AugmentationIdentifier codedAugmentId(final int code) throws IOException {
138         try {
139             return codedAugments.get(code);
140         } catch (IndexOutOfBoundsException e) {
141             throw new IOException("QName set code " + code + " was not found", e);
142         }
143     }
144
145     private AugmentationIdentifier rawAugmentId() throws IOException {
146         final AugmentationIdentifier aid = super.readAugmentationIdentifier();
147         codedAugments.add(aid);
148         return aid;
149     }
150
151     private QNameModule codedModule(final int code) throws IOException {
152         try {
153             return codedModules.get(code);
154         } catch (IndexOutOfBoundsException e) {
155             throw new IOException("Module code " + code + " was not found", e);
156         }
157     }
158
159     private QNameModule rawModule() throws IOException {
160         final String namespace = readCodedString();
161         final String revision = readCodedString();
162         final QNameModule mod = QNameFactory.createModule(namespace, revision);
163         codedModules.add(mod);
164         return mod;
165     }
166 }