083bf08f9332192a474d648b16d08d8eeba7ac4b
[mdsal.git] / binding / mdsal-binding-generator / src / main / java / org / opendaylight / mdsal / binding / generator / impl / reactor / ChildLookup.java
1 /*
2  * Copyright (c) 2022 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.generator.impl.reactor;
9
10 import static com.google.common.base.Verify.verify;
11 import static com.google.common.base.Verify.verifyNotNull;
12 import static java.util.Objects.requireNonNull;
13
14 import com.google.common.base.MoreObjects;
15 import com.google.common.collect.ImmutableSet;
16 import java.util.stream.Stream;
17 import org.eclipse.jdt.annotation.NonNull;
18 import org.opendaylight.yangtools.concepts.Immutable;
19 import org.opendaylight.yangtools.yang.common.QName;
20 import org.opendaylight.yangtools.yang.common.QNameModule;
21 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
22 import org.opendaylight.yangtools.yang.model.api.stmt.AugmentEffectiveStatement;
23 import org.opendaylight.yangtools.yang.model.api.stmt.UsesEffectiveStatement;
24
25 /**
26  * Lookup context for dealing with namespace translation during execution of {@link AbstractCompositeGenerator}'s
27  * createInternalRuntimeType(). It tracks which namespaces should be translated on account of crossing into source
28  * {@code grouping} statement.
29  */
30 final class ChildLookup implements Immutable {
31     private final ImmutableSet<AugmentEffectiveStatement> validUsesAugments;
32     private final ImmutableSet<QNameModule> squashNamespaces;
33     private final QNameModule localNamespace;
34
35     private ChildLookup(final ImmutableSet<AugmentEffectiveStatement> validUsesAugments,
36             final ImmutableSet<QNameModule> squashNamespaces, final QNameModule localNamespace) {
37         this.validUsesAugments = requireNonNull(validUsesAugments);
38         this.squashNamespaces = requireNonNull(squashNamespaces);
39         this.localNamespace = localNamespace;
40         verify(localNamespace == null == squashNamespaces.isEmpty(), "Unexpected lookup state %s", this);
41     }
42
43     public static @NonNull ChildLookup of(final EffectiveStatement<?, ?> statement) {
44         return new ChildLookup(streamUsesAugments(statement).collect(ImmutableSet.toImmutableSet()), ImmutableSet.of(),
45             null);
46     }
47
48     @NonNull QName adjustQName(final @NonNull QName qname) {
49         return squashNamespaces.contains(qname.getModule()) ? qname.bindTo(verifyNotNull(localNamespace)) : qname;
50     }
51
52     boolean contains(final AugmentEffectiveStatement augment) {
53         return validUsesAugments.contains(augment);
54     }
55
56     @NonNull ChildLookup inStatement(final EffectiveStatement<?, ?> statememt) {
57         return hasUsesAugments(statememt)
58             ? new ChildLookup(concatUsesAugments(statememt), squashNamespaces, localNamespace) : this;
59     }
60
61     @NonNull ChildLookup inGrouping(final QName qname, final GroupingGenerator grouping) {
62         final var statement = grouping.statement();
63         final var grpNamespace = statement.argument().getModule();
64         final var itemNamespace = qname.getModule();
65
66         final ImmutableSet<QNameModule> newSquashNamespaces;
67         if (squashNamespaces.contains(itemNamespace)) {
68             newSquashNamespaces = squashNamespaces;
69         } else {
70             newSquashNamespaces = ImmutableSet.<QNameModule>builderWithExpectedSize(squashNamespaces.size() + 1)
71                 .addAll(squashNamespaces).add(itemNamespace).build();
72         }
73
74         return new ChildLookup(hasUsesAugments(statement) ? concatUsesAugments(statement) : validUsesAugments,
75             newSquashNamespaces, grpNamespace);
76     }
77
78     @Override
79     public String toString() {
80         return MoreObjects.toStringHelper(this).omitNullValues()
81             .add("augments", validUsesAugments)
82             .add("squash", squashNamespaces)
83             .add("local", localNamespace)
84             .toString();
85     }
86
87     private ImmutableSet<AugmentEffectiveStatement> concatUsesAugments(final EffectiveStatement<?, ?> stmt) {
88         final var concat = ImmutableSet.<AugmentEffectiveStatement>builder().addAll(validUsesAugments);
89         streamUsesAugments(stmt).forEach(concat::add);
90         return concat.build();
91     }
92
93     private static boolean hasUsesAugments(final EffectiveStatement<?, ?> stmt) {
94         return streamUsesAugments(stmt).findAny().isPresent();
95     }
96
97     private static Stream<AugmentEffectiveStatement> streamUsesAugments(final EffectiveStatement<?, ?> stmt) {
98         return stmt.streamEffectiveSubstatements(UsesEffectiveStatement.class)
99             .flatMap(uses -> uses.streamEffectiveSubstatements(AugmentEffectiveStatement.class));
100     }
101 }