5caf707ac387a2aac0aef313cef05b427b70c196
[netconf.git] / plugins / netconf-common-mdsal / src / main / java / org / opendaylight / netconf / common / mdsal / EmptyListXmlMetadataWriter.java
1 /*
2  * Copyright (c) 2021 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.netconf.common.mdsal;
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 javax.xml.stream.XMLStreamWriter;
18 import org.eclipse.jdt.annotation.NonNull;
19 import org.opendaylight.yangtools.rfc7952.data.api.NormalizedMetadata;
20 import org.opendaylight.yangtools.rfc7952.data.api.StreamWriterMetadataExtension;
21 import org.opendaylight.yangtools.yang.common.QName;
22 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
23 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
24 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
25 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
26 import org.opendaylight.yangtools.yang.data.api.schema.stream.ForwardingNormalizedNodeStreamWriter;
27 import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
28
29 /**
30  * This class extends capability of {@link EmptyListXmlWriter} delegate to write metadata
31  * using {@link StreamWriterMetadataExtension} the same way as
32  * {@link org.opendaylight.yangtools.rfc7952.data.util.NormalizedNodeStreamWriterMetadataDecorator}.
33  */
34 final class EmptyListXmlMetadataWriter extends ForwardingNormalizedNodeStreamWriter {
35     private final Deque<NormalizedMetadata> stack = new ArrayDeque<>();
36     private final EmptyListXmlWriter dataWriterDelegate;
37     private final StreamWriterMetadataExtension metaWriter;
38     private final NormalizedMetadata metadata;
39
40     private int absentDepth = 0;
41
42     EmptyListXmlMetadataWriter(final @NonNull NormalizedNodeStreamWriter writer,
43             final @NonNull XMLStreamWriter xmlStreamWriter, final @NonNull StreamWriterMetadataExtension metaWriter,
44             final @NonNull NormalizedMetadata metadata) {
45         dataWriterDelegate = new EmptyListXmlWriter(requireNonNull(writer), requireNonNull(xmlStreamWriter));
46         this.metaWriter = requireNonNull(metaWriter);
47         this.metadata = requireNonNull(metadata);
48     }
49
50     @Override
51     protected NormalizedNodeStreamWriter delegate() {
52         return dataWriterDelegate.delegate();
53     }
54
55     @Override
56     public void startLeafNode(final NodeIdentifier name) throws IOException {
57         dataWriterDelegate.startLeafNode(name);
58         enterMetadataNode(name);
59     }
60
61     @Override
62     public void startLeafSet(final NodeIdentifier name, final int childSizeHint) throws IOException {
63         dataWriterDelegate.startLeafSet(name, childSizeHint);
64         enterMetadataNode(name);
65     }
66
67     @Override
68     public void startOrderedLeafSet(final NodeIdentifier name, final int childSizeHint) throws IOException {
69         dataWriterDelegate.startOrderedLeafSet(name, childSizeHint);
70         enterMetadataNode(name);
71     }
72
73     @Override
74     public void startLeafSetEntryNode(final YangInstanceIdentifier.NodeWithValue<?> name) throws IOException {
75         dataWriterDelegate.startLeafSetEntryNode(name);
76         enterMetadataNode(name);
77     }
78
79     @Override
80     public void startContainerNode(final NodeIdentifier name, final int childSizeHint) throws IOException {
81         dataWriterDelegate.startContainerNode(name, childSizeHint);
82         enterMetadataNode(name);
83     }
84
85     @Override
86     public void startUnkeyedList(final NodeIdentifier name, final int childSizeHint) throws IOException {
87         dataWriterDelegate.startUnkeyedList(name, childSizeHint);
88         enterMetadataNode(name);
89     }
90
91     @Override
92     public void startUnkeyedListItem(final NodeIdentifier name, final int childSizeHint) throws IOException {
93         dataWriterDelegate.startUnkeyedListItem(name, childSizeHint);
94         enterMetadataNode(name);
95     }
96
97     @Override
98     public void startMapNode(final NodeIdentifier name, final int childSizeHint) throws IOException {
99         dataWriterDelegate.startMapNode(name, childSizeHint);
100         enterMetadataNode(name);
101     }
102
103     @Override
104     public void startMapEntryNode(final NodeIdentifierWithPredicates identifier, final int childSizeHint)
105             throws IOException {
106         dataWriterDelegate.startMapEntryNode(identifier, childSizeHint);
107         enterMetadataNode(identifier);
108     }
109
110     @Override
111     public void startOrderedMapNode(final NodeIdentifier name, final int childSizeHint) throws IOException {
112         dataWriterDelegate.startOrderedMapNode(name, childSizeHint);
113         enterMetadataNode(name);
114     }
115
116     @Override
117     public void startChoiceNode(final NodeIdentifier name, final int childSizeHint) throws IOException {
118         dataWriterDelegate.startChoiceNode(name, childSizeHint);
119         enterMetadataNode(name);
120     }
121
122     @Override
123     public void startAugmentationNode(final AugmentationIdentifier identifier) throws IOException {
124         dataWriterDelegate.startAugmentationNode(identifier);
125         enterMetadataNode(identifier);
126     }
127
128     @Override
129     public boolean startAnyxmlNode(final NodeIdentifier name, final Class<?> objectModel) throws IOException {
130         final boolean ret = dataWriterDelegate.startAnyxmlNode(name, objectModel);
131         if (ret) {
132             enterMetadataNode(name);
133         }
134         return ret;
135     }
136
137     @Override
138     public void endNode() throws IOException {
139         dataWriterDelegate.endNode();
140
141         if (absentDepth > 0) {
142             absentDepth--;
143         } else {
144             stack.pop();
145         }
146     }
147
148     private void enterMetadataNode(final YangInstanceIdentifier.PathArgument name) throws IOException {
149         if (absentDepth > 0) {
150             absentDepth++;
151             return;
152         }
153
154         final NormalizedMetadata current = stack.peek();
155         if (current != null) {
156             final NormalizedMetadata child = current.getChildren().get(name);
157             if (child != null) {
158                 enterChild(child);
159             } else {
160                 absentDepth = 1;
161             }
162         } else {
163             // Empty stack: enter first entry
164             enterChild(metadata);
165         }
166     }
167
168     private void enterChild(final NormalizedMetadata child) throws IOException {
169         final Map<QName, Object> annotations = child.getAnnotations();
170         if (!annotations.isEmpty()) {
171             metaWriter.metadata(ImmutableMap.copyOf(annotations));
172         }
173         stack.push(child);
174     }
175 }