Remove Augmentation{Identifier,Node}
[yangtools.git] / data / yang-data-util / src / main / java / org / opendaylight / yangtools / yang / data / util / NormalizedNodeStreamWriterMetadataDecorator.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.yangtools.yang.data.util;
9
10 import static java.util.Objects.requireNonNull;
11
12 import com.google.common.collect.ImmutableMap;
13 import java.io.IOException;
14 import java.util.ArrayDeque;
15 import java.util.Deque;
16 import java.util.Map;
17 import org.opendaylight.yangtools.yang.common.QName;
18 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
19 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
20 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
21 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
22 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedMetadata;
23 import org.opendaylight.yangtools.yang.data.api.schema.stream.ForwardingNormalizedNodeStreamWriter;
24 import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
25
26 /**
27  * A simple decorator on top of a NormalizedNodeStreamWriter, which attaches NormalizedMetadata to the event stream,
28  * so that the metadata is emitted along with data.
29  */
30 final class NormalizedNodeStreamWriterMetadataDecorator extends ForwardingNormalizedNodeStreamWriter {
31     private final Deque<NormalizedMetadata> stack = new ArrayDeque<>();
32     private final NormalizedNodeStreamWriter writer;
33     private final MetadataExtension metaWriter;
34     private final NormalizedMetadata metadata;
35
36     private int absentDepth = 0;
37
38     NormalizedNodeStreamWriterMetadataDecorator(final NormalizedNodeStreamWriter writer,
39             final MetadataExtension metaWriter, final NormalizedMetadata metadata) {
40         this.writer = requireNonNull(writer);
41         this.metaWriter = requireNonNull(metaWriter);
42         this.metadata = requireNonNull(metadata);
43     }
44
45     @Override
46     protected NormalizedNodeStreamWriter delegate() {
47         return writer;
48     }
49
50     @Override
51     public void startLeafNode(final NodeIdentifier name) throws IOException {
52         super.startLeafNode(name);
53         enterMetadataNode(name);
54     }
55
56     @Override
57     public void startLeafSet(final NodeIdentifier name, final int childSizeHint) throws IOException {
58         super.startLeafSet(name, childSizeHint);
59         enterMetadataNode(name);
60     }
61
62     @Override
63     public void startOrderedLeafSet(final NodeIdentifier name, final int childSizeHint) throws IOException {
64         super.startOrderedLeafSet(name, childSizeHint);
65         enterMetadataNode(name);
66     }
67
68     @Override
69     public void startLeafSetEntryNode(final NodeWithValue<?> name) throws IOException {
70         super.startLeafSetEntryNode(name);
71         enterMetadataNode(name);
72     }
73
74     @Override
75     public void startContainerNode(final NodeIdentifier name, final int childSizeHint) throws IOException {
76         super.startContainerNode(name, childSizeHint);
77         enterMetadataNode(name);
78     }
79
80     @Override
81     public void startUnkeyedList(final NodeIdentifier name, final int childSizeHint) throws IOException {
82         super.startUnkeyedList(name, childSizeHint);
83         enterMetadataNode(name);
84     }
85
86     @Override
87     public void startUnkeyedListItem(final NodeIdentifier name, final int childSizeHint) throws IOException {
88         super.startUnkeyedListItem(name, childSizeHint);
89         enterMetadataNode(name);
90     }
91
92     @Override
93     public void startMapNode(final NodeIdentifier name, final int childSizeHint) throws IOException {
94         super.startMapNode(name, childSizeHint);
95         enterMetadataNode(name);
96     }
97
98     @Override
99     public void startMapEntryNode(final NodeIdentifierWithPredicates identifier, final int childSizeHint)
100             throws IOException {
101         super.startMapEntryNode(identifier, childSizeHint);
102         enterMetadataNode(identifier);
103     }
104
105     @Override
106     public void startOrderedMapNode(final NodeIdentifier name, final int childSizeHint) throws IOException {
107         super.startOrderedMapNode(name, childSizeHint);
108         enterMetadataNode(name);
109     }
110
111     @Override
112     public void startChoiceNode(final NodeIdentifier name, final int childSizeHint) throws IOException {
113         super.startChoiceNode(name, childSizeHint);
114         enterMetadataNode(name);
115     }
116
117     @Override
118     public boolean startAnyxmlNode(final NodeIdentifier name, final Class<?> objectModel) throws IOException {
119         final boolean ret = super.startAnyxmlNode(name, objectModel);
120         if (ret) {
121             enterMetadataNode(name);
122         }
123         return ret;
124     }
125
126     @Override
127     public void endNode() throws IOException {
128         super.endNode();
129
130         if (absentDepth > 0) {
131             absentDepth--;
132         } else {
133             stack.pop();
134         }
135     }
136
137     private void enterMetadataNode(final PathArgument name) throws IOException {
138         if (absentDepth > 0) {
139             absentDepth++;
140             return;
141         }
142
143         final NormalizedMetadata current = stack.peek();
144         if (current != null) {
145             final NormalizedMetadata child = current.getChildren().get(name);
146             if (child != null) {
147                 enterChild(child);
148             } else {
149                 absentDepth = 1;
150             }
151         } else {
152             // Empty stack: enter first entry
153             enterChild(metadata);
154         }
155     }
156
157     private void enterChild(final NormalizedMetadata child) throws IOException {
158         final Map<QName, Object> annotations = child.getAnnotations();
159         if (!annotations.isEmpty()) {
160             metaWriter.metadata(ImmutableMap.copyOf(annotations));
161         }
162         stack.push(child);
163     }
164 }