X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=binding%2Fmdsal-binding-runtime-spi%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fmdsal%2Fbinding%2Fruntime%2Fspi%2FModuleInfoSnapshotBuilder.java;h=363cdab4a37cfc42144e32c027c95ed7c6fa55d4;hb=e996a1b5aa1f8986deb917e0d1d77bd1dab0b82e;hp=785614323c6cdaf80e4ea18be52ce72a746585fa;hpb=79582aace5e6ecb2bbe3ec546d2b9a562f21ecf9;p=mdsal.git diff --git a/binding/mdsal-binding-runtime-spi/src/main/java/org/opendaylight/mdsal/binding/runtime/spi/ModuleInfoSnapshotBuilder.java b/binding/mdsal-binding-runtime-spi/src/main/java/org/opendaylight/mdsal/binding/runtime/spi/ModuleInfoSnapshotBuilder.java index 785614323c..363cdab4a3 100644 --- a/binding/mdsal-binding-runtime-spi/src/main/java/org/opendaylight/mdsal/binding/runtime/spi/ModuleInfoSnapshotBuilder.java +++ b/binding/mdsal-binding-runtime-spi/src/main/java/org/opendaylight/mdsal/binding/runtime/spi/ModuleInfoSnapshotBuilder.java @@ -7,23 +7,139 @@ */ package org.opendaylight.mdsal.binding.runtime.spi; +import static java.util.Objects.requireNonNull; + import com.google.common.annotations.Beta; -import java.util.NoSuchElementException; +import com.google.common.base.Throwables; +import com.google.common.collect.HashMultimap; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Multimaps; +import com.google.common.collect.SetMultimap; +import java.io.IOException; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Set; +import org.eclipse.jdt.annotation.NonNull; import org.opendaylight.mdsal.binding.runtime.api.ModuleInfoSnapshot; -import org.opendaylight.yangtools.concepts.CheckedBuilder; -import org.opendaylight.yangtools.yang.model.parser.api.YangParserFactory; -import org.opendaylight.yangtools.yang.parser.repo.YangTextSchemaContextResolver; +import org.opendaylight.yangtools.yang.binding.BindingObject; +import org.opendaylight.yangtools.yang.binding.DataRoot; +import org.opendaylight.yangtools.yang.binding.YangFeature; +import org.opendaylight.yangtools.yang.binding.YangModuleInfo; +import org.opendaylight.yangtools.yang.binding.contract.Naming; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.common.QNameModule; +import org.opendaylight.yangtools.yang.model.api.source.SourceIdentifier; +import org.opendaylight.yangtools.yang.model.api.stmt.FeatureSet; +import org.opendaylight.yangtools.yang.parser.api.YangParser; +import org.opendaylight.yangtools.yang.parser.api.YangParserException; +import org.opendaylight.yangtools.yang.parser.api.YangParserFactory; +import org.opendaylight.yangtools.yang.parser.api.YangSyntaxErrorException; @Beta -public final class ModuleInfoSnapshotBuilder extends AbstractModuleInfoTracker - implements CheckedBuilder { +public final class ModuleInfoSnapshotBuilder { + private final SetMultimap, YangFeature> moduleFeatures = HashMultimap.create(); + private final Set moduleInfos = new HashSet<>(); + private final YangParserFactory parserFactory; + + public ModuleInfoSnapshotBuilder(final YangParserFactory parserFactory) { + this.parserFactory = requireNonNull(parserFactory); + } + + @SuppressWarnings("checkstyle:illegalCatch") + public @NonNull ModuleInfoSnapshotBuilder add(final Class clazz) { + final YangModuleInfo moduleInfo; + try { + moduleInfo = BindingRuntimeHelpers.getYangModuleInfo(clazz); + } catch (Exception e) { + Throwables.throwIfUnchecked(e); + throw new IllegalStateException("Failed to introspect " + clazz, e); + } + + return add(moduleInfo); + } - public ModuleInfoSnapshotBuilder(final String name, final YangParserFactory parserFactory) { - super(YangTextSchemaContextResolver.create(name, parserFactory)); + @SafeVarargs + public final @NonNull ModuleInfoSnapshotBuilder add(final Class... classes) { + for (var clazz : classes) { + add(clazz); + } + return this; } - @Override - public synchronized ModuleInfoSnapshot build() { - return updateSnapshot(); + public @NonNull ModuleInfoSnapshotBuilder add(final YangModuleInfo info) { + ModuleInfoSnapshotResolver.flatDependencies(moduleInfos, info); + return this; + } + + public @NonNull ModuleInfoSnapshotBuilder add(final YangModuleInfo... infos) { + for (var info : infos) { + add(info); + } + return this; + } + + public @NonNull ModuleInfoSnapshotBuilder add(final Iterable infos) { + for (YangModuleInfo info : infos) { + add(info); + } + return this; + } + + public @NonNull ModuleInfoSnapshotBuilder addModuleFeatures(final Class module, + final Set> supportedFeatures) { + moduleFeatures.putAll(requireNonNull(module), ImmutableList.copyOf(supportedFeatures)); + return this; + } + + /** + * Build {@link ModuleInfoSnapshot} from all {@code moduleInfos} in this builder. + * + * @return Resulting {@link ModuleInfoSnapshot} + * @throws YangParserException if parsing any of the {@link YangModuleInfo} instances fails + */ + public @NonNull ModuleInfoSnapshot build() throws YangParserException { + final YangParser parser = parserFactory.createParser(); + + final var mappedInfos = new HashMap(); + final var classLoaders = new HashMap(); + final var namespaces = new HashMap(); + + for (var info : moduleInfos) { + final var source = ModuleInfoSnapshotResolver.toYangTextSource(info); + mappedInfos.put(source.sourceId(), info); + + final Class infoClass = info.getClass(); + final String infoRoot = Naming.getModelRootPackageName(infoClass.getPackage().getName()); + classLoaders.put(infoRoot, infoClass.getClassLoader()); + namespaces.put(infoRoot, info.getName().getModule()); + + try { + parser.addSource(source); + } catch (YangSyntaxErrorException | IOException e) { + throw new YangParserException("Failed to add source for " + info, e); + } + } + + if (!moduleFeatures.isEmpty()) { + final var featuresByModule = FeatureSet.builder(); + for (var entry : Multimaps.asMap(moduleFeatures).entrySet()) { + final var moduleData = entry.getKey(); + final var moduleRoot = Naming.getModelRootPackageName(moduleData.getPackage().getName()); + final var moduleNamespace = namespaces.get(moduleRoot); + if (moduleNamespace == null) { + throw new YangParserException("Failed to resolve namespace of " + moduleData); + } + + featuresByModule.addModuleFeatures(moduleNamespace, entry.getValue().stream() + .map(YangFeature::qname) + .map(QName::getLocalName) + .sorted() + .collect(ImmutableSet.toImmutableSet())); + } + parser.setSupportedFeatures(featuresByModule.build()); + } + + return new DefaultModuleInfoSnapshot(parser.buildEffectiveModel(), mappedInfos, classLoaders); } }