2 * Copyright (c) 2021 PANTHEON.tech, 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.generator.impl.rt;
10 import static java.util.Objects.requireNonNull;
11 import static java.util.Objects.requireNonNullElse;
13 import com.google.common.base.Functions;
14 import com.google.common.base.VerifyException;
15 import com.google.common.collect.ImmutableMap;
16 import java.util.Arrays;
17 import java.util.Collections;
18 import java.util.List;
19 import org.eclipse.jdt.annotation.NonNull;
20 import org.opendaylight.mdsal.binding.model.api.GeneratedType;
21 import org.opendaylight.mdsal.binding.model.api.JavaTypeName;
22 import org.opendaylight.mdsal.binding.runtime.api.CompositeRuntimeType;
23 import org.opendaylight.mdsal.binding.runtime.api.GeneratedRuntimeType;
24 import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
25 import org.opendaylight.yangtools.yang.common.QName;
26 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
27 import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeEffectiveStatement;
29 abstract class AbstractCompositeRuntimeType<S extends EffectiveStatement<?, ?>>
30 extends AbstractRuntimeType<S, GeneratedType> implements CompositeRuntimeType {
31 private static final RuntimeType[] EMPTY = new RuntimeType[0];
33 private final ImmutableMap<JavaTypeName, GeneratedRuntimeType> byClass;
34 private final Object bySchemaTree;
36 AbstractCompositeRuntimeType(final GeneratedType bindingType, final S statement, final List<RuntimeType> children) {
37 super(bindingType, statement);
39 byClass = children.stream()
40 .filter(GeneratedRuntimeType.class::isInstance)
41 .map(GeneratedRuntimeType.class::cast)
42 .collect(ImmutableMap.toImmutableMap(GeneratedRuntimeType::getIdentifier, Functions.identity()));
44 final var tmp = children.stream()
45 .filter(child -> child.statement() instanceof SchemaTreeEffectiveStatement)
46 .toArray(RuntimeType[]::new);
47 bySchemaTree = switch (tmp.length) {
51 Arrays.sort(tmp, (o1, o2) -> {
52 final int cmp = extractQName(o1).compareTo(extractQName(o2));
54 throw new VerifyException("Type " + o1 + " conflicts with " + o2 + " on schema tree");
64 public final RuntimeType schemaTreeChild(final QName qname) {
65 if (bySchemaTree instanceof RuntimeType tmp) {
66 return qname.equals(tmp.statement().argument()) ? tmp : null;
69 final var tmp = (RuntimeType[]) bySchemaTree;
70 // Here we are assuming that Arrays.binarySearch() accepts a null object, so as to help CHA by not introducing
71 // a fake RuntimeType class and the corresponding instanceof checks to side-step the statement lookup (which
72 // would need more faking).
73 // We make a slight assumption that o2 is the what we specify as a key, but can recover if it is the other way
75 final int offset = Arrays.binarySearch(tmp, null,
76 (o1, o2) -> extractQName(requireNonNullElse(o1, o2)).compareTo(qname));
77 return offset < 0 ? null : tmp[offset];
81 public final GeneratedRuntimeType bindingChild(final JavaTypeName typeName) {
82 return byClass.get(requireNonNull(typeName));
85 // Makes an assertion of all types being of specified type
86 @SuppressWarnings("unchecked")
87 final <T extends RuntimeType> @NonNull List<T> schemaTree(final Class<T> expectedType) {
88 if (expectedType.isInstance(bySchemaTree)) {
89 return List.of(expectedType.cast(bySchemaTree));
92 final var tmp = (RuntimeType[]) bySchemaTree;
93 for (var item : tmp) {
94 if (!expectedType.isInstance(item)) {
95 throw new VerifyException("Unexpected schema tree child " + item);
98 return (List<T>) Collections.unmodifiableList(Arrays.asList(tmp));
101 private static @NonNull QName extractQName(final RuntimeType type) {
102 final var stmt = type.statement();
103 if (stmt instanceof SchemaTreeEffectiveStatement<?> schemaTreeStmt) {
104 return schemaTreeStmt.argument();
106 throw new VerifyException("Unexpected statement " + stmt + " in " + type);