Promote YangNamespaceContext 97/106297/1
authorRobert Varga <robert.varga@pantheon.tech>
Tue, 30 May 2023 21:09:36 +0000 (23:09 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Tue, 30 May 2023 21:09:36 +0000 (23:09 +0200)
This is a stable interface, update its API and promote it to non-@Beta.

Change-Id: I236e3b4bf4343362e32e0c291f5ef87d07b45713
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
common/yang-common/src/main/java/org/opendaylight/yangtools/yang/common/BiMapYangNamespaceContext.java
common/yang-common/src/main/java/org/opendaylight/yangtools/yang/common/YangNamespaceContext.java
model/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/ModuleNameNamespaceContext.java
parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/namespace/StmtNamespaceContext.java

index bdc74582744daace917f955856ee8added37aad5..8e230f3935eef6f072fd88ddf91a8ce7ec323093 100644 (file)
@@ -9,25 +9,18 @@ package org.opendaylight.yangtools.yang.common;
 
 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.ImmutableBiMap;
-import com.google.common.collect.ImmutableBiMap.Builder;
 import java.io.DataInput;
 import java.io.DataOutput;
 import java.io.IOException;
 import java.io.Serial;
-import java.util.Map.Entry;
-import java.util.Optional;
 import org.opendaylight.yangtools.concepts.WritableObject;
 
 /**
  * A BiMap-based implementation of {@link YangNamespaceContext}.
- *
- * @author Robert Varga
  */
-@Beta
 public final class BiMapYangNamespaceContext implements YangNamespaceContext, WritableObject {
     @Serial
     private static final long serialVersionUID = 1L;
@@ -39,19 +32,19 @@ public final class BiMapYangNamespaceContext implements YangNamespaceContext, Wr
     }
 
     @Override
-    public Optional<QNameModule> findNamespaceForPrefix(final String prefix) {
-        return Optional.ofNullable(mapping.get(requireNonNull(prefix)));
+    public QNameModule namespaceForPrefix(final String prefix) {
+        return mapping.get(requireNonNull(prefix));
     }
 
     @Override
-    public Optional<String> findPrefixForNamespace(final QNameModule namespace) {
-        return Optional.ofNullable(mapping.inverse().get(requireNonNull(namespace)));
+    public String prefixForNamespace(final QNameModule namespace) {
+        return mapping.inverse().get(requireNonNull(namespace));
     }
 
     @Override
     public void writeTo(final DataOutput out) throws IOException {
         out.writeInt(mapping.size());
-        for (Entry<String, QNameModule> entry : mapping.entrySet()) {
+        for (var entry : mapping.entrySet()) {
             out.writeUTF(entry.getKey());
             entry.getValue().writeTo(out);
         }
@@ -59,10 +52,10 @@ public final class BiMapYangNamespaceContext implements YangNamespaceContext, Wr
 
     public static BiMapYangNamespaceContext readFrom(final DataInput in) throws IOException {
         final int size = in.readInt();
-        final Builder<String, QNameModule> builder = ImmutableBiMap.builder();
+        final var builder = ImmutableBiMap.<String, QNameModule>builder();
         for (int i = 0; i < size; ++i) {
-            final String prefix = in.readUTF();
-            final QNameModule namespace = QNameModule.readFrom(in);
+            final var prefix = in.readUTF();
+            final var namespace = QNameModule.readFrom(in);
             builder.put(prefix, namespace);
         }
 
index 4b3a7ade7c310beb13d1267d2ab741f9cb4ac804..9e131a863e396d799cc649c447f48cc205a9e346 100644 (file)
@@ -7,12 +7,10 @@
  */
 package org.opendaylight.yangtools.yang.common;
 
-import static com.google.common.base.Preconditions.checkArgument;
-
-import com.google.common.annotations.Beta;
 import java.io.Serializable;
 import java.util.Optional;
 import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
 import org.opendaylight.yangtools.concepts.Immutable;
 
 /**
@@ -23,34 +21,59 @@ import org.opendaylight.yangtools.concepts.Immutable;
  * <p>
  * Each namespace context has a set of prefix/namespace mappings. A namespace can be bound to multiple prefixes at the
  * same time.
- *
- * @author Robert Varga
  */
-@Beta
 public interface YangNamespaceContext extends Immutable, Serializable {
     /**
      * Return QNameModule to which a particular prefix is bound.
      *
      * @param prefix Prefix to look up
+     * @return QNameModule bound to specified prefix, or {@code null}
+     * @throws NullPointerException if {@code prefix} is {@code null}
+     */
+    @Nullable QNameModule namespaceForPrefix(String prefix);
+
+    /**
+     * Return QNameModule to which a particular prefix is bound.
+     *
+     * @implSpec Default implementation defers to {@link #namespaceForPrefix(String)}
+     * @param prefix Prefix to look up
      * @return QNameModule bound to specified prefix
-     * @throws NullPointerException if {@code prefix} is null
+     * @throws NullPointerException if {@code prefix} is {@code null}
      */
-    @NonNull Optional<QNameModule> findNamespaceForPrefix(String prefix);
+    default @NonNull Optional<QNameModule> findNamespaceForPrefix(final String prefix) {
+        return Optional.ofNullable(namespaceForPrefix(prefix));
+    }
 
     /**
      * Return a prefix to which a particular QNameModule is bound. If a namespace is bound to multiple prefixes, it is
      * left unspecified which of those prefixes is returned.
      *
      * @param namespace QNameModule to look up
+     * @return Prefix to which the QNameModule is bound, or {@code null}
+     * @throws NullPointerException if {@code module} is {@code null}
+     */
+    @Nullable String prefixForNamespace(QNameModule namespace);
+
+    /**
+     * Return a prefix to which a particular QNameModule is bound. If a namespace is bound to multiple prefixes, it is
+     * left unspecified which of those prefixes is returned.
+     *
+     * @implSpec Default implementation defers to {@link #prefixForNamespace(QNameModule)}
+     * @param namespace QNameModule to look up
      * @return Prefix to which the QNameModule is bound
-     * @throws NullPointerException if {@code module} is null
+     * @throws NullPointerException if {@code module} is {@code null}
      */
-    @NonNull Optional<String> findPrefixForNamespace(QNameModule namespace);
+    default @NonNull Optional<String> findPrefixForNamespace(final QNameModule namespace) {
+        return Optional.ofNullable(prefixForNamespace(namespace));
+    }
 
     /**
      * Create a {@link QName} by resolving a prefix against currently-bound prefixes and combining it with specified
      * local name.
      *
+     * @implSpec
+     *     Default implementation defers to {@link #namespaceForPrefix(String)} and constructs QName based on its
+     *     return.
      * @param prefix Namespace prefix
      * @param localName QName local name
      * @return A QName.
@@ -59,8 +82,10 @@ public interface YangNamespaceContext extends Immutable, Serializable {
      *                                  prefix is not bound in this context.
      */
     default @NonNull QName createQName(final String prefix, final String localName) {
-        final Optional<QNameModule> namespace = findNamespaceForPrefix(prefix);
-        checkArgument(namespace.isPresent(), "Prefix %s is not bound", prefix);
-        return QName.create(namespace.orElseThrow(), localName);
+        final var namespace = namespaceForPrefix(prefix);
+        if (namespace == null) {
+            throw new IllegalArgumentException("Prefix " + prefix + " is not bound");
+        }
+        return QName.create(namespace, localName);
     }
 }
index 6a47fb6e38030801e61a11f33d32abba7b8df627..fee7619a543de86af906b476f2c7dc4205fcceb5 100644 (file)
@@ -10,7 +10,6 @@ package org.opendaylight.yangtools.yang.model.util;
 import com.google.common.annotations.Beta;
 import com.google.common.collect.ImmutableBiMap;
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
-import java.util.Optional;
 import org.opendaylight.yangtools.yang.common.BiMapYangNamespaceContext;
 import org.opendaylight.yangtools.yang.common.QNameModule;
 import org.opendaylight.yangtools.yang.common.YangNamespaceContext;
@@ -26,12 +25,11 @@ import org.opendaylight.yangtools.yang.model.spi.AbstractEffectiveModelContextPr
  * <p>
  * When multiple revisions of a particular namespace are present in the backing SchemaContext, this ambiguity is
  * resolved by using the latest revision available.
- *
- * @author Robert Varga
  */
 @Beta
 public final class ModuleNameNamespaceContext extends AbstractEffectiveModelContextProvider
         implements YangNamespaceContext {
+    @java.io.Serial
     private static final long serialVersionUID = 1L;
 
     @SuppressFBWarnings(value = "SE_NO_SUITABLE_CONSTRUCTOR", justification = "Handled through writeReplace()")
@@ -54,15 +52,17 @@ public final class ModuleNameNamespaceContext extends AbstractEffectiveModelCont
     }
 
     @Override
-    public Optional<QNameModule> findNamespaceForPrefix(final String prefix) {
-        return getEffectiveModelContext().findModules(prefix).stream().findFirst().map(Module::getQNameModule);
+    public QNameModule namespaceForPrefix(final String prefix) {
+        return getEffectiveModelContext().findModules(prefix).stream().findFirst().map(Module::getQNameModule)
+            .orElse(null);
     }
 
     @Override
-    public Optional<String> findPrefixForNamespace(final QNameModule namespace) {
-        return getEffectiveModelContext().findModule(namespace).map(Module::getName);
+    public String prefixForNamespace(final QNameModule namespace) {
+        return getEffectiveModelContext().findModule(namespace).map(Module::getName).orElse(null);
     }
 
+    @java.io.Serial
     private Object writeReplace() {
         return toBiMap();
     }
index f0f69a44745809bf0f696544b67b3252eaff636e..74c05b143d623a04f5c1a94f72a833062ae00d63 100644 (file)
@@ -7,15 +7,13 @@
  */
 package org.opendaylight.yangtools.yang.parser.rfc7950.namespace;
 
+import static java.util.Objects.requireNonNull;
+
 import com.google.common.collect.ImmutableBiMap;
 import com.google.common.collect.ImmutableMap;
 import java.util.HashMap;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Optional;
 import javax.xml.namespace.NamespaceContext;
 import org.opendaylight.yangtools.yang.common.QNameModule;
-import org.opendaylight.yangtools.yang.common.UnresolvedQName.Unqualified;
 import org.opendaylight.yangtools.yang.common.YangNamespaceContext;
 import org.opendaylight.yangtools.yang.model.api.stmt.SubmoduleStatement;
 import org.opendaylight.yangtools.yang.parser.spi.ParserNamespaces;
@@ -33,16 +31,16 @@ final class StmtNamespaceContext implements YangNamespaceContext {
 
     StmtNamespaceContext(final StmtContext<?, ?, ?> ctx) {
         // QNameModule -> prefix mappings
-        final Map<QNameModule, String> qnameToPrefix = ctx.namespace(ModuleQNameToPrefix.INSTANCE);
+        final var qnameToPrefix = ctx.namespace(ModuleQNameToPrefix.INSTANCE);
         moduleToPrefix = qnameToPrefix == null ? ImmutableBiMap.of() : ImmutableBiMap.copyOf(qnameToPrefix);
 
         // Additional mappings
-        final Map<String, QNameModule> additional = new HashMap<>();
-        final Map<String, StmtContext<?, ?, ?>> imports = ctx.namespace(ParserNamespaces.IMPORT_PREFIX_TO_MODULECTX);
+        final var additional = new HashMap<String, QNameModule>();
+        final var imports = ctx.namespace(ParserNamespaces.IMPORT_PREFIX_TO_MODULECTX);
         if (imports != null) {
-            for (Entry<String, StmtContext<?, ?, ?>> entry : imports.entrySet()) {
+            for (var entry : imports.entrySet()) {
                 if (!moduleToPrefix.containsValue(entry.getKey())) {
-                    QNameModule qnameModule = ctx.namespaceItem(ParserNamespaces.MODULECTX_TO_QNAME, entry.getValue());
+                    var qnameModule = ctx.namespaceItem(ParserNamespaces.MODULECTX_TO_QNAME, entry.getValue());
                     if (qnameModule == null && ctx.producesDeclared(SubmoduleStatement.class)) {
                         qnameModule = ctx.namespaceItem(ParserNamespaces.MODULE_NAME_TO_QNAME,
                             ctx.namespaceItem(ParserNamespaces.BELONGSTO_PREFIX_TO_MODULE_NAME, entry.getKey()));
@@ -55,11 +53,10 @@ final class StmtNamespaceContext implements YangNamespaceContext {
             }
         }
         if (ctx.producesDeclared(SubmoduleStatement.class)) {
-            final Map<String, Unqualified> belongsTo = ctx.namespace(ParserNamespaces.BELONGSTO_PREFIX_TO_MODULE_NAME);
+            final var belongsTo = ctx.namespace(ParserNamespaces.BELONGSTO_PREFIX_TO_MODULE_NAME);
             if (belongsTo != null) {
-                for (Entry<String, Unqualified> entry : belongsTo.entrySet()) {
-                    final QNameModule module = ctx.namespaceItem(ParserNamespaces.MODULE_NAME_TO_QNAME,
-                        entry.getValue());
+                for (var entry : belongsTo.entrySet()) {
+                    final var module = ctx.namespaceItem(ParserNamespaces.MODULE_NAME_TO_QNAME, entry.getValue());
                     if (module != null && !additional.containsKey(entry.getKey())) {
                         additional.put(entry.getKey(), module);
                     }
@@ -71,13 +68,14 @@ final class StmtNamespaceContext implements YangNamespaceContext {
     }
 
     @Override
-    public Optional<String> findPrefixForNamespace(final QNameModule namespace) {
-        return Optional.ofNullable(moduleToPrefix.get(namespace));
+    public String prefixForNamespace(final QNameModule namespace) {
+        return moduleToPrefix.get(requireNonNull(namespace));
     }
 
     @Override
-    public Optional<QNameModule> findNamespaceForPrefix(final String prefix) {
-        final QNameModule normal = moduleToPrefix.inverse().get(prefix);
-        return normal != null ? Optional.of(normal) : Optional.ofNullable(prefixToModule.get(prefix));
+    public QNameModule namespaceForPrefix(final String prefix) {
+        final var checked = requireNonNull(prefix);
+        final var normal = moduleToPrefix.inverse().get(checked);
+        return normal != null ? normal : prefixToModule.get(checked);
     }
 }