5f75ccdea95397bbee642274faa8ac21c965e29d
[yangtools.git] / yang / yang-data-util / src / main / java / org / opendaylight / yangtools / yang / data / util / ListEntryNodeDataWithSchema.java
1 /*
2  * Copyright (c) 2016 Cisco Systems, Inc. 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 com.google.common.base.Verify.verify;
11
12 import java.io.IOException;
13 import java.util.HashMap;
14 import java.util.List;
15 import java.util.Map;
16 import org.eclipse.jdt.annotation.NonNull;
17 import org.opendaylight.yangtools.rfc7952.data.api.StreamWriterMetadataExtension;
18 import org.opendaylight.yangtools.util.ImmutableMapTemplate;
19 import org.opendaylight.yangtools.yang.common.QName;
20 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
21 import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
22 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
23 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
24 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
25
26 /**
27  * Utility class used for tracking parser state as needed by a StAX-like parser.
28  * This class is to be used only by respective XML and JSON parsers in yang-data-codec-xml and yang-data-codec-gson.
29  *
30  * <p>
31  * Represents a YANG list entry node.
32  */
33 public abstract class ListEntryNodeDataWithSchema extends AbstractMountPointDataWithSchema<ListSchemaNode> {
34     private static final class Keyed extends ListEntryNodeDataWithSchema {
35         private final Map<QName, SimpleNodeDataWithSchema<?>> keyValues = new HashMap<>();
36         // This template results in Maps in schema definition order
37         private final ImmutableMapTemplate<QName> predicateTemplate;
38
39         Keyed(final ListSchemaNode schema, final List<QName> keyDef) {
40             super(schema);
41             predicateTemplate = ImmutableMapTemplate.ordered(keyDef);
42         }
43
44         @Override
45         public void addChild(final AbstractNodeDataWithSchema<?> newChild) {
46             final DataSchemaNode childSchema = newChild.getSchema();
47             if (childSchema instanceof LeafSchemaNode) {
48                 final QName childName = childSchema.getQName();
49                 if (predicateTemplate.keySet().contains(childName)) {
50                     verify(newChild instanceof SimpleNodeDataWithSchema);
51                     keyValues.put(childName, (SimpleNodeDataWithSchema<?>)newChild);
52                 }
53             }
54             super.addChild(newChild);
55         }
56
57         @Override
58         public void write(final NormalizedNodeStreamWriter writer, final StreamWriterMetadataExtension metaWriter)
59                 throws IOException {
60             writer.nextDataSchemaNode(getSchema());
61             final NodeIdentifierWithPredicates identifier = NodeIdentifierWithPredicates.of(getSchema().getQName(),
62                 predicateTemplate.instantiateTransformed(keyValues, (key, node) -> node.getValue()));
63
64             writer.startMapEntryNode(identifier, childSizeHint());
65             writeMetadata(metaWriter);
66             super.write(writer, metaWriter);
67             writer.endNode();
68         }
69     }
70
71     private static final class Unkeyed extends ListEntryNodeDataWithSchema {
72         Unkeyed(final ListSchemaNode schema) {
73             super(schema);
74         }
75
76         @Override
77         public void write(final NormalizedNodeStreamWriter writer, final StreamWriterMetadataExtension metaWriter)
78                 throws IOException {
79             writer.nextDataSchemaNode(getSchema());
80             writer.startUnkeyedListItem(provideNodeIdentifier(), childSizeHint());
81             super.write(writer, metaWriter);
82             writer.endNode();
83         }
84     }
85
86     ListEntryNodeDataWithSchema(final ListSchemaNode schema) {
87         super(schema);
88     }
89
90     public static @NonNull ListEntryNodeDataWithSchema forSchema(final ListSchemaNode schema) {
91         final List<QName> keyDef = schema.getKeyDefinition();
92         return keyDef.isEmpty() ? new Unkeyed(schema) :  new Keyed(schema, keyDef);
93     }
94 }