2 * Copyright (c) 2016 Cisco Systems, Inc. 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.impl.schema;
10 import com.google.common.collect.ArrayListMultimap;
11 import java.io.IOException;
12 import java.util.Collection;
13 import java.util.List;
14 import java.util.Objects;
15 import org.opendaylight.yangtools.yang.common.QName;
16 import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
17 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
18 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
19 import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
20 import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeWriter;
21 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
22 import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
23 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
24 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
25 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
26 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
27 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
28 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
31 * This is an iterator over a {@link NormalizedNode}. Unlike {@link NormalizedNodeWriter},
32 * this iterates over elements in order as they are defined in .yang file.
34 public class SchemaOrderedNormalizedNodeWriter extends NormalizedNodeWriter {
36 private final SchemaContext schemaContext;
37 private final SchemaNode root;
38 private final NormalizedNodeStreamWriter writer;
40 private SchemaNode currentSchemaNode;
43 * Create a new writer backed by a {@link NormalizedNodeStreamWriter}.
44 * @param writer Back-end writer
45 * @param schemaContext Schema context
48 public SchemaOrderedNormalizedNodeWriter(final NormalizedNodeStreamWriter writer, final SchemaContext schemaContext, final SchemaPath path) {
51 this.schemaContext = schemaContext;
52 this.root = SchemaUtils.findParentSchemaOnPath(schemaContext, path);
56 public SchemaOrderedNormalizedNodeWriter write(final NormalizedNode<?, ?> node) throws IOException {
57 if (Objects.equals(root, schemaContext)) {
58 currentSchemaNode = schemaContext.getDataChildByName(node.getNodeType());
60 currentSchemaNode = root;
62 return write(node, currentSchemaNode);
67 * Iterate over the provided collection and emit write
68 * events to the encapsulated {@link NormalizedNodeStreamWriter}.
71 * @return NormalizedNodeWriter this
72 * @throws IOException when thrown from the backing writer.
74 public SchemaOrderedNormalizedNodeWriter write(final Collection<DataContainerChild<?,?>> nodes) throws IOException {
75 currentSchemaNode = root;
76 if (writeChildren(nodes, currentSchemaNode, false)) {
80 throw new IllegalStateException("It wasn't possible to serialize nodes " + nodes);
84 private SchemaOrderedNormalizedNodeWriter write(final NormalizedNode<?, ?> node, final SchemaNode dataSchemaNode) throws IOException {
86 //Set current schemaNode
87 try (SchemaNodeSetter sns = new SchemaNodeSetter(dataSchemaNode)) {
92 if (wasProcessedAsCompositeNode(node)) {
96 if (wasProcessAsSimpleNode(node)) {
101 throw new IllegalStateException("It wasn't possible to serialize node " + node);
104 private void write(final List<NormalizedNode<?, ?>> nodes, final SchemaNode dataSchemaNode) throws IOException {
105 for (NormalizedNode<?, ?> node : nodes) {
106 write(node, dataSchemaNode);
110 protected boolean writeChildren(final Iterable<? extends NormalizedNode<?, ?>> children) throws IOException {
111 return writeChildren(children, currentSchemaNode, true);
114 private boolean writeChildren(final Iterable<? extends NormalizedNode<?, ?>> children, final SchemaNode parentSchemaNode, boolean endParent) throws IOException {
115 //Augmentations cannot be gotten with node.getChild so create our own structure with augmentations resolved
116 ArrayListMultimap<QName, NormalizedNode<?, ?>> qNameToNodes = ArrayListMultimap.create();
117 for (NormalizedNode<?, ?> child : children) {
118 if (child instanceof AugmentationNode) {
119 qNameToNodes.putAll(resolveAugmentations(child));
121 qNameToNodes.put(child.getNodeType(), child);
125 if (parentSchemaNode instanceof DataNodeContainer) {
126 if (parentSchemaNode instanceof ListSchemaNode && qNameToNodes.containsKey(parentSchemaNode.getQName())) {
127 write(qNameToNodes.get(parentSchemaNode.getQName()), parentSchemaNode);
129 for (DataSchemaNode schemaNode : ((DataNodeContainer) parentSchemaNode).getChildNodes()) {
130 write(qNameToNodes.get(schemaNode.getQName()), schemaNode);
133 } else if(parentSchemaNode instanceof ChoiceSchemaNode) {
134 for (ChoiceCaseNode ccNode : ((ChoiceSchemaNode) parentSchemaNode).getCases()) {
135 for (DataSchemaNode dsn : ccNode.getChildNodes()) {
136 if (qNameToNodes.containsKey(dsn.getQName())) {
137 write(qNameToNodes.get(dsn.getQName()), dsn);
142 for (NormalizedNode<?, ?> child : children) {
152 private SchemaOrderedNormalizedNodeWriter writeLeaf(final NormalizedNode<?, ?> node) throws IOException {
153 if (wasProcessAsSimpleNode(node)) {
157 throw new IllegalStateException("It wasn't possible to serialize node " + node);
160 private ArrayListMultimap<QName, NormalizedNode<?, ?>> resolveAugmentations(final NormalizedNode<?, ?> child) {
161 final ArrayListMultimap<QName, NormalizedNode<?, ?>> resolvedAugs = ArrayListMultimap.create();
162 for (NormalizedNode<?, ?> node : ((AugmentationNode) child).getValue()) {
163 if (node instanceof AugmentationNode) {
164 resolvedAugs.putAll(resolveAugmentations(node));
166 resolvedAugs.put(node.getNodeType(), node);
173 private class SchemaNodeSetter implements AutoCloseable {
175 private final SchemaNode previousSchemaNode;
178 * Sets current schema node new value and store old value for later restore
180 public SchemaNodeSetter(final SchemaNode schemaNode) {
181 previousSchemaNode = SchemaOrderedNormalizedNodeWriter.this.currentSchemaNode;
182 SchemaOrderedNormalizedNodeWriter.this.currentSchemaNode = schemaNode;
186 * Restore previous schema node
189 public void close() {
190 SchemaOrderedNormalizedNodeWriter.this.currentSchemaNode = previousSchemaNode;