X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=binding%2Fmdsal-binding-generator%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fmdsal%2Fbinding%2Fgenerator%2Fimpl%2Freactor%2FAbstractTypeObjectGenerator.java;h=0ee7b438831283373285838e1f7c634f955c5da0;hb=31776f5c9d96892e93b8378ca09dc0c3caa41c2c;hp=002ab608e07772f74399619146b9230e2d753b89;hpb=3131e455f634c58b81443b6ddfa495e448c2a7bf;p=mdsal.git diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AbstractTypeObjectGenerator.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AbstractTypeObjectGenerator.java index 002ab608e0..0ee7b43883 100644 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AbstractTypeObjectGenerator.java +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AbstractTypeObjectGenerator.java @@ -23,7 +23,6 @@ import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; import org.opendaylight.mdsal.binding.generator.BindingGeneratorUtil; import org.opendaylight.mdsal.binding.generator.impl.reactor.TypeReference.ResolvedLeafref; -import org.opendaylight.mdsal.binding.model.api.AccessModifier; import org.opendaylight.mdsal.binding.model.api.ConcreteType; import org.opendaylight.mdsal.binding.model.api.Enumeration; import org.opendaylight.mdsal.binding.model.api.GeneratedProperty; @@ -42,6 +41,7 @@ import org.opendaylight.mdsal.binding.model.ri.TypeConstants; import org.opendaylight.mdsal.binding.model.ri.Types; import org.opendaylight.mdsal.binding.model.ri.generated.type.builder.AbstractEnumerationBuilder; import org.opendaylight.mdsal.binding.model.ri.generated.type.builder.GeneratedPropertyBuilderImpl; +import org.opendaylight.mdsal.binding.runtime.api.RuntimeType; import org.opendaylight.mdsal.binding.spec.naming.BindingMapping; import org.opendaylight.yangtools.concepts.Immutable; import org.opendaylight.yangtools.yang.binding.RegexPatterns; @@ -222,7 +222,8 @@ import org.slf4j.LoggerFactory; * type indirection in YANG constructs is therefore explicitly excluded from the generated Java code, but the Binding * Specification still takes them into account when determining types as outlined above. */ -abstract class AbstractTypeObjectGenerator> extends AbstractDependentGenerator { +abstract class AbstractTypeObjectGenerator, R extends RuntimeType> + extends AbstractDependentGenerator { private static final class UnionDependencies implements Immutable { private final Map, TypeReference> identityTypes = new HashMap<>(); private final Map, TypeReference> leafTypes = new HashMap<>(); @@ -294,9 +295,15 @@ abstract class AbstractTypeObjectGenerator> e private TypeReference refType; private List auxiliaryGeneratedTypes = List.of(); private UnionDependencies unionDependencies; - private List> inferred = List.of(); + private List> inferred = List.of(); - AbstractTypeObjectGenerator(final T statement, final AbstractCompositeGenerator parent) { + /** + * The type of single-element return type of the getter method associated with this generator. This is retained for + * run-time type purposes. It may be uninitialized, in which case this object must have a generated type. + */ + private Type methodReturnTypeElement; + + AbstractTypeObjectGenerator(final S statement, final AbstractCompositeGenerator parent) { super(statement, parent); type = statement().findFirstEffectiveSubstatement(TypeEffectiveStatement.class).orElseThrow(); } @@ -317,16 +324,16 @@ abstract class AbstractTypeObjectGenerator> e return; } - final AbstractExplicitGenerator prev = previous(); + final AbstractExplicitGenerator prev = previous(); if (prev != null) { verify(prev instanceof AbstractTypeObjectGenerator, "Unexpected previous %s", prev); - ((AbstractTypeObjectGenerator) prev).linkInferred(this); + ((AbstractTypeObjectGenerator) prev).linkInferred(this); } else { linkBaseGen(context.resolveTypedef(typeName)); } } - private void linkInferred(final AbstractTypeObjectGenerator downstream) { + private void linkInferred(final AbstractTypeObjectGenerator downstream) { if (inferred == null) { downstream.linkBaseGen(verifyNotNull(baseGen, "Mismatch on linking between %s and %s", this, downstream)); return; @@ -340,13 +347,13 @@ abstract class AbstractTypeObjectGenerator> e private void linkBaseGen(final TypedefGenerator upstreamBaseGen) { verify(baseGen == null, "Attempted to replace base %s with %s in %s", baseGen, upstreamBaseGen, this); - final List> downstreams = verifyNotNull(inferred, + final List> downstreams = verifyNotNull(inferred, "Duplicated linking of %s", this); baseGen = verifyNotNull(upstreamBaseGen); baseGen.addDerivedGenerator(this); inferred = null; - for (AbstractTypeObjectGenerator downstream : downstreams) { + for (AbstractTypeObjectGenerator downstream : downstreams) { downstream.linkBaseGen(upstreamBaseGen); } } @@ -364,7 +371,7 @@ abstract class AbstractTypeObjectGenerator> e .map(context::resolveIdentity) .collect(Collectors.toUnmodifiableList())); } else if (TypeDefinitions.LEAFREF.equals(arg)) { - final AbstractTypeObjectGenerator targetGenerator = context.resolveLeafref( + final AbstractTypeObjectGenerator targetGenerator = context.resolveLeafref( type.findFirstEffectiveSubstatementArgument(PathEffectiveStatement.class).orElseThrow()); checkArgument(targetGenerator != this, "Effective model contains self-referencing leaf %s", statement().argument()); @@ -448,7 +455,28 @@ abstract class AbstractTypeObjectGenerator> e return methodReturnElementType(builderFactory); } + @Override + final Type runtimeJavaType() { + if (methodReturnTypeElement != null) { + return methodReturnTypeElement; + } + final var genType = generatedType(); + if (genType.isPresent()) { + return genType.orElseThrow(); + } + final var prev = verifyNotNull(previous(), "No previous generator for %s", this); + return prev.runtimeJavaType(); + } + final @NonNull Type methodReturnElementType(final @NonNull TypeBuilderFactory builderFactory) { + var local = methodReturnTypeElement; + if (local == null) { + methodReturnTypeElement = local = createMethodReturnElementType(builderFactory); + } + return local; + } + + private @NonNull Type createMethodReturnElementType(final @NonNull TypeBuilderFactory builderFactory) { final GeneratedType generatedType = tryGeneratedType(builderFactory); if (generatedType != null) { // We have generated a type here, so return it. This covers 'bits', 'enumeration' and 'union'. @@ -460,7 +488,7 @@ abstract class AbstractTypeObjectGenerator> e return refType.methodReturnType(builderFactory); } - final AbstractExplicitGenerator prev = previous(); + final AbstractExplicitGenerator prev = previous(); if (prev != null) { // We have been added through augment/uses, defer to the original definition return prev.methodReturnType(builderFactory); @@ -518,8 +546,8 @@ abstract class AbstractTypeObjectGenerator> e return; } - final AbstractTypeObjectGenerator prev = - (AbstractTypeObjectGenerator) verifyNotNull(previous(), "Missing previous link in %s", this); + final AbstractTypeObjectGenerator prev = + (AbstractTypeObjectGenerator) verifyNotNull(previous(), "Missing previous link in %s", this); if (prev.refType instanceof ResolvedLeafref) { // We should be already inheriting the correct type return; @@ -598,7 +626,7 @@ abstract class AbstractTypeObjectGenerator> e // builder.setSchemaPath(typedef.getPath()); builder.setModuleName(module.statement().argument().getLocalName()); - addCodegenInformation(typedef, builder); + builderFactory.addCodegenInformation(typedef, builder); annotateDeprecatedIfNecessary(typedef, builder); makeSerializable(builder); return builder.build(); @@ -636,7 +664,7 @@ abstract class AbstractTypeObjectGenerator> e // builder.setSchemaPath(typedef.getPath()); builder.setModuleName(moduleName); - addCodegenInformation(typedef, builder); + builderFactory.addCodegenInformation(typedef, builder); annotateDeprecatedIfNecessary(typedef, builder); @@ -661,7 +689,7 @@ abstract class AbstractTypeObjectGenerator> e // builder.setSchemaPath(typedef.getPath()); builder.setModuleName(module.statement().argument().getLocalName()); - addCodegenInformation(definingStatement, builder); + builderFactory.addCodegenInformation(definingStatement, builder); annotateDeprecatedIfNecessary(definingStatement, builder); @@ -715,7 +743,7 @@ abstract class AbstractTypeObjectGenerator> e Type baseType = SIMPLE_TYPES.get(subName); if (baseType == null) { // This has to be a reference to a typedef, let's lookup it up and pick up its type - final AbstractTypeObjectGenerator baseGen = verifyNotNull( + final AbstractTypeObjectGenerator baseGen = verifyNotNull( dependencies.baseTypes.get(subName), "Cannot resolve base type %s in %s", subName, definingStatement); baseType = baseGen.methodReturnType(builderFactory); @@ -790,29 +818,7 @@ abstract class AbstractTypeObjectGenerator> e addUnits(builder, typedef); makeSerializable(builder); - final GeneratedTransferObject ret = builder.build(); - - // Define a corresponding union builder. Typedefs are always anchored at a Java package root, - // so we are placing the builder alongside the union. - final GeneratedTOBuilder unionBuilder = builderFactory.newGeneratedTOBuilder(unionBuilderName(typeName)); - unionBuilder.setIsUnionBuilder(true); - unionBuilder.addMethod("getDefaultInstance") - .setAccessModifier(AccessModifier.PUBLIC) - .setStatic(true) - .setReturnType(ret) - .addParameter(Types.STRING, "defaultValue"); - auxiliaryGeneratedTypes.add(unionBuilder.build()); - - return ret; - } - - // FIXME: this can be a source of conflicts as we are not guarding against nesting - private static @NonNull JavaTypeName unionBuilderName(final JavaTypeName unionName) { - final StringBuilder sb = new StringBuilder(); - for (String part : unionName.localNameComponents()) { - sb.append(part); - } - return JavaTypeName.create(unionName.packageName(), sb.append(BindingMapping.BUILDER_SUFFIX).toString()); + return builder.build(); } // FIXME: we should not rely on TypeDefinition