Fix BindingStructuralType.isNotAddressable()
[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 org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
12 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
13 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
14 import org.opendaylight.yangtools.yang.data.api.schema.AnydataNode;
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         var dataBased = domChildNode.dataAfter();
72         if (dataBased == null) {
73             dataBased = domChildNode.dataBefore();
74         }
75         return dataBased != null ? from(dataBased) : from(domChildNode.name());
76     }
77
78     private static BindingStructuralType from(final PathArgument identifier) {
79         if (identifier instanceof NodeIdentifierWithPredicates) {
80             return VISIBLE_CONTAINER;
81         }
82         if (identifier instanceof NodeWithValue) {
83             return NOT_ADDRESSABLE;
84         }
85         return UNKNOWN;
86     }
87
88     static BindingStructuralType from(final NormalizedNode data) {
89         if (isNotAddressable(data)) {
90             return NOT_ADDRESSABLE;
91         }
92         if (data instanceof MapNode) {
93             return INVISIBLE_LIST;
94         }
95         if (data instanceof ChoiceNode) {
96             return INVISIBLE_CONTAINER;
97         }
98         if (isVisibleContainer(data)) {
99             return VISIBLE_CONTAINER;
100         }
101         return UNKNOWN;
102     }
103
104     public static BindingStructuralType recursiveFrom(final DataTreeCandidateNode node) {
105         final var type = BindingStructuralType.from(node);
106         return switch (type) {
107             case INVISIBLE_CONTAINER, INVISIBLE_LIST -> {
108                 // This node is invisible, try to resolve using a child node
109                 for (var child : node.childNodes()) {
110                     final var childType = recursiveFrom(child);
111                     yield switch (childType) {
112                             case INVISIBLE_CONTAINER, INVISIBLE_LIST ->
113                                 // Invisible nodes are not addressable
114                                 BindingStructuralType.NOT_ADDRESSABLE;
115                             case NOT_ADDRESSABLE, UNKNOWN, VISIBLE_CONTAINER -> childType;
116                         };
117                 }
118
119                 yield BindingStructuralType.NOT_ADDRESSABLE;
120             }
121             default -> type;
122         };
123     }
124
125     private static boolean isVisibleContainer(final NormalizedNode data) {
126         return data instanceof MapEntryNode || data instanceof ContainerNode;
127     }
128
129     private static boolean isNotAddressable(final NormalizedNode normalizedNode) {
130         return normalizedNode instanceof LeafNode
131                 || normalizedNode instanceof AnyxmlNode
132                 || normalizedNode instanceof AnydataNode
133                 || normalizedNode instanceof LeafSetNode
134                 || normalizedNode instanceof LeafSetEntryNode
135                 || normalizedNode instanceof UnkeyedListNode
136                 || normalizedNode instanceof UnkeyedListEntryNode;
137     }
138 }