Update binding-dom adaptation to remove AugmentationNode
[mdsal.git] / binding / mdsal-binding-dom-adapter / src / main / java / org / opendaylight / mdsal / binding / dom / adapter / BindingStructuralType.java
1 /*
2  * Copyright (c) 2015 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.mdsal.binding.dom.adapter;
9
10 import com.google.common.annotations.Beta;
11 import java.util.Optional;
12 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
13 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
14 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
15 import org.opendaylight.yangtools.yang.data.api.schema.AnyxmlNode;
16 import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
17 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
18 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
19 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
20 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
21 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
22 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
23 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
24 import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
25 import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode;
26 import org.opendaylight.yangtools.yang.data.tree.api.DataTreeCandidateNode;
27
28 /**
29  * Defines structural mapping of Normalized Node to Binding data addressable by Instance Identifier. Not all binding
30  * data are addressable by instance identifier and there are some differences.
31  *
32  * <p>
33  * See {@link #NOT_ADDRESSABLE},{@link #INVISIBLE_CONTAINER},{@link #VISIBLE_CONTAINER} for more details.
34  *
35  * <p>
36  * NOTE: this class is exposed for migration purposes only, no new users outside of its package should be introduced.
37  */
38 @Beta
39 public enum BindingStructuralType {
40     /**
41      * DOM Item is not addressable in Binding InstanceIdentifier, data is not lost, but are available only via parent
42      * object. Such types of data are leaf-lists, leafs, list without keys or anyxml.
43      */
44     NOT_ADDRESSABLE,
45     /**
46      * Data container is addressable in NormalizedNode format, but in Binding it is not represented in
47      * InstanceIdentifier. These are choice / case nodes.
48      *
49      * <p>
50      * This data is still accessible using parent object and their children are addressable.
51      */
52     INVISIBLE_CONTAINER,
53     /**
54      * Data container is addressable in NormalizedNode format, but in Binding it is not represented in
55      * InstanceIdentifier. These are list nodes.
56      *
57      * <p>
58      * This data is still accessible using parent object and their children are addressable.
59      */
60     INVISIBLE_LIST,
61     /**
62      * Data container is addressable in Binding InstanceIdentifier format and also YangInstanceIdentifier format.
63      */
64     VISIBLE_CONTAINER,
65     /**
66      * Mapping algorithm was unable to detect type or was not updated after introduction of new NormalizedNode type.
67      */
68     UNKNOWN;
69
70     public static BindingStructuralType from(final DataTreeCandidateNode domChildNode) {
71         Optional<NormalizedNode> dataBased = domChildNode.getDataAfter();
72         if (!dataBased.isPresent()) {
73             dataBased = domChildNode.getDataBefore();
74         }
75         if (dataBased.isPresent()) {
76             return from(dataBased.orElseThrow());
77         }
78         return from(domChildNode.getIdentifier());
79     }
80
81     private static BindingStructuralType from(final PathArgument identifier) {
82         if (identifier instanceof NodeIdentifierWithPredicates) {
83             return VISIBLE_CONTAINER;
84         }
85         if (identifier instanceof NodeWithValue) {
86             return NOT_ADDRESSABLE;
87         }
88         return UNKNOWN;
89     }
90
91     static BindingStructuralType from(final NormalizedNode data) {
92         if (isNotAddressable(data)) {
93             return NOT_ADDRESSABLE;
94         }
95         if (data instanceof MapNode) {
96             return INVISIBLE_LIST;
97         }
98         if (data instanceof ChoiceNode) {
99             return INVISIBLE_CONTAINER;
100         }
101         if (isVisibleContainer(data)) {
102             return VISIBLE_CONTAINER;
103         }
104         return UNKNOWN;
105     }
106
107     public static BindingStructuralType recursiveFrom(final DataTreeCandidateNode node) {
108         final BindingStructuralType type = BindingStructuralType.from(node);
109         return switch (type) {
110             case INVISIBLE_CONTAINER, INVISIBLE_LIST -> {
111                 // This node is invisible, try to resolve using a child node
112                 for (final DataTreeCandidateNode child : node.getChildNodes()) {
113                     final BindingStructuralType childType = recursiveFrom(child);
114                     yield switch (childType) {
115                             case INVISIBLE_CONTAINER, INVISIBLE_LIST ->
116                                 // Invisible nodes are not addressable
117                                 BindingStructuralType.NOT_ADDRESSABLE;
118                             case NOT_ADDRESSABLE, UNKNOWN, VISIBLE_CONTAINER -> childType;
119                         };
120                 }
121
122                 yield BindingStructuralType.NOT_ADDRESSABLE;
123             }
124             default -> type;
125         };
126     }
127
128     private static boolean isVisibleContainer(final NormalizedNode data) {
129         return data instanceof MapEntryNode || data instanceof ContainerNode;
130     }
131
132     private static boolean isNotAddressable(final NormalizedNode normalizedNode) {
133         return normalizedNode instanceof LeafNode
134                 || normalizedNode instanceof AnyxmlNode
135                 || normalizedNode instanceof LeafSetNode
136                 || normalizedNode instanceof LeafSetEntryNode
137                 || normalizedNode instanceof UnkeyedListNode
138                 || normalizedNode instanceof UnkeyedListEntryNode;
139     }
140 }