2 * Copyright (c) 2018 Pantheon Technologies, s.r.o. and others. All rights reserved.
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
8 package org.opendaylight.mdsal.binding.java.api.generator;
10 import static com.google.common.base.Verify.verify;
11 import static java.util.Objects.requireNonNull;
13 import com.google.common.collect.ImmutableList;
14 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
15 import java.util.ArrayDeque;
16 import java.util.Deque;
17 import java.util.Iterator;
18 import java.util.List;
19 import java.util.Optional;
20 import org.eclipse.jdt.annotation.NonNullByDefault;
21 import org.eclipse.jdt.annotation.Nullable;
22 import org.opendaylight.mdsal.binding.model.api.GeneratedType;
23 import org.opendaylight.mdsal.binding.model.api.JavaTypeName;
26 * A type which is nested inside some other type. It defers import decisions to its enclosing type, eventually arriving
27 * at a {@link TopLevelJavaGeneratedType}.
29 * @author Robert Varga
32 final class NestedJavaGeneratedType extends AbstractJavaGeneratedType {
33 private final AbstractJavaGeneratedType enclosingType;
35 NestedJavaGeneratedType(final AbstractJavaGeneratedType enclosingType, final GeneratedType genType) {
37 this.enclosingType = requireNonNull(enclosingType);
41 boolean importCheckedType(final JavaTypeName type) {
42 // Defer to enclosing type, which needs to re-run its checks
43 return enclosingType.checkAndImportType(type);
47 String localTypeName(final JavaTypeName type) {
48 // Check if the type is a reference to our immediately-enclosing type
49 if (enclosingType.getName().equals(type)) {
50 return enclosingType.getSimpleName();
53 final @Nullable List<String> descendant = findDescandantPath(type);
54 if (descendant == null) {
55 // The type is not present in our hierarchy, defer to our immediately-enclosing type, which may be able
56 // to find the target.
57 return enclosingType.localTypeName(type);
60 // Target type is a declared as a enclosed type of us and we have the path where it lurks.
61 final Iterator<String> it = descendant.iterator();
62 final StringBuilder sb = new StringBuilder().append(it.next());
63 while (it.hasNext()) {
64 sb.append('.').append(it.next());
69 @SuppressFBWarnings(value = "NP_NONNULL_RETURN_VIOLATION",
70 justification = "SpotBugs confusion @Nullable vs @NonNullByDefault")
71 private @Nullable List<String> findDescandantPath(final JavaTypeName type) {
72 Optional<JavaTypeName> optEnclosing = type.immediatelyEnclosingClass();
73 verify(optEnclosing.isPresent());
75 final Deque<String> queue = new ArrayDeque<>();
76 queue.addFirst(type.simpleName());
77 while (optEnclosing.isPresent()) {
78 final JavaTypeName enclosing = optEnclosing.get();
79 if (enclosing.equals(getName())) {
80 return ImmutableList.copyOf(queue);
83 queue.addFirst(enclosing.simpleName());
84 optEnclosing = enclosing.immediatelyEnclosingClass();