import static com.google.common.base.Verify.verify;
import com.google.common.base.Stopwatch;
-import java.util.Collection;
import java.util.HashMap;
-import java.util.IdentityHashMap;
import java.util.Map;
import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.mdsal.binding.generator.impl.reactor.AbstractExplicitGenerator;
import org.opendaylight.mdsal.binding.generator.impl.reactor.Generator;
import org.opendaylight.mdsal.binding.generator.impl.reactor.GeneratorReactor;
+import org.opendaylight.mdsal.binding.generator.impl.reactor.IdentityGenerator;
import org.opendaylight.mdsal.binding.generator.impl.reactor.ModuleGenerator;
+import org.opendaylight.mdsal.binding.generator.impl.reactor.RpcGenerator;
+import org.opendaylight.mdsal.binding.generator.impl.reactor.RpcInputGenerator;
+import org.opendaylight.mdsal.binding.generator.impl.reactor.RpcOutputGenerator;
import org.opendaylight.mdsal.binding.generator.impl.reactor.TypeBuilderFactory;
+import org.opendaylight.mdsal.binding.generator.impl.rt.DefaultBindingRuntimeTypes;
import org.opendaylight.mdsal.binding.model.api.GeneratedType;
-import org.opendaylight.mdsal.binding.model.api.Type;
+import org.opendaylight.mdsal.binding.model.api.JavaTypeName;
import org.opendaylight.mdsal.binding.runtime.api.BindingRuntimeTypes;
+import org.opendaylight.mdsal.binding.runtime.api.IdentityRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.InputRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.ModuleRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.OutputRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
import org.opendaylight.yangtools.concepts.Mutable;
import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.DocumentedNode.WithStatus;
+import org.opendaylight.yangtools.yang.common.QNameModule;
import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
-import org.opendaylight.yangtools.yang.model.api.TypedDataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.AugmentEffectiveStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.IdentityEffectiveStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.TypedefEffectiveStatement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
final class BindingRuntimeTypesFactory implements Mutable {
private static final Logger LOG = LoggerFactory.getLogger(BindingRuntimeTypesFactory.class);
- private final Map<Type, AugmentationSchemaNode> augmentationToSchema = new HashMap<>();
- private final Map<Type, WithStatus> typeToSchema = new HashMap<>();
- private final Map<QName, Type> identities = new HashMap<>();
-
- // Note: we are keying through WithStatus, but these nodes compare on semantics, so equivalent schema nodes
- // can result in two distinct types. We certainly need to keep them separate.
- private final Map<WithStatus, Type> schemaToType = new IdentityHashMap<>();
+ // Modules, indexed by their QNameModule
+ private final Map<QNameModule, ModuleRuntimeType> modules = new HashMap<>();
+ // Identities, indexed by their QName
+ private final Map<QName, IdentityRuntimeType> identities = new HashMap<>();
+ // All known types, indexed by their JavaTypeName
+ private final Map<JavaTypeName, RuntimeType> allTypes = new HashMap<>();
+ // All RpcOutputs, indexed by their RPC's QName
+ private final Map<QName, OutputRuntimeType> rpcOutputs = new HashMap<>();
+ // All RpcInputs, indexed by their RPC's QName
+ private final Map<QName, InputRuntimeType> rpcInputs = new HashMap<>();
private BindingRuntimeTypesFactory() {
// Hidden on purpose
}
static @NonNull BindingRuntimeTypes createTypes(final @NonNull EffectiveModelContext context) {
- final Collection<ModuleGenerator> moduleGens = new GeneratorReactor(context)
- .execute(TypeBuilderFactory.runtime())
- .values();
+ final var moduleGens = new GeneratorReactor(context).execute(TypeBuilderFactory.runtime());
final Stopwatch sw = Stopwatch.createStarted();
final BindingRuntimeTypesFactory factory = new BindingRuntimeTypesFactory();
- factory.indexTypes(moduleGens);
+ factory.indexModules(moduleGens);
LOG.debug("Indexed {} generators in {}", moduleGens.size(), sw);
- return new DefaultBindingRuntimeTypes(context, factory.augmentationToSchema, factory.typeToSchema,
- factory.schemaToType, factory.identities);
+ return new DefaultBindingRuntimeTypes(context, factory.modules, factory.allTypes, factory.identities,
+ factory.rpcInputs, factory.rpcOutputs);
}
- private void indexTypes(final Iterable<? extends Generator> generators) {
- for (Generator gen : generators) {
- gen.generatedType().ifPresent(type -> indexType(gen, type));
- indexTypes(gen);
- }
- }
+ private void indexModules(final Map<QNameModule, ModuleGenerator> moduleGens) {
+ for (var entry : moduleGens.entrySet()) {
+ final var modGen = entry.getValue();
- private void indexType(final @NonNull Generator generator, final @NonNull GeneratedType type) {
- if (generator instanceof AbstractExplicitGenerator) {
- final EffectiveStatement<?, ?> stmt = ((AbstractExplicitGenerator<?>) generator).statement();
- if (stmt instanceof IdentityEffectiveStatement) {
- identities.put(((IdentityEffectiveStatement) stmt).argument(), type);
- } else if (stmt instanceof AugmentEffectiveStatement) {
- verify(stmt instanceof AugmentationSchemaNode, "Unexpected statement %s", stmt);
- augmentationToSchema.put(type, (AugmentationSchemaNode) stmt);
- }
+ // index the module's runtime type
+ modGen.runtimeType().ifPresent(type -> {
+ safePut(modules, "modules", entry.getKey(), type);
+ });
- final WithStatus schema;
- if (stmt instanceof TypedDataSchemaNode) {
- schema = ((TypedDataSchemaNode) stmt).getType();
- } else if (stmt instanceof TypedefEffectiveStatement) {
- schema = ((TypedefEffectiveStatement) stmt).getTypeDefinition();
- } else if (stmt instanceof WithStatus) {
- schema = (WithStatus) stmt;
- } else {
- return;
+ // index module's identities and RPC input/outputs
+ for (var gen : modGen) {
+ if (gen instanceof IdentityGenerator) {
+ ((IdentityGenerator) gen).runtimeType().ifPresent(identity -> {
+ safePut(identities, "identities", identity.statement().argument(), identity);
+ });
+ }
+ // FIXME: do not collect these once we they generate a proper RuntimeType
+ if (gen instanceof RpcGenerator) {
+ final QName rpcName = ((RpcGenerator) gen).statement().argument();
+ for (var subgen : gen) {
+ if (subgen instanceof RpcInputGenerator) {
+ ((RpcInputGenerator) subgen).runtimeType()
+ .ifPresent(input -> rpcInputs.put(rpcName, input));
+ } else if (subgen instanceof RpcOutputGenerator) {
+ ((RpcOutputGenerator) subgen).runtimeType()
+ .ifPresent(output -> rpcOutputs.put(rpcName, output));
+ }
+ }
+ }
}
+ }
- typeToSchema.put(type, schema);
- final var prevType = schemaToType.put(schema, type);
- verify(prevType == null, "Conflicting types %s and %s on %s", type, prevType, schema);
+ indexRuntimeTypes(moduleGens.values());
+ }
+
+ private void indexRuntimeTypes(final Iterable<? extends Generator> generators) {
+ for (Generator gen : generators) {
+ if (gen instanceof AbstractExplicitGenerator && gen.generatedType().isPresent()) {
+ final var type = ((AbstractExplicitGenerator<?, ?>) gen).runtimeType().orElseThrow();
+ final var javaType = type.javaType();
+ if (javaType instanceof GeneratedType) {
+ final var name = javaType.getIdentifier();
+ final var prev = allTypes.put(name, type);
+ verify(prev == null || prev == type, "Conflict on runtime type mapping of %s between %s and %s",
+ name, prev, type);
+ }
+ }
+ indexRuntimeTypes(gen);
}
}
+
+ private static <K, V> void safePut(final Map<K, V> map, final String name, final K key, final V value) {
+ final var prev = map.put(key, value);
+ verify(prev == null, "Conflict in %s, key %s conflicts on %s versus %s", name, key, prev, value);
+ }
}