X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=binding%2Fmdsal-binding-generator-impl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fmdsal%2Fbinding%2Fgenerator%2Fimpl%2FModuleContext.java;h=617189b9ce9c8af3b694ad5add045c5a57050bd5;hb=9ab6fa0732bb152e682249dffe7cf940f79e66c5;hp=60ffe405039902edfceac6749c69981192f548fb;hpb=d45b654091cf3a65d4f5d51c856477be0c5dbade;p=mdsal.git diff --git a/binding/mdsal-binding-generator-impl/src/main/java/org/opendaylight/mdsal/binding/generator/impl/ModuleContext.java b/binding/mdsal-binding-generator-impl/src/main/java/org/opendaylight/mdsal/binding/generator/impl/ModuleContext.java index 60ffe40503..617189b9ce 100644 --- a/binding/mdsal-binding-generator-impl/src/main/java/org/opendaylight/mdsal/binding/generator/impl/ModuleContext.java +++ b/binding/mdsal-binding-generator-impl/src/main/java/org/opendaylight/mdsal/binding/generator/impl/ModuleContext.java @@ -7,6 +7,9 @@ */ package org.opendaylight.mdsal.binding.generator.impl; +import static com.google.common.base.Preconditions.checkState; +import static java.util.Objects.requireNonNull; + import com.google.common.collect.BiMap; import com.google.common.collect.HashBiMap; import com.google.common.collect.HashMultimap; @@ -20,34 +23,75 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; +import org.opendaylight.mdsal.binding.model.api.GeneratedType; +import org.opendaylight.mdsal.binding.model.api.JavaTypeName; import org.opendaylight.mdsal.binding.model.api.Type; import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTOBuilder; import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilder; +import org.opendaylight.mdsal.binding.spec.naming.BindingMapping; +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.CaseSchemaNode; +import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; import org.opendaylight.yangtools.yang.model.api.DocumentedNode.WithStatus; +import org.opendaylight.yangtools.yang.model.api.GroupingDefinition; +import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode; +import org.opendaylight.yangtools.yang.model.api.Module; +import org.opendaylight.yangtools.yang.model.api.NotificationDefinition; +import org.opendaylight.yangtools.yang.model.api.OperationDefinition; import org.opendaylight.yangtools.yang.model.api.SchemaNode; import org.opendaylight.yangtools.yang.model.api.SchemaPath; import org.opendaylight.yangtools.yang.model.api.TypeDefinition; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -public final class ModuleContext { - private GeneratedTypeBuilder moduleNode; - private final List genTOs = new ArrayList<>(); - private final Map typedefs = new HashMap<>(); +/** + * Utility class for building up Binding mapping information. This class is NOT thread-safe. + */ +public final class ModuleContext implements Mutable { + private static final Logger LOG = LoggerFactory.getLogger(ModuleContext.class); + + private final BiMap typeToAugmentation = HashBiMap.create(); private final Map childNodes = new HashMap<>(); private final Map groupings = new HashMap<>(); + private final BiMap caseTypeToSchema = HashBiMap.create(); private final Map cases = new HashMap<>(); - private final Map identities = new HashMap<>(); - private final Set topLevelNodes = new HashSet<>(); + private final Map identities = new HashMap<>(); private final List augmentations = new ArrayList<>(); - private final BiMap typeToAugmentation = HashBiMap.create(); - private final Map typeToSchema = new HashMap<>(); private final Multimap choiceToCases = HashMultimap.create(); - private final BiMap caseTypeToSchema = HashBiMap.create(); - + private final Set topLevelNodes = new HashSet<>(); + private final Map aliases = new HashMap<>(); + private final Map typeToSchema = new HashMap<>(); + private final List genTOs = new ArrayList<>(); private final Map innerTypes = new HashMap<>(); + private final Map typedefs = new HashMap<>(); + private final Module module; + + // Conflict mapping + private final Map nameMapping = new HashMap<>(); + + private GeneratedTypeBuilder moduleNode; + private String modulePackageName; + + ModuleContext(final Module module) { + this.module = requireNonNull(module); + } + + Module module() { + return module; + } + + String modulePackageName() { + String ret = modulePackageName; + if (ret == null) { + modulePackageName = ret = BindingMapping.getRootPackageName(module.getQNameModule()); + } + return ret; + } List getGeneratedTypes() { List result = new ArrayList<>(); @@ -73,7 +117,7 @@ public final class ModuleContext { for (GeneratedTypeBuilder b : cases.values()) { result.add(b.build()); } - for (GeneratedTOBuilder b : identities.values()) { + for (GeneratedTypeBuilder b : identities.values()) { result.add(b.build()); } for (GeneratedTypeBuilder b : topLevelNodes) { @@ -93,53 +137,84 @@ public final class ModuleContext { return moduleNode; } - public GeneratedTypeBuilder getChildNode(final SchemaPath p) { - return childNodes.get(p); + public GeneratedTypeBuilder getChildNode(final SchemaPath path) { + return childNodes.get(path); } - public GeneratedTypeBuilder getGrouping(final SchemaPath p) { - return groupings.get(p); + public GeneratedTypeBuilder getGrouping(final SchemaPath path) { + return groupings.get(path); } - public GeneratedTypeBuilder getCase(final SchemaPath p) { - return cases.get(p); + public GeneratedTypeBuilder getCase(final SchemaPath path) { + return cases.get(path); } - public void addModuleNode(final GeneratedTypeBuilder moduleNode) { - this.moduleNode = moduleNode; + public void addModuleNode(final GeneratedTypeBuilder newModuleNode) { + this.moduleNode = newModuleNode; } - public void addGeneratedTOBuilder(final GeneratedTOBuilder b) { - genTOs.add(b); + public void addGeneratedTOBuilder(final GeneratedTOBuilder builder) { + genTOs.add(builder); } - public void addChildNodeType(final SchemaNode p, final GeneratedTypeBuilder b) { - childNodes.put(p.getPath(), b); - typeToSchema.put(b,p); + @NonNull GeneratedType addAliasType(final ModuleContext sourceContext, final ContainerSchemaNode source, + final ContainerSchemaNode alias) { + final GeneratedTypeBuilder builder = sourceContext.getChildNode(source.getPath()); + checkState(builder != null, "Could not find builder for %s", source); + + final JavaTypeName id = builder.getIdentifier(); + final SchemaPath path = alias.getPath(); + final JavaTypeName prev = aliases.putIfAbsent(path, id); + checkState(prev == null, "Type aliasing conflict on %s: %s vs %s", path, prev, id); + + return builder.build(); } - public void addGroupingType(final SchemaPath p, final GeneratedTypeBuilder b) { - groupings.put(p, b); + @Nullable JavaTypeName getAlias(final SchemaPath path) { + return aliases.get(path); } - public void addTypedefType(final SchemaPath p, final Type t) { - typedefs.put(p, t); + public void addChildNodeType(final SchemaNode def, final GeneratedTypeBuilder builder) { + checkNamingConflict(def, builder.getIdentifier()); + childNodes.put(def.getPath(), builder); + typeToSchema.put(builder, def); } - public void addCaseType(final SchemaPath p, final GeneratedTypeBuilder b) { - cases.put(p, b); + public void addGroupingType(final GroupingDefinition def, final GeneratedTypeBuilder builder) { + checkNamingConflict(def, builder.getIdentifier()); + groupings.put(def.getPath(), builder); } - public void addIdentityType(final QName name,final GeneratedTOBuilder b) { - identities.put(name,b); + public void addTypedefType(final TypeDefinition def, final Type type) { + final JavaTypeName name = type.getIdentifier(); + final SchemaNode existingDef = nameMapping.putIfAbsent(name, def); + if (existingDef != null) { + if (!(existingDef instanceof TypeDefinition)) { + throw resolveNamingConfict(existingDef, def, name); + } + + // This seems to be fine + LOG.debug("GeneratedType conflict between {} and {} on {}", def, existingDef, name); + } + + typedefs.put(def.getPath(), type); } - public void addTopLevelNodeType(final GeneratedTypeBuilder b) { - topLevelNodes.add(b); + public void addCaseType(final SchemaPath path, final GeneratedTypeBuilder builder) { + cases.put(path, builder); } - public void addAugmentType(final GeneratedTypeBuilder b) { - augmentations.add(b); + public void addIdentityType(final IdentitySchemaNode def, final GeneratedTypeBuilder builder) { + checkNamingConflict(def, builder.getIdentifier()); + identities.put(def.getQName(), builder); + } + + public void addTopLevelNodeType(final GeneratedTypeBuilder builder) { + topLevelNodes.add(builder); + } + + public void addAugmentType(final GeneratedTypeBuilder builder) { + augmentations.add(builder); } public Map getTypedefs() { @@ -158,7 +233,7 @@ public final class ModuleContext { return Collections.unmodifiableMap(cases); } - public Map getIdentities() { + public Map getIdentities() { return Collections.unmodifiableMap(identities); } @@ -190,10 +265,8 @@ public final class ModuleContext { } /** - * - * Returns mapping of type to its schema. - * - * Valid values are only instances of {@link DataSchemaNode} or {@link AugmentationSchemaNode} + * Returns mapping of type to its schema. Valid values are only instances of {@link DataSchemaNode} + * or {@link AugmentationSchemaNode}. * * @return Mapping from type to corresponding schema */ @@ -207,9 +280,6 @@ public final class ModuleContext { /** * Adds mapping between schema path and an inner type. - * - * @param path - * @param type */ void addInnerTypedefType(final SchemaPath path, final Type type) { innerTypes.put(path, type); @@ -219,4 +289,52 @@ public final class ModuleContext { return innerTypes.get(path); } + private void checkNamingConflict(final SchemaNode def, final JavaTypeName name) { + final SchemaNode existingDef = nameMapping.putIfAbsent(name, def); + if (existingDef != null) { + if (def.equals(existingDef)) { + if (LOG.isDebugEnabled()) { + // TODO: this should not really be happening + LOG.debug("Duplicate definition on {} as {}", name, def, new Throwable()); + } + } else { + throw resolveNamingConfict(existingDef, def, name); + } + } + } + + private static IllegalStateException resolveNamingConfict(final SchemaNode existing, final SchemaNode incoming, + final JavaTypeName name) { + if (existing instanceof IdentitySchemaNode) { + if (incoming instanceof GroupingDefinition || incoming instanceof TypeDefinition + || incoming instanceof DataSchemaNode || incoming instanceof NotificationDefinition + || incoming instanceof OperationDefinition) { + return new RenameMappingException(name, existing); + } + } else if (existing instanceof GroupingDefinition) { + if (incoming instanceof IdentitySchemaNode) { + return new RenameMappingException(name, incoming); + } + if (incoming instanceof TypeDefinition || incoming instanceof DataSchemaNode + || incoming instanceof NotificationDefinition || incoming instanceof OperationDefinition) { + return new RenameMappingException(name, existing); + } + } else if (existing instanceof TypeDefinition) { + if (incoming instanceof GroupingDefinition || incoming instanceof IdentitySchemaNode) { + return new RenameMappingException(name, incoming); + } + if (incoming instanceof DataSchemaNode || incoming instanceof NotificationDefinition + || incoming instanceof OperationDefinition) { + return new RenameMappingException(name, existing); + } + } else { + if (incoming instanceof GroupingDefinition || incoming instanceof IdentitySchemaNode + || incoming instanceof TypeDefinition) { + return new RenameMappingException(name, incoming); + } + } + + return new IllegalStateException(String.format("Unhandled GeneratedType conflict between %s and %s on %s", + incoming, existing, name)); + } }