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