--- /dev/null
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.generator.impl.reactor;
+
+import static java.util.Objects.requireNonNull;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.opendaylight.mdsal.binding.model.api.GeneratedTransferObject;
+import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTOBuilder;
+import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilderBase;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.stmt.TypedefEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
+
+/**
+ * Generator corresponding to a {@code typedef} statement.
+ */
+final class TypedefGenerator extends AbstractTypeObjectGenerator<TypedefEffectiveStatement> {
+ /**
+ * List of all generators for types directly derived from this typedef. We populate this list during initial type
+ * linking. It allows us to easily cascade inferences made by this typedef down the type derivation tree.
+ */
+ private List<AbstractTypeObjectGenerator<?>> derivedGenerators = null;
+
+ TypedefGenerator(final TypedefEffectiveStatement statement, final AbstractCompositeGenerator<?> parent) {
+ super(statement, parent);
+ }
+
+ @Override
+ StatementNamespace namespace() {
+ return StatementNamespace.TYPEDEF;
+ }
+
+ @Override
+ void pushToInference(final SchemaInferenceStack dataTree) {
+ dataTree.enterTypedef(statement().argument());
+ }
+
+ void addDerivedGenerator(final AbstractTypeObjectGenerator<?> derivedGenerator) {
+ if (derivedGenerators == null) {
+ derivedGenerators = new ArrayList<>(4);
+ }
+ derivedGenerators.add(requireNonNull(derivedGenerator));
+ }
+
+ @Override
+ void bindDerivedGenerators(final TypeReference reference) {
+ // Trigger any derived resolvers ...
+ if (derivedGenerators != null) {
+ for (AbstractTypeObjectGenerator<?> derived : derivedGenerators) {
+ derived.bindTypeDefinition(reference);
+ }
+ }
+ // ... and make sure nobody can come in late
+ derivedGenerators = List.of();
+ }
+
+ @Override
+ ClassPlacement classPlacementImpl() {
+ return ClassPlacement.TOP_LEVEL;
+ }
+
+ @Override
+ TypeDefinition<?> extractTypeDefinition() {
+ return statement().getTypeDefinition();
+ }
+
+ @Override
+ GeneratedTransferObject createDerivedType(final TypeBuilderFactory builderFactory,
+ final GeneratedTransferObject baseType) {
+ final GeneratedTOBuilder builder = builderFactory.newGeneratedTOBuilder(typeName());
+ builder.setTypedef(true);
+ builder.setExtendsType(baseType);
+ builder.setIsUnion(baseType.isUnionType());
+ builder.setRestrictions(computeRestrictions());
+
+ final TypeDefinition<?> typedef = statement().getTypeDefinition();
+ annotateDeprecatedIfNecessary(typedef, builder);
+ addStringRegExAsConstant(builder, resolveRegExpressions(typedef));
+ addUnits(builder, typedef);
+
+ makeSerializable(builder);
+ return builder.build();
+ }
+
+ @Override
+ void addAsGetterMethod(final GeneratedTypeBuilderBase<?> builder, final TypeBuilderFactory builderFactory) {
+ // typedefs are a separate concept
+ }
+}