Retain grouping/uses instantiation vectors
[mdsal.git] / binding / mdsal-binding-runtime-api / src / main / java / org / opendaylight / mdsal / binding / runtime / api / GroupingRuntimeType.java
1 /*
2  * Copyright (c) 2021 PANTHEON.tech, s.r.o. 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.runtime.api;
9
10 import java.util.List;
11 import java.util.stream.Collectors;
12 import java.util.stream.Stream;
13 import org.eclipse.jdt.annotation.NonNull;
14 import org.opendaylight.yangtools.yang.model.api.stmt.GroupingEffectiveStatement;
15
16 /**
17  * A {@link RuntimeType} associated with a {@code grouping} statement.
18  */
19 public interface GroupingRuntimeType extends CompositeRuntimeType {
20     @Override
21     GroupingEffectiveStatement statement();
22
23     /**
24      * Return the set of all concrete data tree instantiations of this {@code grouping}. This is necessary to completely
25      * resolve type information for {@code leafref}s.
26      *
27      * <p>
28      * As an example, consider {@link GroupingRuntimeType} of {@code grouping baz} and it's instantiations roots
29      * {@code container one} and {@code container two} define in these three models:
30      * <pre>{@code
31      *   module baz {
32      *     namespace baz;
33      *     prefix baz;
34      *
35      *     grouping baz {
36      *       leaf baz {
37      *         type leafref {
38      *           path "../bar";
39      *         }
40      *       }
41      *     }
42      *   }
43      *
44      *   module one {
45      *     namespace one;
46      *     prefix one;
47      *     import baz { prefix baz; }
48      *
49      *     container one {
50      *       leaf bar {
51      *         type string;
52      *       }
53      *       uses baz:baz;
54      *     }
55      *   }
56      *
57      *   module two {
58      *     namespace two;
59      *     prefix two;
60      *     import baz { prefix baz; }
61      *
62      *     container two {
63      *       leaf bar {
64      *         type uint16;
65      *       }
66      *       uses baz:baz;
67      *     }
68      *   }
69      * }</pre>
70      *
71      * <p>
72      * Since these are separate modules, each of them can be part of its own compilation unit and therefore
73      * {@code grouping baz} compile-time analysis cannot definitely determine the return type of {@code getBaz()} and
74      * must fall back to {@code Object}.
75      *
76      * <p>
77      * At run-time, though, we have a closed world, and therefore we can provide accurate information about
78      * instantiation sites: this method will return the {@link CompositeRuntimeType}s for {@code one} and {@code two}.
79      * We can then use this information to know that {@code getBaz()} can either be a {@code String} or an
80      * {@code Uint32} and which type is appropriate at a particular point in YANG data tree.
81      *
82      * @return The set instantiated {@link CompositeRuntimeType}s which use this grouping
83      */
84     default @NonNull List<CompositeRuntimeType> instantiations() {
85         final var users = directUsers();
86         return switch (users.size()) {
87             case 0 -> List.of();
88             case 1 -> {
89                 final var user = users.get(0);
90                 yield user instanceof GroupingRuntimeType grouping ? grouping.instantiations() : List.of(user);
91             }
92             default -> users.stream()
93                 .flatMap(user -> user instanceof GroupingRuntimeType grouping ? grouping.instantiations().stream()
94                     : Stream.of(user))
95                 .distinct()
96                 .collect(Collectors.toUnmodifiableList());
97         };
98     }
99
100     /**
101      * Support method for {@link #instantiations()}. This method's return, unlike {@link #instantiations()} can contain
102      * other {@link GroupingRuntimeType}s.
103      *
104      * @return Direct users of this grouping
105      */
106     @NonNull List<CompositeRuntimeType> directUsers();
107 }