2 * Copyright (c) 2019 PANTHEON.tech, s.r.o. 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 static com.google.common.base.Verify.verify;
12 import java.io.DataInput;
13 import java.io.IOException;
14 import java.util.ArrayList;
15 import java.util.List;
16 import org.opendaylight.yangtools.yang.common.QName;
17 import org.opendaylight.yangtools.yang.common.QNameModule;
18 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
19 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
22 * Neon SR2 specialization of AbstractLithiumDataInput. Unlike its Lithium counterpart, this format uses coding for
23 * QNameModules, QNames, NodeIdentifiers and AugmentationIdentifiers, thus reducing stream duplication.
25 final class NeonSR2NormalizedNodeInputStreamReader extends AbstractLithiumDataInput {
26 private final ArrayList<NodeIdentifier> codedNodeIdentifiers = new ArrayList<>();
27 private final List<AugmentationIdentifier> codedAugments = new ArrayList<>();
28 private final List<QNameModule> codedModules = new ArrayList<>();
29 private final List<QName> codedQNames = new ArrayList<>();
31 NeonSR2NormalizedNodeInputStreamReader(final DataInput input) {
36 public NormalizedNodeStreamVersion getVersion() {
37 return NormalizedNodeStreamVersion.NEON_SR2;
41 public QName readQName() throws IOException {
42 final byte valueType = readByte();
44 case NeonSR2Tokens.IS_QNAME_CODE:
45 return codedQName(readInt());
46 case NeonSR2Tokens.IS_QNAME_VALUE:
49 throw new IOException("Unhandled QName value type " + valueType);
54 AugmentationIdentifier readAugmentationIdentifier() throws IOException {
55 final byte valueType = readByte();
57 case NeonSR2Tokens.IS_AUGMENT_CODE:
58 return codedAugmentId(readInt());
59 case NeonSR2Tokens.IS_AUGMENT_VALUE:
60 return rawAugmentId();
62 throw new IOException("Unhandled QName value type " + valueType);
67 NodeIdentifier readNodeIdentifier() throws IOException {
68 // NodeIdentifier rides on top of QName, with this method really saying 'interpret next QName as NodeIdentifier'
69 // to do that we inter-mingle with readQName()
70 final byte valueType = readByte();
72 case NeonSR2Tokens.IS_QNAME_CODE:
73 return codedNodeIdentifier(readInt());
74 case NeonSR2Tokens.IS_QNAME_VALUE:
75 return rawNodeIdentifier();
77 throw new IOException("Unhandled QName value type " + valueType);
81 private QNameModule readModule() throws IOException {
82 final byte valueType = readByte();
84 case NeonSR2Tokens.IS_MODULE_CODE:
85 return codedModule(readInt());
86 case NeonSR2Tokens.IS_MODULE_VALUE:
89 throw new IOException("Unhandled QName value type " + valueType);
93 private NodeIdentifier codedNodeIdentifier(final int code) throws IOException {
94 final NodeIdentifier existing = codedNodeIdentifiers.size() > code ? codedNodeIdentifiers.get(code) : null;
95 return existing != null ? existing : storeNodeIdentifier(code, codedQName(code));
98 private NodeIdentifier rawNodeIdentifier() throws IOException {
99 // Capture size before it incremented
100 final int code = codedQNames.size();
101 return storeNodeIdentifier(code, rawQName());
104 private NodeIdentifier storeNodeIdentifier(final int code, final QName qname) {
105 final NodeIdentifier ret = NodeIdentifier.create(qname);
106 final int size = codedNodeIdentifiers.size();
110 codedNodeIdentifiers.ensureCapacity(code + 1);
111 for (int i = size; i < code; ++i) {
112 codedNodeIdentifiers.add(null);
115 codedNodeIdentifiers.add(ret);
117 final NodeIdentifier check = codedNodeIdentifiers.set(code, ret);
118 verify(check == null);
124 private QName codedQName(final int code) throws IOException {
126 return codedQNames.get(code);
127 } catch (IndexOutOfBoundsException e) {
128 throw new IOException("QName code " + code + " was not found", e);
132 private QName rawQName() throws IOException {
133 final String localName = readCodedString();
134 final QNameModule module = readModule();
135 final QName qname = QNameFactory.create(module, localName);
136 codedQNames.add(qname);
140 private AugmentationIdentifier codedAugmentId(final int code) throws IOException {
142 return codedAugments.get(code);
143 } catch (IndexOutOfBoundsException e) {
144 throw new IOException("QName set code " + code + " was not found", e);
148 private AugmentationIdentifier rawAugmentId() throws IOException {
149 final AugmentationIdentifier aid = defaultReadAugmentationIdentifier();
150 codedAugments.add(aid);
154 private QNameModule codedModule(final int code) throws IOException {
156 return codedModules.get(code);
157 } catch (IndexOutOfBoundsException e) {
158 throw new IOException("Module code " + code + " was not found", e);
162 private QNameModule rawModule() throws IOException {
163 final String namespace = readCodedString();
164 final String revision = readCodedString();
165 final QNameModule mod = QNameFactory.createModule(namespace, revision);
166 codedModules.add(mod);