Add YangLibModule et al. 99/100999/16
authorRobert Varga <robert.varga@pantheon.tech>
Thu, 5 May 2022 00:21:56 +0000 (02:21 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Mon, 20 Jun 2022 12:10:01 +0000 (14:10 +0200)
Introduce ietf-yang-library equivalents and a resolver that trusts
them by default. This routes the information we need to the reactor.

JIRA: YANGTOOLS-837
Change-Id: Iab12347ea065f7d6351b0943ff3416fdb23eb0e5
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
parser/yang-parser-api/src/main/java/org/opendaylight/yangtools/yang/parser/api/YangLibModule.java [new file with mode: 0644]
parser/yang-parser-api/src/main/java/org/opendaylight/yangtools/yang/parser/api/YangLibModuleSet.java [new file with mode: 0644]
parser/yang-parser-api/src/main/java/org/opendaylight/yangtools/yang/parser/api/YangLibResolver.java [new file with mode: 0644]
parser/yang-parser-api/src/main/java/org/opendaylight/yangtools/yang/parser/api/YangLibSubmodule.java [new file with mode: 0644]
parser/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/impl/DefaultYangLibResolver.java [new file with mode: 0644]
parser/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/impl/DefaultYangParser.java

diff --git a/parser/yang-parser-api/src/main/java/org/opendaylight/yangtools/yang/parser/api/YangLibModule.java b/parser/yang-parser-api/src/main/java/org/opendaylight/yangtools/yang/parser/api/YangLibModule.java
new file mode 100644 (file)
index 0000000..fccfcc8
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2022 PANTHEON.tech, s.r.o. and others.  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.yangtools.yang.parser.api;
+
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.yangtools.yang.common.UnresolvedQName.Unqualified;
+import org.opendaylight.yangtools.yang.common.XMLNamespace;
+import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceRepresentation;
+import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
+
+/**
+ * A single <a href="https://www.rfc-editor.org/rfc/rfc8525">RFC8525</a> {@code module} or {@code import-only-module}
+ * list entry. Note that the YANG definition has two dissimilar instances, but that really is an artifact of how indexes
+ * work in YANG.
+ *
+ * @param identifier {@link SourceIdentifier} of this module, e.g. the combination of {@code name} and {@code revision}
+ * @param namespace {@link XMLNamespace} of this module
+ * @param submodules Submodules of this module
+ * @param features The set of supported features in this module
+ * @param deviationModuleNames Names of modules containing {@code deviate} statements targetting this module
+ * @param source A {@link SchemaSourceRepresentation} of the module
+ */
+public record YangLibModule(@NonNull SourceIdentifier identifier, @NonNull XMLNamespace namespace,
+        @NonNull ImmutableMap<Unqualified, YangLibSubmodule> submodules, @NonNull ImmutableSet<Unqualified> features,
+        @NonNull ImmutableSet<Unqualified> deviationModuleNames, @NonNull SchemaSourceRepresentation source) {
+    public YangLibModule {
+        requireNonNull(identifier);
+        requireNonNull(namespace);
+        requireNonNull(submodules);
+        requireNonNull(features);
+        requireNonNull(deviationModuleNames);
+    }
+}
diff --git a/parser/yang-parser-api/src/main/java/org/opendaylight/yangtools/yang/parser/api/YangLibModuleSet.java b/parser/yang-parser-api/src/main/java/org/opendaylight/yangtools/yang/parser/api/YangLibModuleSet.java
new file mode 100644 (file)
index 0000000..f718768
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2022 PANTHEON.tech, s.r.o. and others.  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.yangtools.yang.parser.api;
+
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.collect.ImmutableMap;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.yangtools.yang.common.UnresolvedQName.Unqualified;
+import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
+
+/**
+ * A single <a href="https://www.rfc-editor.org/rfc/rfc8525">RFC8525</a> {@code module-set}.
+ */
+public record YangLibModuleSet(@NonNull String name,
+        @NonNull ImmutableMap<Unqualified, YangLibModule> modules,
+        @NonNull ImmutableMap<SourceIdentifier, YangLibModule> importOnlyModules) {
+    public YangLibModuleSet {
+        requireNonNull(name);
+        requireNonNull(modules);
+        requireNonNull(importOnlyModules);
+    }
+}
diff --git a/parser/yang-parser-api/src/main/java/org/opendaylight/yangtools/yang/parser/api/YangLibResolver.java b/parser/yang-parser-api/src/main/java/org/opendaylight/yangtools/yang/parser/api/YangLibResolver.java
new file mode 100644 (file)
index 0000000..29b986c
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2022 PANTHEON.tech, s.r.o. and others.  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.yangtools.yang.parser.api;
+
+import com.google.common.annotations.Beta;
+import java.io.IOException;
+import java.util.Collection;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
+import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceRepresentation;
+
+/**
+ * A service capable of transforming a {@link YangLibModuleSet} to an {@link EffectiveModelContext}.
+ */
+@Beta
+public interface YangLibResolver {
+    /**
+     * Return enumeration of concrete types of {@link SchemaSourceRepresentation} this resolver supports. Users can use
+     * this information prepare the source they have to a representation which will be accepted by this resolver.
+     *
+     * @return Enumeration of supported schema source representations.
+     */
+    @NonNull Collection<Class<? extends SchemaSourceRepresentation>> supportedSourceRepresentations();
+
+    /**
+     * Build the effective view of a combined view of effective statements.
+     *
+     * @return Effective module statements indexed by their QNameModule.
+     * @throws IOException if a module source cannot be read
+     * @throws YangSyntaxErrorException when a syntactic error is encountered
+     * @throws NullPointerException if {@code moduleSet} is {@code null}
+     * @throws IllegalArgumentException if {@code moduleSet} references an unsupported
+     *                                  {@link SchemaSourceRepresentation}
+     */
+    @NonNull EffectiveModelContext resolveModuleSet(YangLibModuleSet moduleSet) throws IOException, YangParserException;
+}
diff --git a/parser/yang-parser-api/src/main/java/org/opendaylight/yangtools/yang/parser/api/YangLibSubmodule.java b/parser/yang-parser-api/src/main/java/org/opendaylight/yangtools/yang/parser/api/YangLibSubmodule.java
new file mode 100644 (file)
index 0000000..eae369c
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2022 PANTHEON.tech, s.r.o. and others.  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.yangtools.yang.parser.api;
+
+import static java.util.Objects.requireNonNull;
+
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceRepresentation;
+import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
+
+/**
+ * A single <a href="https://www.rfc-editor.org/rfc/rfc8525">RFC8525</a> {@code submodule} list entry.
+ *
+ * @param identifier {@link SourceIdentifier} of this submodule, e.g. the combination of {@code name} and
+ *        {@code revision}
+ * @param source A {@link SchemaSourceRepresentation} of the submodule
+ */
+public record YangLibSubmodule(@NonNull SourceIdentifier identifier, @NonNull SchemaSourceRepresentation source) {
+    public YangLibSubmodule {
+        requireNonNull(identifier);
+        requireNonNull(source);
+    }
+}
diff --git a/parser/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/impl/DefaultYangLibResolver.java b/parser/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/impl/DefaultYangLibResolver.java
new file mode 100644 (file)
index 0000000..e406b4a
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2022 PANTHEON.tech, s.r.o. and others.  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.yangtools.yang.parser.impl;
+
+import com.google.common.annotations.Beta;
+import com.google.common.collect.ImmutableSet;
+import java.io.IOException;
+import java.util.Collection;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import org.kohsuke.MetaInfServices;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.QNameModule;
+import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
+import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceRepresentation;
+import org.opendaylight.yangtools.yang.parser.api.YangLibModuleSet;
+import org.opendaylight.yangtools.yang.parser.api.YangLibResolver;
+import org.opendaylight.yangtools.yang.parser.api.YangParserException;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
+import org.opendaylight.yangtools.yang.parser.stmt.reactor.CrossSourceStatementReactor;
+import org.opendaylight.yangtools.yang.xpath.api.YangXPathParserFactory;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+/**
+ * Reference {@link YangLibResolver} implementation.
+ */
+@Beta
+@Singleton
+@MetaInfServices
+@Component(immediate = true)
+public final class DefaultYangLibResolver implements YangLibResolver {
+    private final CrossSourceStatementReactor reactor;
+
+    public DefaultYangLibResolver() {
+        reactor = DefaultReactors.defaultReactorBuilder().build();
+    }
+
+    @Inject
+    @Activate
+    public DefaultYangLibResolver(final @Reference YangXPathParserFactory xpathFactory) {
+        reactor = DefaultReactors.defaultReactorBuilder(xpathFactory).build();
+    }
+
+    @Override
+    public Collection<Class<? extends SchemaSourceRepresentation>> supportedSourceRepresentations() {
+        return DefaultYangParser.REPRESENTATIONS;
+    }
+
+    @Override
+    public EffectiveModelContext resolveModuleSet(final YangLibModuleSet moduleSet)
+            throws IOException, YangParserException {
+        final var act = reactor.newBuild();
+        final var features = ImmutableSet.<QName>builder();
+
+        for (var module : moduleSet.modules().values()) {
+            final var namespace = QNameModule.create(module.namespace(), module.identifier().revision());
+            for (var feat : module.features()) {
+                features.add(feat.bindTo(namespace));
+            }
+
+            act.addSource(DefaultYangParser.sourceToStatementStream(module.source()));
+        }
+
+        for (var module : moduleSet.importOnlyModules().values()) {
+            act.addLibSource(DefaultYangParser.sourceToStatementStream(module.source()));
+        }
+
+        try {
+            return act.setSupportedFeatures(features.build()).buildEffective();
+        } catch (ReactorException e) {
+            throw DefaultYangParser.decodeReactorException(e);
+        }
+    }
+}
index 647522a75b37c33380187cae81ae7e75e1fb5678..488bd5a0922df865719b8ede687787356e087ce8 100644 (file)
@@ -39,7 +39,7 @@ import org.opendaylight.yangtools.yang.parser.stmt.reactor.CrossSourceStatementR
 import org.xml.sax.SAXException;
 
 final class DefaultYangParser implements YangParser {
-    private static final @NonNull Collection<Class<? extends SchemaSourceRepresentation>> REPRESENTATIONS =
+    static final @NonNull Collection<Class<? extends SchemaSourceRepresentation>> REPRESENTATIONS =
             ImmutableList.of(IRSchemaSource.class, YangTextSchemaSource.class, YinDomSchemaSource.class,
                 YinXmlSchemaSource.class, YinTextSchemaSource.class);
 
@@ -99,12 +99,12 @@ final class DefaultYangParser implements YangParser {
         }
     }
 
-    private static YangParserException decodeReactorException(final ReactorException reported) {
+    static YangParserException decodeReactorException(final ReactorException reported) {
         // FIXME: map exception in some reasonable manner
         return new YangParserException("Failed to assemble sources", reported);
     }
 
-    private static StatementStreamSource sourceToStatementStream(final SchemaSourceRepresentation source)
+    static StatementStreamSource sourceToStatementStream(final SchemaSourceRepresentation source)
             throws IOException, YangSyntaxErrorException {
         requireNonNull(source);
         if (source instanceof IRSchemaSource) {