From: Robert Varga Date: Fri, 25 Feb 2022 16:06:13 +0000 (+0100) Subject: BindingRuntimeTypes should be an interface X-Git-Tag: v9.0.0~27 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=mdsal.git;a=commitdiff_plain;h=8f2a259e8bf106c4b33acd8df3a7dbe19aaa43d0 BindingRuntimeTypes should be an interface We do not want to expose the internals of how this interface is realized, make sure we split it into an interface and an implementation. JIRA: MDSAL-696 Change-Id: Icc01bc2c66cbf57c8cbb2ff9c32ac30c373b899d Signed-off-by: Robert Varga --- diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/BindingRuntimeTypesFactory.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/BindingRuntimeTypesFactory.java index bb54c9c5ab..8c5a494504 100644 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/BindingRuntimeTypesFactory.java +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/BindingRuntimeTypesFactory.java @@ -61,7 +61,7 @@ final class BindingRuntimeTypesFactory implements Mutable { factory.indexTypes(moduleGens); LOG.debug("Indexed {} generators in {}", moduleGens.size(), sw); - return new BindingRuntimeTypes(context, factory.augmentationToSchema, factory.typeToSchema, + return new DefaultBindingRuntimeTypes(context, factory.augmentationToSchema, factory.typeToSchema, factory.schemaToType, factory.identities); } diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/DefaultBindingRuntimeTypes.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/DefaultBindingRuntimeTypes.java new file mode 100644 index 0000000000..3f21a81125 --- /dev/null +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/DefaultBindingRuntimeTypes.java @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2018 Pantheon Technologies, s.r.o. 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; + +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; +import com.google.common.collect.BiMap; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.Multimap; +import com.google.common.collect.MultimapBuilder; +import java.util.Collection; +import java.util.IdentityHashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; +import org.eclipse.jdt.annotation.NonNull; +import org.opendaylight.mdsal.binding.model.api.GeneratedType; +import org.opendaylight.mdsal.binding.model.api.Type; +import org.opendaylight.mdsal.binding.runtime.api.BindingRuntimeTypes; +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.model.api.EffectiveModelContext; +import org.opendaylight.yangtools.yang.model.api.stmt.CaseEffectiveStatement; +import org.opendaylight.yangtools.yang.model.api.stmt.ChoiceEffectiveStatement; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +final class DefaultBindingRuntimeTypes implements BindingRuntimeTypes { + private static final Logger LOG = LoggerFactory.getLogger(DefaultBindingRuntimeTypes.class); + + private final @NonNull EffectiveModelContext schemaContext; + private final ImmutableMap typeToAugmentation; + private final ImmutableMap typeToSchema; + private final ImmutableMultimap choiceToCases; + private final ImmutableMap identities; + // Not Immutable as we use two different implementations + private final Map schemaToType; + + DefaultBindingRuntimeTypes(final EffectiveModelContext schemaContext, + final Map typeToAugmentation, + final Map typeToSchema, final Map schemaToType, + final Map identities) { + this.schemaContext = requireNonNull(schemaContext); + this.typeToAugmentation = ImmutableMap.copyOf(typeToAugmentation); + this.typeToSchema = ImmutableMap.copyOf(typeToSchema); + this.identities = ImmutableMap.copyOf(identities); + + // Careful to use identity for SchemaNodes, but only if needed + // FIXME: 8.0.0: YT should be switching to identity for equals(), so this should become unnecessary + Map copy; + try { + copy = ImmutableMap.copyOf(schemaToType); + } catch (IllegalArgumentException e) { + LOG.debug("Equality-duplicates found in {}", schemaToType.keySet()); + copy = new IdentityHashMap<>(schemaToType); + } + + this.schemaToType = copy; + + // Two-phase indexing of choice/case nodes. First we load all choices. Note we are using typeToSchema argument, + // not field, so as not to instantiate its entrySet. + final Set choiceTypes = typeToSchema.entrySet().stream() + .filter(entry -> entry.getValue() instanceof ChoiceEffectiveStatement) + .map(entry -> { + final Type key = entry.getKey(); + verify(key instanceof GeneratedType, "Unexpected choice type %s", key); + return (GeneratedType) key; + }) + .collect(Collectors.toUnmodifiableSet()); + + final Multimap builder = MultimapBuilder.hashKeys(choiceTypes.size()).arrayListValues().build(); + for (Entry entry : typeToSchema.entrySet()) { + if (entry.getValue() instanceof CaseEffectiveStatement) { + final Type type = entry.getKey(); + verify(type instanceof GeneratedType, "Unexpected case type %s", type); + builder.put(verifyNotNull(implementedChoiceType(((GeneratedType) type).getImplements(), choiceTypes), + "Cannot determine choice type for %s", type), type); + } + } + + choiceToCases = ImmutableMultimap.copyOf(builder); + } + + private static GeneratedType implementedChoiceType(final List impls, final Set choiceTypes) { + for (Type impl : impls) { + if (impl instanceof GeneratedType && choiceTypes.contains(impl)) { + return (GeneratedType) impl; + } + } + return null; + } + + DefaultBindingRuntimeTypes(final EffectiveModelContext schemaContext, + final Map typeToAugmentation, + final BiMap typeToDefiningSchema, final Map identities) { + this(schemaContext, typeToAugmentation, typeToDefiningSchema, typeToDefiningSchema.inverse(), identities); + } + + @Override + public EffectiveModelContext getEffectiveModelContext() { + return schemaContext; + } + + @Override + public Optional findAugmentation(final Type type) { + return Optional.ofNullable(typeToAugmentation.get(type)); + } + + @Override + public Optional findIdentity(final QName qname) { + return Optional.ofNullable(identities.get(qname)); + } + + @Override + public Optional findSchema(final Type type) { + return Optional.ofNullable(typeToSchema.get(type)); + } + + @Override + public Optional findType(final WithStatus schema) { + return Optional.ofNullable(schemaToType.get(schema)); + } + + @Override + public Optional findOriginalAugmentationType(final AugmentationSchemaNode augment) { + // If the augment statement does not contain any child nodes, we did not generate an augmentation, as it would + // be plain littering. + // FIXME: MDSAL-695: this check is rather costly (involves filtering), can we just rely on the not being found + // in the end? all we are saving is essentially two map lookups after all... + if (augment.getChildNodes().isEmpty()) { + return Optional.empty(); + } + + // FIXME: MDSAL-695: We should have enough information from mdsal-binding-generator to receive a (sparse) Map + // for current -> original lookup. When combined with schemaToType, this amounts to the + // inverse view of what 'typeToSchema' holds + AugmentationSchemaNode current = augment; + while (true) { + // If this augmentation has been added through 'uses foo { augment bar { ... } }', we need to invert that + // walk and arrive at the original declaration site, as that is where we generated 'grouping foo's + // augmentation. That site may have a different module, hence the augment namespace may be different. + final Optional original = current.getOriginalDefinition(); + if (original.isEmpty()) { + return findType(current); + } + current = original.orElseThrow(); + } + } + + @Override + public Multimap getChoiceToCases() { + return choiceToCases; + } + + @Override + public Collection findCases(final Type choiceType) { + return choiceToCases.get(choiceType); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("typeToAugmentation", typeToAugmentation) + .add("typeToSchema", typeToSchema) + .add("choiceToCases", choiceToCases) + .add("identities", identities) + .toString(); + } +} diff --git a/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/BindingRuntimeTypes.java b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/BindingRuntimeTypes.java index 8a54fe653e..d0ac16642a 100644 --- a/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/BindingRuntimeTypes.java +++ b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/BindingRuntimeTypes.java @@ -7,175 +7,34 @@ */ package org.opendaylight.mdsal.binding.runtime.api; -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.annotations.Beta; -import com.google.common.base.MoreObjects; -import com.google.common.collect.BiMap; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.Multimap; -import com.google.common.collect.MultimapBuilder; import java.util.Collection; -import java.util.IdentityHashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; import java.util.Optional; -import java.util.Set; -import java.util.stream.Collectors; -import org.eclipse.jdt.annotation.NonNull; -import org.opendaylight.mdsal.binding.model.api.GeneratedType; import org.opendaylight.mdsal.binding.model.api.Type; import org.opendaylight.yangtools.concepts.Immutable; 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.model.api.EffectiveModelContext; import org.opendaylight.yangtools.yang.model.api.EffectiveModelContextProvider; -import org.opendaylight.yangtools.yang.model.api.stmt.CaseEffectiveStatement; -import org.opendaylight.yangtools.yang.model.api.stmt.ChoiceEffectiveStatement; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** * The result of BindingGenerator run. Contains mapping between Types and SchemaNodes. */ @Beta -public final class BindingRuntimeTypes implements EffectiveModelContextProvider, Immutable { - private static final Logger LOG = LoggerFactory.getLogger(BindingRuntimeTypes.class); - - private final @NonNull EffectiveModelContext schemaContext; - private final ImmutableMap typeToAugmentation; - private final ImmutableMap typeToSchema; - private final ImmutableMultimap choiceToCases; - private final ImmutableMap identities; - // Not Immutable as we use two different implementations - private final Map schemaToType; - - public BindingRuntimeTypes(final EffectiveModelContext schemaContext, - final Map typeToAugmentation, - final Map typeToSchema, final Map schemaToType, - final Map identities) { - this.schemaContext = requireNonNull(schemaContext); - this.typeToAugmentation = ImmutableMap.copyOf(typeToAugmentation); - this.typeToSchema = ImmutableMap.copyOf(typeToSchema); - this.identities = ImmutableMap.copyOf(identities); - - // Careful to use identity for SchemaNodes, but only if needed - // FIXME: 8.0.0: YT should be switching to identity for equals(), so this should become unnecessary - Map copy; - try { - copy = ImmutableMap.copyOf(schemaToType); - } catch (IllegalArgumentException e) { - LOG.debug("Equality-duplicates found in {}", schemaToType.keySet()); - copy = new IdentityHashMap<>(schemaToType); - } - - this.schemaToType = copy; - - // Two-phase indexing of choice/case nodes. First we load all choices. Note we are using typeToSchema argument, - // not field, so as not to instantiate its entrySet. - final Set choiceTypes = typeToSchema.entrySet().stream() - .filter(entry -> entry.getValue() instanceof ChoiceEffectiveStatement) - .map(entry -> { - final Type key = entry.getKey(); - verify(key instanceof GeneratedType, "Unexpected choice type %s", key); - return (GeneratedType) key; - }) - .collect(Collectors.toUnmodifiableSet()); - - final Multimap builder = MultimapBuilder.hashKeys(choiceTypes.size()).arrayListValues().build(); - for (Entry entry : typeToSchema.entrySet()) { - if (entry.getValue() instanceof CaseEffectiveStatement) { - final Type type = entry.getKey(); - verify(type instanceof GeneratedType, "Unexpected case type %s", type); - builder.put(verifyNotNull(implementedChoiceType(((GeneratedType) type).getImplements(), choiceTypes), - "Cannot determine choice type for %s", type), type); - } - } - - choiceToCases = ImmutableMultimap.copyOf(builder); - } - - private static GeneratedType implementedChoiceType(final List impls, final Set choiceTypes) { - for (Type impl : impls) { - if (impl instanceof GeneratedType && choiceTypes.contains(impl)) { - return (GeneratedType) impl; - } - } - return null; - } - - public BindingRuntimeTypes(final EffectiveModelContext schemaContext, - final Map typeToAugmentation, - final BiMap typeToDefiningSchema, final Map identities) { - this(schemaContext, typeToAugmentation, typeToDefiningSchema, typeToDefiningSchema.inverse(), identities); - } - - @Override - public EffectiveModelContext getEffectiveModelContext() { - return schemaContext; - } - - public Optional findAugmentation(final Type type) { - return Optional.ofNullable(typeToAugmentation.get(type)); - } - - public Optional findIdentity(final QName qname) { - return Optional.ofNullable(identities.get(qname)); - } +public interface BindingRuntimeTypes extends EffectiveModelContextProvider, Immutable { - public Optional findSchema(final Type type) { - return Optional.ofNullable(typeToSchema.get(type)); - } + Optional findAugmentation(Type type); - public Optional findType(final WithStatus schema) { - return Optional.ofNullable(schemaToType.get(schema)); - } + Optional findIdentity(QName qname); - public Optional findOriginalAugmentationType(final AugmentationSchemaNode augment) { - // If the augment statement does not contain any child nodes, we did not generate an augmentation, as it would - // be plain littering. - // FIXME: MDSAL-695: this check is rather costly (involves filtering), can we just rely on the not being found - // in the end? all we are saving is essentially two map lookups after all... - if (augment.getChildNodes().isEmpty()) { - return Optional.empty(); - } + Optional findSchema(Type type); - // FIXME: MDSAL-695: We should have enough information from mdsal-binding-generator to receive a (sparse) Map - // for current -> original lookup. When combined with schemaToType, this amounts to the - // inverse view of what 'typeToSchema' holds - AugmentationSchemaNode current = augment; - while (true) { - // If this augmentation has been added through 'uses foo { augment bar { ... } }', we need to invert that - // walk and arrive at the original declaration site, as that is where we generated 'grouping foo's - // augmentation. That site may have a different module, hence the augment namespace may be different. - final Optional original = current.getOriginalDefinition(); - if (original.isEmpty()) { - return findType(current); - } - current = original.orElseThrow(); - } - } + Optional findType(WithStatus schema); - public Multimap getChoiceToCases() { - return choiceToCases; - } + Optional findOriginalAugmentationType(AugmentationSchemaNode augment); - public Collection findCases(final Type choiceType) { - return choiceToCases.get(choiceType); - } + Multimap getChoiceToCases(); - @Override - public String toString() { - return MoreObjects.toStringHelper(this) - .add("typeToAugmentation", typeToAugmentation) - .add("typeToSchema", typeToSchema) - .add("choiceToCases", choiceToCases) - .add("identities", identities) - .toString(); - } + Collection findCases(Type choiceType); }