*/
package org.opendaylight.mdsal.binding.generator.impl.reactor;
-import static com.google.common.base.Verify.verify;
import static com.google.common.base.Verify.verifyNotNull;
import static java.util.Objects.requireNonNull;
import com.google.common.base.MoreObjects.ToStringHelper;
+import com.google.common.base.VerifyException;
import java.util.Optional;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.opendaylight.mdsal.binding.generator.impl.reactor.CollisionDomain.Member;
import org.opendaylight.mdsal.binding.generator.impl.tree.StatementRepresentation;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
import org.opendaylight.mdsal.binding.model.api.MethodSignature.ValueMechanics;
import org.opendaylight.mdsal.binding.model.api.Type;
import org.opendaylight.mdsal.binding.model.api.TypeMemberComment;
import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilderBase;
import org.opendaylight.mdsal.binding.model.api.type.builder.MethodSignatureBuilder;
import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
-import org.opendaylight.mdsal.binding.spec.naming.BindingMapping;
+import org.opendaylight.yangtools.yang.binding.contract.Naming;
import org.opendaylight.yangtools.yang.common.AbstractQName;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.model.api.AddedByUsesAware;
/**
* An explicit {@link Generator}, associated with a particular {@link EffectiveStatement}.
*/
+// FIXME: unify this with Generator
public abstract class AbstractExplicitGenerator<S extends EffectiveStatement<?, ?>, R extends RuntimeType>
extends Generator implements CopyableNode, StatementRepresentation<S> {
private static final Logger LOG = LoggerFactory.getLogger(AbstractExplicitGenerator.class);
}
/**
- * Return the {@link RuntimeType} associated with this object, of applicable.
+ * Return the {@link RuntimeType} associated with this object, if applicable. This represents the
+ * externally-accessible view of this object when considered outside the schema tree or binding tree hierarchy.
*
* @return Associated run-time type, or empty
*/
public final Optional<R> runtimeType() {
if (!runtimeTypeInitialized) {
- runtimeType = createRuntimeType();
+ final var type = runtimeJavaType();
+ if (type != null) {
+ runtimeType = createExternalRuntimeType(type);
+ }
runtimeTypeInitialized = true;
}
return Optional.ofNullable(runtimeType);
}
- final Optional<R> runtimeTypeOf(final @NonNull S stmt) {
- return recursiveRuntimeType().map(childType -> rebaseRuntimeType(childType, stmt));
+ /**
+ * Return the {@link Type} associated with this object at run-time, if applicable. This method often synonymous
+ * with {@code generatedType().orElseNull()}, but not always. For example
+ * <pre>
+ * <code>
+ * leaf foo {
+ * type string;
+ * }
+ * </code>
+ * </pre>
+ * Results in an empty {@link #generatedType()}, but still produces a {@code java.lang.String}-based
+ * {@link RuntimeType}.
+ *
+ * @return Associated {@link Type}
+ */
+ // FIXME: this should be a generic class argument
+ // FIXME: this needs a better name, but 'runtimeType' is already taken.
+ @Nullable Type runtimeJavaType() {
+ return generatedType().orElse(null);
}
- public final Optional<R> recursiveRuntimeType() {
- AbstractExplicitGenerator<S, R> gen = this;
+ /**
+ * Create the externally-accessible {@link RuntimeType} view of this object. The difference between
+ * this method and {@link #createInternalRuntimeType(EffectiveStatement)} is that this method represents the view
+ * attached to {@link #statement()} and contains a separate global view of all available augmentations attached to
+ * the GeneratedType.
+ *
+ * @param type {@link Type} associated with this object, as returned by {@link #runtimeJavaType()}
+ * @return Externally-accessible RuntimeType
+ */
+ abstract @NonNull R createExternalRuntimeType(@NonNull Type type);
+
+ /**
+ * Create the internally-accessible {@link RuntimeType} view of this object, if applicable. The difference between
+ * this method and {@link #createExternalRuntimeType()} is that this represents the view attached to the specified
+ * {@code stmt}, which is supplied by the parent statement. The returned {@link RuntimeType} always reports the
+ * global view of attached augmentations as empty.
+ *
+ * @param lookup context to use when looking up child statements
+ * @param stmt Statement for which to create the view
+ * @return Internally-accessible RuntimeType, or {@code null} if not applicable
+ */
+ final @Nullable R createInternalRuntimeType(final @NonNull AugmentResolver resolver, final @NonNull S stmt) {
+ // FIXME: cache requests: if we visited this statement, we obviously know what it entails. Note that we walk
+ // towards the original definition. As such, the cache may have to live in the generator we look up,
+ // but should operate on this statement to reflect lookups. This needs a bit of figuring out.
+ var gen = this;
do {
- final var ret = gen.runtimeType();
- if (ret.isPresent()) {
- return ret;
+ final var type = gen.runtimeJavaType();
+ if (type != null) {
+ return createInternalRuntimeType(resolver, stmt, type);
}
gen = gen.previous();
} while (gen != null);
- return Optional.empty();
+ return null;
}
- abstract @Nullable R createRuntimeType();
-
- abstract @NonNull R rebaseRuntimeType(@NonNull R type, @NonNull S statement);
+ abstract @NonNull R createInternalRuntimeType(@NonNull AugmentResolver resolver, @NonNull S statement,
+ @NonNull Type type);
@Override
public final boolean isAddedByUses() {
- return statement instanceof AddedByUsesAware && ((AddedByUsesAware) statement).isAddedByUses();
+ return statement instanceof AddedByUsesAware aware && aware.isAddedByUses();
}
@Override
public final boolean isAugmenting() {
- return statement instanceof CopyableNode && ((CopyableNode) statement).isAugmenting();
+ return statement instanceof CopyableNode copyable && copyable.isAugmenting();
}
/**
final @Nullable AbstractExplicitGenerator<?, ?> findLocalSchemaTreeGenerator(final QName qname) {
for (Generator child : this) {
- if (child instanceof AbstractExplicitGenerator) {
- final AbstractExplicitGenerator<?, ?> gen = (AbstractExplicitGenerator<?, ?>) child;
- final EffectiveStatement<?, ?> stmt = gen.statement();
- if (stmt instanceof SchemaTreeEffectiveStatement && qname.equals(stmt.argument())) {
- return gen;
- }
+ if (child instanceof AbstractExplicitGenerator<?, ?> gen
+ && gen.statement() instanceof SchemaTreeEffectiveStatement<?> stmt && qname.equals(stmt.argument())) {
+ return gen;
}
}
return null;
final @NonNull QName getQName() {
final Object arg = statement.argument();
- verify(arg instanceof QName, "Unexpected argument %s", arg);
- return (QName) arg;
+ if (arg instanceof QName qname) {
+ return qname;
+ }
+ throw new VerifyException("Unexpected argument " + arg);
}
@NonNull AbstractQName localName() {
// FIXME: this should be done in a nicer way
- final Object argument = statement.argument();
- verify(argument instanceof AbstractQName, "Illegal argument %s", argument);
- return (AbstractQName) argument;
+ final Object arg = statement.argument();
+ if (arg instanceof AbstractQName aqn) {
+ return aqn;
+ }
+ throw new VerifyException("Illegal argument " + arg);
}
@Override
}
MethodSignatureBuilder constructGetter(final GeneratedTypeBuilderBase<?> builder, final Type returnType) {
- return constructGetter(builder, returnType, BindingMapping.getGetterMethodName(localName().getLocalName()));
+ return constructGetter(builder, returnType, Naming.getGetterMethodName(localName().getLocalName()));
}
final MethodSignatureBuilder constructGetter(final GeneratedTypeBuilderBase<?> builder,
}
final void constructRequireImpl(final GeneratedTypeBuilderBase<?> builder, final Type returnType) {
- constructGetter(builder, returnType, BindingMapping.getRequireMethodName(localName().getLocalName()))
+ constructGetter(builder, returnType, Naming.getRequireMethodName(localName().getLocalName()))
.setDefault(true)
.setMechanics(ValueMechanics.NONNULL);
}
}
return helper;
}
+
+ static final @NonNull GeneratedType verifyGeneratedType(final Type type) {
+ if (type instanceof GeneratedType ret) {
+ return ret;
+ }
+ throw new VerifyException("Unexpected type " + type);
+ }
}