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