Introduce AnnotationName 75/106075/3
authorRobert Varga <robert.varga@pantheon.tech>
Sat, 20 May 2023 12:48:55 +0000 (14:48 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Sat, 20 May 2023 14:15:24 +0000 (16:15 +0200)
We have data-facing construct names captured in yang-common, do the same
for RFC7952 annotations, introducing AnnotationName.

Change-Id: Iaedd0a8c76edf5f3927bd5d4d56723dd47a84d1e
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
18 files changed:
codec/yang-data-codec-xml/src/main/java/org/opendaylight/yangtools/yang/data/codec/xml/SchemaAwareXMLStreamNormalizedNodeStreamWriter.java
codec/yang-data-codec-xml/src/main/java/org/opendaylight/yangtools/yang/data/codec/xml/XmlParserStream.java
common/yang-common/src/main/java/org/opendaylight/yangtools/yang/common/AnnotationName.java [new file with mode: 0644]
data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/NormalizedMetadata.java
model/rfc7952-model-api/src/main/java/org/opendaylight/yangtools/rfc7952/model/api/AnnotationEffectiveStatement.java
model/rfc7952-model-api/src/main/java/org/opendaylight/yangtools/rfc7952/model/api/AnnotationSchemaNode.java
model/rfc7952-model-api/src/main/java/org/opendaylight/yangtools/rfc7952/model/api/AnnotationSchemaNodeAware.java
model/rfc7952-model-api/src/main/java/org/opendaylight/yangtools/rfc7952/model/api/AnnotationStatement.java
model/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/stmt/LeafListStatement.java
model/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/stmt/LeafStatement.java
model/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/stmt/TypeAwareDeclaredStatement.java
model/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/stmt/TypedefStatement.java
model/yang-model-spi/src/main/java/org/opendaylight/yangtools/yang/model/spi/SimpleSchemaContext.java
parser/rfc7952-parser-support/src/main/java/org/opendaylight/yangtools/rfc7952/parser/AnnotationEffectiveStatementImpl.java
parser/rfc7952-parser-support/src/main/java/org/opendaylight/yangtools/rfc7952/parser/AnnotationStatementImpl.java
parser/rfc7952-parser-support/src/main/java/org/opendaylight/yangtools/rfc7952/parser/AnnotationStatementSupport.java
parser/rfc7952-parser-support/src/main/java/org/opendaylight/yangtools/rfc7952/parser/RefAnnotationStatement.java
parser/rfc7952-parser-support/src/test/java/org/opendaylight/yangtools/rfc7952/parser/AnnotationTest.java

index 94ed17f369e0049db990ff80d808f27211ce6f16..b9e50c6f701c7329885ce31c7e20d28c8d3ebda9 100644 (file)
@@ -18,6 +18,7 @@ import javax.xml.stream.XMLStreamWriter;
 import javax.xml.transform.dom.DOMSource;
 import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.yangtools.rfc7952.model.api.AnnotationSchemaNode;
+import org.opendaylight.yangtools.yang.common.AnnotationName;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
@@ -58,7 +59,8 @@ final class SchemaAwareXMLStreamNormalizedNodeStreamWriter
     @Override
     String encodeAnnotationValue(final ValueWriter xmlWriter, final QName qname, final Object value)
             throws XMLStreamException {
-        final var optAnnotation = AnnotationSchemaNode.find(streamUtils.getEffectiveModelContext(), qname);
+        final var optAnnotation = AnnotationSchemaNode.find(streamUtils.getEffectiveModelContext(),
+            new AnnotationName(qname));
         if (optAnnotation.isPresent()) {
             return streamUtils.encodeValue(xmlWriter, resolveType(optAnnotation.orElseThrow().getType()), value,
                 qname.getModule());
index b462d3939615e4e96658f0861dd12ab7a5ac7e5b..19703cb426b306765e5b12b4e46a9d9fb8d3a614 100644 (file)
@@ -44,6 +44,7 @@ import javax.xml.transform.stax.StAXSource;
 import org.opendaylight.yangtools.rfc7952.model.api.AnnotationSchemaNode;
 import org.opendaylight.yangtools.rfc8528.model.api.MountPointSchemaNode;
 import org.opendaylight.yangtools.rfc8528.model.api.SchemaMountConstants;
+import org.opendaylight.yangtools.yang.common.AnnotationName;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.QNameModule;
 import org.opendaylight.yangtools.yang.common.XMLNamespace;
@@ -397,7 +398,8 @@ public final class XmlParserStream implements Closeable, Flushable {
             final Optional<QNameModule> optModule = resolveXmlNamespace(attributeNS);
             if (optModule.isPresent()) {
                 final QName qname = QName.create(optModule.orElseThrow(), localName);
-                final var optAnnotation = AnnotationSchemaNode.find(codecs.getEffectiveModelContext(), qname);
+                final var optAnnotation = AnnotationSchemaNode.find(codecs.getEffectiveModelContext(),
+                    new AnnotationName(qname));
                 if (optAnnotation.isPresent()) {
                     final AnnotationSchemaNode schema = optAnnotation.orElseThrow();
                     final Object value = codecs.codecFor(schema, stack)
diff --git a/common/yang-common/src/main/java/org/opendaylight/yangtools/yang/common/AnnotationName.java b/common/yang-common/src/main/java/org/opendaylight/yangtools/yang/common/AnnotationName.java
new file mode 100644 (file)
index 0000000..c4a4a40
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2019 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.common;
+
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.collect.Interner;
+import com.google.common.collect.Interners;
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.opendaylight.yangtools.concepts.Identifier;
+import org.opendaylight.yangtools.concepts.WritableObject;
+
+/**
+ * Name of an individual YANG annotation, as defined in
+ * <a href="https://www.rfc-editor.org/rfc/rfc7952#section-5.2.1">RFC7952</a>.
+ */
+@NonNullByDefault
+public record AnnotationName(QName qname) implements Identifier, WritableObject {
+    @java.io.Serial
+    private static final long serialVersionUID = 1L;
+    private static final Interner<AnnotationName> INTERNER = Interners.newWeakInterner();
+
+    public AnnotationName {
+        requireNonNull(qname);
+    }
+
+    public AnnotationName intern() {
+        final var cacheQName = qname.intern();
+
+        // Identity comparison is here on purpose, as we are deciding whether to potentially store 'qname'. It is
+        // important that it does not hold user-supplied reference (such a String instance from parsing of an XML
+        // document).
+        final var template = cacheQName == qname ? this : new AnnotationName(cacheQName);
+
+        return INTERNER.intern(template);
+    }
+
+    public static AnnotationName readFrom(final DataInput in) throws IOException {
+        return new AnnotationName(QName.readFrom(in));
+    }
+
+    @Override
+    public void writeTo(final DataOutput out) throws IOException {
+        qname.writeTo(out);
+    }
+}
index 791f7285ca1aa8c3ee5385a8eb8cede27b9d3114..dfdfc9f06c87c4b273aaab066d3285fcd5af9afe 100644 (file)
@@ -33,6 +33,7 @@ public interface NormalizedMetadata extends Immutable {
      *
      * @return The set of annotations attached to the corresponding data node.
      */
+    // FIXME: use AnnotationName instead of QName once we sort out the XML codec/NETCONF story
     @NonNull Map<QName, Object> getAnnotations();
 
     /**
index 2e0175b1b4cf4c1664e3e2e202f8af0ca7de4ec9..4d502a61a1cf6bc95ea7c3421ecd548a5d99ca91 100644 (file)
@@ -8,7 +8,7 @@
 package org.opendaylight.yangtools.rfc7952.model.api;
 
 import com.google.common.annotations.Beta;
-import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.AnnotationName;
 import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
 import org.opendaylight.yangtools.yang.model.api.stmt.TypeDefinitionAware;
 import org.opendaylight.yangtools.yang.model.api.stmt.UnknownEffectiveStatement;
@@ -18,7 +18,7 @@ import org.opendaylight.yangtools.yang.model.api.stmt.UnknownEffectiveStatement;
  * <a href="https://www.rfc-editor.org/rfc/rfc7952">RFC7952</a>.
  */
 @Beta
-public interface AnnotationEffectiveStatement extends UnknownEffectiveStatement<QName, AnnotationStatement>,
+public interface AnnotationEffectiveStatement extends UnknownEffectiveStatement<AnnotationName, AnnotationStatement>,
         TypeDefinitionAware {
     @Override
     default StatementDefinition statementDefinition() {
index 51be134fe8e7afcbb53b80927c27788cc85c54a5..3a743e621c7d6519240c8bffed08cda02324a76a 100644 (file)
@@ -9,12 +9,11 @@ package org.opendaylight.yangtools.rfc7952.model.api;
 
 import com.google.common.annotations.Beta;
 import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableMap.Builder;
 import java.util.Map;
 import java.util.Optional;
 import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.yangtools.yang.common.AnnotationName;
 import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.api.TypeAware;
 import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
@@ -29,21 +28,21 @@ public interface AnnotationSchemaNode extends UnknownSchemaNode, TypeAware {
      * Find specified annotation if it is supported by the specified SchemaContext.
      *
      * @param context SchemaContext to search
-     * @param qname Annotation name
+     * @param name Annotation name
      * @return {@link AnnotationSchemaNode} corresponding to specified name, or empty if it is not supported
      *         by the SchemaContext..
      * @throws NullPointerException if any of the arguments is null
      */
-    static @NonNull Optional<AnnotationSchemaNode> find(final SchemaContext context, final QName qname) {
-        if (context instanceof AnnotationSchemaNodeAware) {
-            return ((AnnotationSchemaNodeAware) context).findAnnotation(qname);
+    static @NonNull Optional<AnnotationSchemaNode> find(final SchemaContext context, final AnnotationName name) {
+        if (context instanceof AnnotationSchemaNodeAware aware) {
+            return aware.findAnnotation(name);
         }
 
-        return context.findModule(qname.getModule())
+        return context.findModule(name.qname().getModule())
             .flatMap(module -> module.getUnknownSchemaNodes().stream()
                 .filter(AnnotationSchemaNode.class::isInstance)
                 .map(AnnotationSchemaNode.class::cast)
-                .filter(annotation -> qname.equals(annotation.getQName()))
+                .filter(annotation -> name.equals(annotation.name()))
                 .findAny());
     }
 
@@ -54,19 +53,27 @@ public interface AnnotationSchemaNode extends UnknownSchemaNode, TypeAware {
      * @return {@link AnnotationSchemaNode}s supported by the SchemaContext..
      * @throws NullPointerException if context is null
      */
-    static @NonNull Map<QName, AnnotationSchemaNode> findAll(final SchemaContext context) {
-        final Builder<QName, AnnotationSchemaNode> builder = ImmutableMap.builder();
-        for (Module module : context.getModules()) {
-            for (UnknownSchemaNode node : module.getUnknownSchemaNodes()) {
-                if (node instanceof AnnotationSchemaNode) {
-                    builder.put(node.getQName(), (AnnotationSchemaNode) node);
+    static @NonNull Map<AnnotationName, AnnotationSchemaNode> findAll(final SchemaContext context) {
+        final var builder = ImmutableMap.<AnnotationName, AnnotationSchemaNode>builder();
+        for (var module : context.getModules()) {
+            for (var node : module.getUnknownSchemaNodes()) {
+                if (node instanceof AnnotationSchemaNode annotation) {
+                    builder.put(annotation.name(), annotation);
                 }
             }
         }
-
         return builder.build();
     }
 
+    default @NonNull AnnotationName name() {
+        return asEffectiveStatement().argument();
+    }
+
+    @Override
+    default QName getQName() {
+        return name().qname();
+    }
+
     @Override
     AnnotationEffectiveStatement asEffectiveStatement();
 }
index d7cee7e92fb32dea1b3368b1815342c68a218761..8efa8acfdf27de55494286b33cb3686c9fb18ff0 100644 (file)
@@ -10,21 +10,19 @@ package org.opendaylight.yangtools.rfc7952.model.api;
 import com.google.common.annotations.Beta;
 import java.util.Optional;
 import org.eclipse.jdt.annotation.NonNull;
-import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.AnnotationName;
 
 /**
  * Interface for entities which can lookup {@link AnnotationSchemaNode}s based on their name.
- *
- * @author Robert Varga
  */
 @Beta
 public interface AnnotationSchemaNodeAware {
     /**
      * Find an annotation based on its QName.
      *
-     * @param qname Annotation name
+     * @param name Annotation name
      * @return AnnotationSchemaNode if found
      * @throws NullPointerException if {@code qname} is null
      */
-    @NonNull Optional<AnnotationSchemaNode> findAnnotation(QName qname);
+    @NonNull Optional<AnnotationSchemaNode> findAnnotation(AnnotationName name);
 }
index 878892344afeb9d8276537473a8fbe1e81613500..8e5b26367867d97d8375c2530a87e2ca3a5fab94 100644 (file)
@@ -8,7 +8,7 @@
 package org.opendaylight.yangtools.rfc7952.model.api;
 
 import com.google.common.annotations.Beta;
-import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.AnnotationName;
 import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
 import org.opendaylight.yangtools.yang.model.api.stmt.DocumentedDeclaredStatement.WithStatus;
 import org.opendaylight.yangtools.yang.model.api.stmt.IfFeatureAwareDeclaredStatement;
@@ -20,10 +20,15 @@ import org.opendaylight.yangtools.yang.model.api.stmt.UnknownStatement;
  * <a href="https://www.rfc-editor.org/rfc/rfc7952">RFC7952</a>.
  */
 @Beta
-public interface AnnotationStatement extends UnknownStatement<QName>, WithStatus<QName>,
-        IfFeatureAwareDeclaredStatement<QName>, TypeAwareDeclaredStatement {
+public interface AnnotationStatement extends UnknownStatement<AnnotationName>, WithStatus<AnnotationName>,
+        IfFeatureAwareDeclaredStatement<AnnotationName>, TypeAwareDeclaredStatement<AnnotationName> {
     @Override
     default StatementDefinition statementDefinition() {
         return MetadataStatements.ANNOTATION;
     }
+
+    @Override
+    default String rawArgument() {
+        return argument().qname().getLocalName();
+    }
 }
index de80b6d3166c51f4bfc4259f234d09474e121b85..363dfbe274c17232f351b7f24b240215af46a92f 100644 (file)
@@ -16,7 +16,7 @@ import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
 /**
  * Declared representation of a {@code leaf-list} statement.
  */
-public interface LeafListStatement extends MultipleElementsDeclaredStatement, TypeAwareDeclaredStatement,
+public interface LeafListStatement extends MultipleElementsDeclaredStatement, TypeAwareDeclaredStatement<QName>,
         ConfigStatementAwareDeclaredStatement<QName>, MustStatementAwareDeclaredStatement<QName> {
     @Override
     default StatementDefinition statementDefinition() {
index e5eb61fd0d6f8bf847eb7947c9c0bf1c91f52312..410722d14bb0a3acbbb08e176c381b9967e48f89 100644 (file)
@@ -14,7 +14,7 @@ import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
 /**
  * Declared representation of a {@code leaf} statement.
  */
-public interface LeafStatement extends DataDefinitionStatement, TypeAwareDeclaredStatement,
+public interface LeafStatement extends DataDefinitionStatement, TypeAwareDeclaredStatement<QName>,
         ConfigStatementAwareDeclaredStatement<QName>, DefaultStatementAwareDeclaredStatement,
         MandatoryStatementAwareDeclaredStatement<QName>, MustStatementAwareDeclaredStatement<QName> {
     @Override
index 1046be628da5ac538fc986dd9f58872c50d851da..b9f9028794ff349a89ceaf4871ecbf61732e625e 100644 (file)
@@ -10,11 +10,10 @@ package org.opendaylight.yangtools.yang.model.api.stmt;
 import com.google.common.annotations.Beta;
 import java.util.Optional;
 import org.eclipse.jdt.annotation.NonNull;
-import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
 
 @Beta
-public interface TypeAwareDeclaredStatement extends DeclaredStatement<QName> {
+public interface TypeAwareDeclaredStatement<A> extends DeclaredStatement<A> {
     default @NonNull TypeStatement getType() {
         return findFirstDeclaredSubstatement(TypeStatement.class).orElseThrow();
     }
index b555d919b70a8871614ee21e649694915468f604..e4fb7336367a0a285c9153d0beb228d660f46688 100644 (file)
@@ -14,8 +14,8 @@ import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
 /**
  * Declared representation of a {@code typedef} statement.
  */
-public interface TypedefStatement extends DocumentedDeclaredStatement.WithStatus<QName>, TypeAwareDeclaredStatement,
-        DefaultStatementAwareDeclaredStatement {
+public interface TypedefStatement extends DocumentedDeclaredStatement.WithStatus<QName>,
+        TypeAwareDeclaredStatement<QName>, DefaultStatementAwareDeclaredStatement {
     @Override
     default StatementDefinition statementDefinition() {
         return YangStmtMapping.TYPEDEF;
index 1ee5ab62ee2e82c9eb391e5b4859c38cee4688e9..6adbeb75b8edac30711b7d7034e04a513383d48a 100644 (file)
@@ -28,7 +28,7 @@ import java.util.TreeMap;
 import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.yangtools.rfc7952.model.api.AnnotationSchemaNode;
 import org.opendaylight.yangtools.rfc7952.model.api.AnnotationSchemaNodeAwareSchemaContext;
-import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.AnnotationName;
 import org.opendaylight.yangtools.yang.common.QNameModule;
 import org.opendaylight.yangtools.yang.common.XMLNamespace;
 import org.opendaylight.yangtools.yang.model.api.Module;
@@ -44,7 +44,7 @@ public class SimpleSchemaContext extends AbstractSchemaContext implements Annota
     private final ImmutableSetMultimap<String, Module> nameToModules;
     private final ImmutableMap<QNameModule, Module> moduleMap;
     private final ImmutableSet<Module> modules;
-    private final ImmutableMap<QName, AnnotationSchemaNode> annotations;
+    private final ImmutableMap<AnnotationName, AnnotationSchemaNode> annotations;
 
     protected SimpleSchemaContext(final Collection<? extends @NonNull Module> modules) {
         /*
@@ -97,7 +97,7 @@ public class SimpleSchemaContext extends AbstractSchemaContext implements Annota
     }
 
     @Override
-    public final Optional<AnnotationSchemaNode> findAnnotation(final QName qname) {
+    public final Optional<AnnotationSchemaNode> findAnnotation(final AnnotationName qname) {
         return Optional.ofNullable(annotations.get(requireNonNull(qname)));
     }
 
index e0fae59008797756a669f071ad29d3a399c2ffba..c52ee2ecaa5ab2b694866e018e449077d8c82fda 100644 (file)
@@ -12,6 +12,7 @@ import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.yangtools.rfc7952.model.api.AnnotationEffectiveStatement;
 import org.opendaylight.yangtools.rfc7952.model.api.AnnotationSchemaNode;
 import org.opendaylight.yangtools.rfc7952.model.api.AnnotationStatement;
+import org.opendaylight.yangtools.yang.common.AnnotationName;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
@@ -23,14 +24,15 @@ import org.opendaylight.yangtools.yang.model.spi.meta.AbstractEffectiveUnknownSc
 import org.opendaylight.yangtools.yang.parser.spi.meta.EffectiveStmtCtx.Current;
 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
 
-final class AnnotationEffectiveStatementImpl extends AbstractEffectiveUnknownSchmemaNode<QName, AnnotationStatement>
+final class AnnotationEffectiveStatementImpl
+        extends AbstractEffectiveUnknownSchmemaNode<AnnotationName, AnnotationStatement>
         implements AnnotationEffectiveStatement, AnnotationSchemaNode {
     private final @NonNull TypeDefinition<?> type;
 
-    AnnotationEffectiveStatementImpl(final Current<QName, AnnotationStatement> stmt,
+    AnnotationEffectiveStatementImpl(final Current<AnnotationName, AnnotationStatement> stmt,
             final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
         super(stmt.declared(), stmt.argument(), stmt.history(), substatements);
-        final QName qname = stmt.getArgument();
+        final QName qname = stmt.getArgument().qname();
 
         // FIXME: move this into onFullDefinitionDeclared()
         final TypeEffectiveStatement<?> typeStmt = SourceException.throwIfNull(
@@ -43,11 +45,6 @@ final class AnnotationEffectiveStatementImpl extends AbstractEffectiveUnknownSch
         type = builder.build();
     }
 
-    @Override
-    public QName getQName() {
-        return argument();
-    }
-
     @Override
     public TypeDefinition<?> getType() {
         return type;
index 237c4e1661aa528e358c06547b90df2d621585f7..88505423cd256a226d18cdf83d15e9da99a22e66 100644 (file)
@@ -7,14 +7,32 @@
  */
 package org.opendaylight.yangtools.rfc7952.parser;
 
+import static java.util.Objects.requireNonNull;
+
 import com.google.common.collect.ImmutableList;
+import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.yangtools.rfc7952.model.api.AnnotationStatement;
-import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.AnnotationName;
 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
-import org.opendaylight.yangtools.yang.model.spi.meta.AbstractDeclaredStatement.WithQNameArgument.WithSubstatements;
+import org.opendaylight.yangtools.yang.model.spi.meta.AbstractDeclaredStatement;
+
+final class AnnotationStatementImpl extends AbstractDeclaredStatement<AnnotationName> implements AnnotationStatement {
+    private final @NonNull AnnotationName argument;
+    private final @NonNull Object substatements;
+
+    AnnotationStatementImpl(final AnnotationName argument,
+            final ImmutableList<? extends DeclaredStatement<?>> substatements) {
+        this.argument = requireNonNull(argument);
+        this.substatements = maskList(substatements);
+    }
+
+    @Override
+    public AnnotationName argument() {
+        return argument;
+    }
 
-final class AnnotationStatementImpl extends WithSubstatements implements AnnotationStatement {
-    AnnotationStatementImpl(final QName argument, final ImmutableList<? extends DeclaredStatement<?>> substatements) {
-        super(argument, substatements);
+    @Override
+    public ImmutableList<? extends DeclaredStatement<?>> declaredSubstatements() {
+        return unmaskList(substatements);
     }
 }
\ No newline at end of file
index b34779bb45307d62e181678164895eaeab4eefbc..92be01ba0fec3059336d5d16d33a86d506063c86 100644 (file)
@@ -11,7 +11,8 @@ import com.google.common.collect.ImmutableList;
 import org.opendaylight.yangtools.rfc7952.model.api.AnnotationEffectiveStatement;
 import org.opendaylight.yangtools.rfc7952.model.api.AnnotationStatement;
 import org.opendaylight.yangtools.rfc7952.model.api.MetadataStatements;
-import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.AnnotationName;
+import org.opendaylight.yangtools.yang.common.QNameModule;
 import org.opendaylight.yangtools.yang.model.api.YangStmtMapping;
 import org.opendaylight.yangtools.yang.model.api.meta.DeclarationReference;
 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
@@ -21,6 +22,7 @@ import org.opendaylight.yangtools.yang.parser.api.YangParserConfiguration;
 import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractStatementSupport;
 import org.opendaylight.yangtools.yang.parser.spi.meta.BoundStmtCtx;
 import org.opendaylight.yangtools.yang.parser.spi.meta.EffectiveStmtCtx.Current;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupport.StatementPolicy;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils;
@@ -28,7 +30,7 @@ import org.opendaylight.yangtools.yang.parser.spi.meta.SubstatementValidator;
 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
 
 public final class AnnotationStatementSupport
-         extends AbstractStatementSupport<QName, AnnotationStatement, AnnotationEffectiveStatement> {
+         extends AbstractStatementSupport<AnnotationName, AnnotationStatement, AnnotationEffectiveStatement> {
     private static final SubstatementValidator VALIDATOR = SubstatementValidator.builder(MetadataStatements.ANNOTATION)
         .addMandatory(YangStmtMapping.TYPE)
         .addOptional(YangStmtMapping.DESCRIPTION)
@@ -43,19 +45,27 @@ public final class AnnotationStatementSupport
     }
 
     @Override
-    public QName parseArgumentValue(final StmtContext<?, ?, ?> ctx, final String value) {
-        return StmtContextUtils.parseIdentifier(ctx, value);
+    public AnnotationName parseArgumentValue(final StmtContext<?, ?, ?> ctx, final String value) {
+        return new AnnotationName(StmtContextUtils.parseIdentifier(ctx, value)).intern();
     }
 
     @Override
-    public void onStatementAdded(final Mutable<QName, AnnotationStatement, AnnotationEffectiveStatement> stmt) {
+    public AnnotationName adaptArgumentValue(
+            final StmtContext<AnnotationName, AnnotationStatement, AnnotationEffectiveStatement> ctx,
+            final QNameModule targetModule) {
+        return new AnnotationName(ctx.getArgument().qname().bindTo(targetModule)).intern();
+    }
+
+    @Override
+    public void onStatementAdded(
+            final Mutable<AnnotationName, AnnotationStatement, AnnotationEffectiveStatement> stmt) {
         final StatementDefinition parentDef = stmt.coerceParentContext().publicDefinition();
         SourceException.throwIf(YangStmtMapping.MODULE != parentDef && YangStmtMapping.SUBMODULE != parentDef,
                 stmt, "Annotations may only be defined at root of either a module or a submodule");
     }
 
     @Override
-    protected AnnotationStatement createDeclared(final BoundStmtCtx<QName> ctx,
+    protected AnnotationStatement createDeclared(final BoundStmtCtx<AnnotationName> ctx,
             final ImmutableList<DeclaredStatement<?>> substatements) {
         return new AnnotationStatementImpl(ctx.getArgument(), substatements);
     }
@@ -67,7 +77,7 @@ public final class AnnotationStatementSupport
     }
 
     @Override
-    protected AnnotationEffectiveStatement createEffective(final Current<QName, AnnotationStatement> stmt,
+    protected AnnotationEffectiveStatement createEffective(final Current<AnnotationName, AnnotationStatement> stmt,
             final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
         return new AnnotationEffectiveStatementImpl(stmt, substatements);
     }
index 8cb52c4ba4630f46a0dfd81295b215e661fa0838..4efe8926df02c53263eaaeccc43c353e6e8b9968 100644 (file)
@@ -8,11 +8,11 @@
 package org.opendaylight.yangtools.rfc7952.parser;
 
 import org.opendaylight.yangtools.rfc7952.model.api.AnnotationStatement;
-import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.AnnotationName;
 import org.opendaylight.yangtools.yang.model.api.meta.DeclarationReference;
 import org.opendaylight.yangtools.yang.model.spi.meta.AbstractRefStatement;
 
-final class RefAnnotationStatement extends AbstractRefStatement<QName, AnnotationStatement>
+final class RefAnnotationStatement extends AbstractRefStatement<AnnotationName, AnnotationStatement>
         implements AnnotationStatement {
     RefAnnotationStatement(final AnnotationStatement delegate, final DeclarationReference ref) {
         super(delegate, ref);
index 251c581ea51f54b8f301befe93c83cb6fafbde80..277dc93c5b830778fbe0a5cb775754dc598c08bc 100644 (file)
@@ -7,16 +7,17 @@
  */
 package org.opendaylight.yangtools.rfc7952.parser;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import java.util.Optional;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.junit.Test;
 import org.opendaylight.yangtools.rfc7952.model.api.AnnotationSchemaNode;
+import org.opendaylight.yangtools.yang.common.AnnotationName;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
 import org.opendaylight.yangtools.yang.model.ri.type.BaseTypes;
@@ -27,8 +28,8 @@ import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
 import org.opendaylight.yangtools.yang.parser.stmt.reactor.CrossSourceStatementReactor;
 
 public class AnnotationTest {
-    private static final QName LAST_MODIFIED_QNAME = QName.create("http://example.org/example-last-modified",
-            "last-modified");
+    private static final AnnotationName LAST_MODIFIED =
+        new AnnotationName(QName.create("http://example.org/example-last-modified", "last-modified"));
     private static CrossSourceStatementReactor REACTOR;
 
     @BeforeClass
@@ -54,10 +55,10 @@ public class AnnotationTest {
 
         final var annotations = AnnotationSchemaNode.findAll(context);
         assertEquals(1, annotations.size());
-        final var annotation = annotations.get(LAST_MODIFIED_QNAME);
+        final var annotation = annotations.get(LAST_MODIFIED);
         assertNotNull(annotation);
 
-        final var findAnnotation = AnnotationSchemaNode.find(context, LAST_MODIFIED_QNAME);
+        final var findAnnotation = AnnotationSchemaNode.find(context, LAST_MODIFIED);
         assertTrue(findAnnotation.isPresent());
         assertSame(annotation, findAnnotation.orElseThrow());