Require XPath parser implementation in RFC7950 reactors 40/87940/7
authorRobert Varga <robert.varga@pantheon.tech>
Thu, 20 Feb 2020 13:52:28 +0000 (14:52 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Fri, 21 Feb 2020 16:05:33 +0000 (17:05 +0100)
XPath parser is now considered full production ready and our system
needs to process XPaths at compile-time.

Flip to requiring a parser instance for all RFC7950-based reactors,
supplied by ServiceLoader when used in static contexts.

JIRA: YANGTOOLS-1085
Change-Id: I32f12d7285bc25c522606cd51f04312ac41a287f
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
25 files changed:
docs/pom.xml
features/odl-yangtools-parser/src/main/feature/feature.xml
features/odl-yangtools-xpath/src/main/feature/feature.xml [new file with mode: 0644]
yang/odlext-parser-support/pom.xml
yang/rfc6241-parser-support/pom.xml
yang/rfc6536-parser-support/pom.xml
yang/rfc7952-parser-support/pom.xml
yang/rfc8040-parser-support/pom.xml
yang/rfc8528-parser-support/pom.xml
yang/yang-parser-impl/pom.xml
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/impl/DefaultReactors.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/impl/OSGiYangParserFactory.java [new file with mode: 0644]
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/impl/YangParserFactoryImpl.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/impl/osgi/Activator.java [deleted file]
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/impl/osgi/package-info.java [deleted file]
yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/reactor/CustomCrossSourceStatementReactorBuilder.java
yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/reactor/RFC7950Reactors.java
yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/reactor/ServiceLoaderState.java [new file with mode: 0644]
yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/ArgumentUtils.java
yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/XPathSupport.java
yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/must/MustStatementSupport.java
yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/when/WhenStatementSupport.java
yang/yang-xpath-impl/pom.xml
yang/yang-xpath-impl/src/main/java/org/opendaylight/yangtools/yang/xpath/impl/Activator.java [deleted file]
yang/yang-xpath-impl/src/main/java/org/opendaylight/yangtools/yang/xpath/impl/AntlrXPathParserFactory.java

index a56e7acd98db1d467dfab795804c931221b430e9..313fa181d2895acc9915fa6d0482820520edb9da 100644 (file)
             <artifactId>metainf-services</artifactId>
             <scope>provided</scope>
         </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>osgi.cmpn</artifactId>
+            <scope>provided</scope>
+        </dependency>
         <dependency>
             <groupId>org.osgi</groupId>
             <artifactId>org.osgi.core</artifactId>
index 760cd874f5bae1167fc0a1cc06027ed56458d354..8f4b841215baf5cc759537650cfec1f94dd190ba 100644 (file)
@@ -2,5 +2,6 @@
 <features xmlns="http://karaf.apache.org/xmlns/features/v1.4.0" name="odl-yangtools-parser">
     <feature name="odl-yangtools-parser">
         <feature version="[6,7)">odl-antlr4</feature>
+        <feature>scr</feature>
     </feature>
 </features>
diff --git a/features/odl-yangtools-xpath/src/main/feature/feature.xml b/features/odl-yangtools-xpath/src/main/feature/feature.xml
new file mode 100644 (file)
index 0000000..291ab20
--- /dev/null
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<features xmlns="http://karaf.apache.org/xmlns/features/v1.4.0" name="odl-yangtools-xpath">
+    <feature name="odl-yangtools-xpath">
+        <feature>scr</feature>
+    </feature>
+</features>
index f0df632aa15c80159eface4957f7ebf460ed5d21..55be87d852cb5745e3da02f07f2e98e460d2adc1 100644 (file)
             <groupId>org.opendaylight.yangtools</groupId>
             <artifactId>yang-parser-rfc7950</artifactId>
         </dependency>
+
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-xpath-impl</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
     <build>
index a191ffce2662be41f37c1752cf29c66a75f77d51..3986cd563e6e505425cc75481bc439a4cfba553b 100644 (file)
             <groupId>org.opendaylight.yangtools</groupId>
             <artifactId>yang-common</artifactId>
         </dependency>
-
         <dependency>
             <groupId>org.opendaylight.yangtools</groupId>
             <artifactId>rfc6241-model-api</artifactId>
         </dependency>
-
         <dependency>
             <groupId>org.opendaylight.yangtools</groupId>
             <artifactId>yang-parser-rfc7950</artifactId>
         </dependency>
+
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-xpath-impl</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
     <build>
index cfd2c17116a6352cdd3d6b3c56dfab699ea0ce53..a63ad7851fc361b078b543545296e094f28827ea 100644 (file)
             <groupId>org.opendaylight.yangtools</groupId>
             <artifactId>yang-common</artifactId>
         </dependency>
-
         <dependency>
             <groupId>org.opendaylight.yangtools</groupId>
             <artifactId>rfc6536-model-api</artifactId>
         </dependency>
-
         <dependency>
             <groupId>org.opendaylight.yangtools</groupId>
             <artifactId>yang-parser-rfc7950</artifactId>
         </dependency>
+
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-xpath-impl</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
     <build>
index 05872cb297b98a561c9d44940756569ee4bb3615..8367def0246036f48fd1bdb3d6acd1b5e405f8b3 100644 (file)
             <groupId>org.opendaylight.yangtools</groupId>
             <artifactId>yang-common</artifactId>
         </dependency>
-
         <dependency>
             <groupId>org.opendaylight.yangtools</groupId>
             <artifactId>rfc7952-model-api</artifactId>
         </dependency>
-
         <dependency>
             <groupId>org.opendaylight.yangtools</groupId>
             <artifactId>yang-parser-rfc7950</artifactId>
         </dependency>
+
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-xpath-impl</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
     <build>
index d6619abcbfe8d4fc086c294419fd74630628674a..912bc345a554208bdbd7e5a9165cecf7b424405d 100644 (file)
             <groupId>org.opendaylight.yangtools</groupId>
             <artifactId>yang-common</artifactId>
         </dependency>
-
         <dependency>
             <groupId>org.opendaylight.yangtools</groupId>
             <artifactId>rfc8040-model-api</artifactId>
         </dependency>
-
         <dependency>
             <groupId>org.opendaylight.yangtools</groupId>
             <artifactId>yang-parser-rfc7950</artifactId>
         </dependency>
+
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-xpath-impl</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
     <build>
index 60703c055b82b6b7225d8aa5a2b78de0d41d4829..40ee8fb560f76e17142a425906f81498aa8307db 100644 (file)
             <groupId>org.opendaylight.yangtools</groupId>
             <artifactId>yang-common</artifactId>
         </dependency>
-
         <dependency>
             <groupId>org.opendaylight.yangtools</groupId>
             <artifactId>rfc8528-model-api</artifactId>
         </dependency>
-
         <dependency>
             <groupId>org.opendaylight.yangtools</groupId>
             <artifactId>yang-parser-rfc7950</artifactId>
         </dependency>
+
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-xpath-impl</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
     <build>
index 0f830bd92338981e78c263cb9794f788148f5f46..aea76021c64add6bdd3d1d31f33712ad4a5900fc 100644 (file)
             <artifactId>yang-xpath-impl</artifactId>
         </dependency>
 
-        <dependency>
-            <groupId>com.google.guava</groupId>
-            <artifactId>guava</artifactId>
-        </dependency>
         <dependency>
             <groupId>org.kohsuke.metainf-services</groupId>
             <artifactId>metainf-services</artifactId>
         </dependency>
         <dependency>
             <groupId>org.osgi</groupId>
-            <artifactId>org.osgi.core</artifactId>
+            <artifactId>osgi.cmpn</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>javax.inject</groupId>
+            <artifactId>javax.inject</artifactId>
+            <scope>provided</scope>
+            <optional>true</optional>
         </dependency>
     </dependencies>
 
                 <configuration>
                     <instructions>
                         <Automatic-Module-Name>org.opendaylight.yangtools.yang.parser.impl</Automatic-Module-Name>
-                        <Bundle-Activator>org.opendaylight.yangtools.yang.parser.impl.osgi.Activator</Bundle-Activator>
                     </instructions>
                 </configuration>
             </plugin>
index 3bcd1c6107b9d2e33ce7f87fd916acf56e5c51c5..35249717d0bbcf4845e812c2a5ad9e4b200246c6 100644 (file)
@@ -25,6 +25,7 @@ import org.opendaylight.yangtools.yang.parser.rfc7950.reactor.RFC7950Reactors;
 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
 import org.opendaylight.yangtools.yang.parser.stmt.reactor.CrossSourceStatementReactor;
 import org.opendaylight.yangtools.yang.parser.stmt.reactor.CrossSourceStatementReactor.Builder;
+import org.opendaylight.yangtools.yang.xpath.api.YangXPathParserFactory;
 
 /**
  * Utility class for instantiating default-configured {@link CrossSourceStatementReactor}s.
@@ -33,7 +34,10 @@ import org.opendaylight.yangtools.yang.parser.stmt.reactor.CrossSourceStatementR
  */
 @Beta
 public final class DefaultReactors {
-    private static final @NonNull CrossSourceStatementReactor DEFAULT_REACTOR = defaultReactorBuilder().build();
+    private static final class DefaultReactor {
+        // Thread-safe lazy init
+        static final @NonNull CrossSourceStatementReactor INSTANCE = defaultReactorBuilder().build();
+    }
 
     private DefaultReactors() {
         // Hidden on purpose
@@ -53,7 +57,7 @@ public final class DefaultReactors {
      * @return a shared default-configured reactor instance.
      */
     public static @NonNull CrossSourceStatementReactor defaultReactor() {
-        return DEFAULT_REACTOR;
+        return DefaultReactor.INSTANCE;
     }
 
     /**
@@ -62,8 +66,24 @@ public final class DefaultReactors {
      *
      * @return A populated CrossSourceStatementReactor builder.
      */
-    public static CustomCrossSourceStatementReactorBuilder defaultReactorBuilder() {
-        return RFC7950Reactors.defaultReactorBuilder()
+    public static @NonNull CustomCrossSourceStatementReactorBuilder defaultReactorBuilder() {
+        return addExtensions(RFC7950Reactors.defaultReactorBuilder());
+    }
+
+    /**
+     * Return a baseline CrossSourceStatementReactor {@link Builder}. The builder is initialized to the equivalent
+     * of the reactor returned via {@link #defaultReactor()}, but can be further customized before use.
+     *
+     * @return A populated CrossSourceStatementReactor builder.
+     */
+    public static @NonNull CustomCrossSourceStatementReactorBuilder defaultReactorBuilder(
+            final YangXPathParserFactory xpathFactory) {
+        return addExtensions(RFC7950Reactors.defaultReactorBuilder(xpathFactory));
+    }
+
+    private static @NonNull CustomCrossSourceStatementReactorBuilder addExtensions(
+            final @NonNull CustomCrossSourceStatementReactorBuilder builder) {
+        return builder
                 // AnyxmlSchemaLocation support
                 .addStatementSupport(ModelProcessingPhase.FULL_DECLARATION,
                     AnyxmlSchemaLocationStatementSupport.getInstance())
diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/impl/OSGiYangParserFactory.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/impl/OSGiYangParserFactory.java
new file mode 100644 (file)
index 0000000..3dcb2eb
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2020 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 java.util.Collection;
+import org.opendaylight.yangtools.yang.model.parser.api.YangParser;
+import org.opendaylight.yangtools.yang.model.parser.api.YangParserFactory;
+import org.opendaylight.yangtools.yang.model.repo.api.StatementParserMode;
+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.Deactivate;
+import org.osgi.service.component.annotations.Reference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Beta
+@Component(immediate = true)
+// FIXME: merge this with YangParserFactoryImpl once we have OSGi R7, which we really want because field injection is
+//        a static analysis pain. It also results in not-obvious classes like this one.
+public final class OSGiYangParserFactory implements YangParserFactory {
+    private static final Logger LOG = LoggerFactory.getLogger(OSGiYangParserFactory.class);
+
+    @Reference
+    YangXPathParserFactory xpathFactory = null;
+
+    private YangParserFactory delegate = null;
+
+    @Activate
+    void activate() {
+        delegate = new YangParserFactoryImpl(xpathFactory);
+        LOG.info("YANG Parser activated");
+    }
+
+    @Deactivate
+    void deactivate() {
+        LOG.info("YANG Parser deactivated");
+        delegate = null;
+    }
+
+    @Override
+    public Collection<StatementParserMode> supportedParserModes() {
+        return delegate.supportedParserModes();
+    }
+
+    @Override
+    public YangParser createParser(final StatementParserMode parserMode) {
+        return delegate.createParser(parserMode);
+    }
+}
index f64fb23d6454e532f49979e6ab0b37f0747e1816..7bc003d4e060144960d032522e54b0cfa3b7bbf7 100644 (file)
@@ -12,12 +12,15 @@ import static java.util.Objects.requireNonNull;
 import com.google.common.annotations.Beta;
 import com.google.common.collect.ImmutableList;
 import java.util.Collection;
+import javax.inject.Inject;
+import javax.inject.Singleton;
 import org.eclipse.jdt.annotation.NonNull;
 import org.kohsuke.MetaInfServices;
 import org.opendaylight.yangtools.yang.model.parser.api.YangParser;
 import org.opendaylight.yangtools.yang.model.parser.api.YangParserFactory;
 import org.opendaylight.yangtools.yang.model.repo.api.StatementParserMode;
 import org.opendaylight.yangtools.yang.parser.stmt.reactor.CrossSourceStatementReactor;
+import org.opendaylight.yangtools.yang.xpath.api.YangXPathParserFactory;
 
 /**
  * Reference {@link YangParserFactory} implementation.
@@ -26,6 +29,7 @@ import org.opendaylight.yangtools.yang.parser.stmt.reactor.CrossSourceStatementR
  */
 @Beta
 @MetaInfServices
+@Singleton
 public final class YangParserFactoryImpl implements YangParserFactory {
     private static final ImmutableList<StatementParserMode> SUPPORTED_MODES = ImmutableList.of(
         StatementParserMode.DEFAULT_MODE, StatementParserMode.SEMVER_MODE);
@@ -39,12 +43,17 @@ public final class YangParserFactoryImpl implements YangParserFactory {
         this(DefaultReactors.defaultReactor());
     }
 
+    @Inject
+    public YangParserFactoryImpl(final YangXPathParserFactory xpathFactory) {
+        this(DefaultReactors.defaultReactorBuilder(xpathFactory).build());
+    }
+
     /**
      * Construct a new {@link YangParserFactory} backed by specified reactor.
      *
      * @param reactor Backing reactor
      */
-    public YangParserFactoryImpl(@NonNull final CrossSourceStatementReactor reactor) {
+    public YangParserFactoryImpl(final @NonNull CrossSourceStatementReactor reactor) {
         this.reactor = requireNonNull(reactor);
     }
 
diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/impl/osgi/Activator.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/impl/osgi/Activator.java
deleted file mode 100644 (file)
index c42d0b3..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2017 Pantheon Technologies, 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.osgi;
-
-import org.eclipse.jdt.annotation.NonNull;
-import org.opendaylight.yangtools.yang.model.parser.api.YangParserFactory;
-import org.opendaylight.yangtools.yang.parser.impl.YangParserFactoryImpl;
-import org.osgi.framework.BundleActivator;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceRegistration;
-
-/**
- * YANG parser implementation activator. Publishes a {@link YangParserFactory} implementation on bundle start.
- *
- * @author Robert Varga
- */
-public final class Activator implements BundleActivator {
-    private ServiceRegistration<@NonNull YangParserFactory> registration;
-
-    @Override
-    public void start(final BundleContext context) throws Exception {
-        registration = context.registerService(YangParserFactory.class, new YangParserFactoryImpl(), null);
-    }
-
-    @Override
-    public void stop(final BundleContext context) throws Exception {
-        if (registration != null) {
-            registration.unregister();
-            registration = null;
-        }
-    }
-}
diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/impl/osgi/package-info.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/impl/osgi/package-info.java
deleted file mode 100644 (file)
index f052302..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Copyright (c) 2017 Pantheon Technologies, 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
- */
-/**
- * OSGi-specific YANG parser code. Contains activators and similar.
- */
-package org.opendaylight.yangtools.yang.parser.impl.osgi;
\ No newline at end of file
index 44884a2c6d51f9a2026bd860b12dc42fcd40d191..d9ebbfe8b3e62454cf968bef48883f800b142711 100644 (file)
@@ -50,31 +50,31 @@ public class CustomCrossSourceStatementReactorBuilder implements Builder<CrossSo
                 .put(ModelProcessingPhase.EFFECTIVE_MODEL, StatementSupportBundle.builder(supportedVersions)).build();
     }
 
-    public CustomCrossSourceStatementReactorBuilder addStatementSupport(final ModelProcessingPhase phase,
+    public @NonNull CustomCrossSourceStatementReactorBuilder addStatementSupport(final ModelProcessingPhase phase,
             final StatementSupport<?, ?, ?> stmtSupport) {
         reactorSupportBundles.get(phase).addSupport(stmtSupport);
         return this;
     }
 
-    public CustomCrossSourceStatementReactorBuilder overrideStatementSupport(final ModelProcessingPhase phase,
+    public @NonNull CustomCrossSourceStatementReactorBuilder overrideStatementSupport(final ModelProcessingPhase phase,
             final StatementSupport<?, ?, ?> stmtSupport) {
         reactorSupportBundles.get(phase).overrideSupport(stmtSupport);
         return this;
     }
 
-    public CustomCrossSourceStatementReactorBuilder addNamespaceSupport(final ModelProcessingPhase phase,
+    public @NonNull CustomCrossSourceStatementReactorBuilder addNamespaceSupport(final ModelProcessingPhase phase,
             final NamespaceBehaviour<?, ?, ?> namespaceSupport) {
         reactorSupportBundles.get(phase).addSupport(namespaceSupport);
         return this;
     }
 
-    public CustomCrossSourceStatementReactorBuilder addValidationBundle(final ValidationBundleType validationBundleType,
-            final Collection<StatementDefinition> validationBundle) {
+    public @NonNull CustomCrossSourceStatementReactorBuilder addValidationBundle(
+            final ValidationBundleType validationBundleType, final Collection<StatementDefinition> validationBundle) {
         reactorValidationBundles.put(validationBundleType, validationBundle);
         return this;
     }
 
-    public CustomCrossSourceStatementReactorBuilder addAllSupports(final ModelProcessingPhase phase,
+    public @NonNull CustomCrossSourceStatementReactorBuilder addAllSupports(final ModelProcessingPhase phase,
             final StatementSupportBundle stmtSupportBundle) {
         addAllCommonStatementSupports(phase, stmtSupportBundle.getCommonDefinitions().values());
         addAllVersionSpecificSupports(phase, stmtSupportBundle.getAllVersionSpecificDefinitions());
@@ -82,7 +82,7 @@ public class CustomCrossSourceStatementReactorBuilder implements Builder<CrossSo
         return this;
     }
 
-    public CustomCrossSourceStatementReactorBuilder addAllNamespaceSupports(final ModelProcessingPhase phase,
+    public @NonNull CustomCrossSourceStatementReactorBuilder addAllNamespaceSupports(final ModelProcessingPhase phase,
             final Collection<NamespaceBehaviour<?, ?, ?>> namespaceSupports) {
         final StatementSupportBundle.Builder stmtBundleBuilder = reactorSupportBundles.get(phase);
         for (final NamespaceBehaviour<?, ?, ?> namespaceSupport : namespaceSupports) {
@@ -91,8 +91,8 @@ public class CustomCrossSourceStatementReactorBuilder implements Builder<CrossSo
         return this;
     }
 
-    public CustomCrossSourceStatementReactorBuilder addAllCommonStatementSupports(final ModelProcessingPhase phase,
-            final Collection<StatementSupport<?, ?, ?>> statementSupports) {
+    public @NonNull CustomCrossSourceStatementReactorBuilder addAllCommonStatementSupports(
+            final ModelProcessingPhase phase, final Collection<StatementSupport<?, ?, ?>> statementSupports) {
         final StatementSupportBundle.Builder stmtBundleBuilder = reactorSupportBundles.get(phase);
         for (final StatementSupport<?, ?, ?> statementSupport : statementSupports) {
             stmtBundleBuilder.addSupport(statementSupport);
@@ -100,7 +100,8 @@ public class CustomCrossSourceStatementReactorBuilder implements Builder<CrossSo
         return this;
     }
 
-    public CustomCrossSourceStatementReactorBuilder addAllVersionSpecificSupports(final ModelProcessingPhase phase,
+    public @NonNull CustomCrossSourceStatementReactorBuilder addAllVersionSpecificSupports(
+            final ModelProcessingPhase phase,
             final Table<YangVersion, QName, StatementSupport<?, ?, ?>> versionSpecificSupports) {
         final StatementSupportBundle.Builder stmtBundleBuilder = reactorSupportBundles.get(phase);
         for (final Cell<YangVersion, QName, StatementSupport<?, ?, ?>> cell : versionSpecificSupports.cellSet()) {
index 202bb16358efd0a98804bd0c6b4469ae7a9f81f3..7c7cea8b7c693ee9ec5171a4895a36c91a8743b5 100644 (file)
@@ -11,17 +11,15 @@ import static org.opendaylight.yangtools.yang.common.YangVersion.VERSION_1;
 import static org.opendaylight.yangtools.yang.common.YangVersion.VERSION_1_1;
 
 import com.google.common.annotations.Beta;
-import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Sets;
-import java.util.Collection;
-import java.util.Map;
+import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.yangtools.yang.common.YangVersion;
-import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
 import org.opendaylight.yangtools.yang.parser.openconfig.stmt.OpenConfigVersionSupport;
 import org.opendaylight.yangtools.yang.parser.rfc7950.namespace.ChildSchemaNodeNamespace;
 import org.opendaylight.yangtools.yang.parser.rfc7950.namespace.ModuleQNameToPrefix;
 import org.opendaylight.yangtools.yang.parser.rfc7950.namespace.URIStringToImportPrefix;
+import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.XPathSupport;
 import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.action.ActionStatementSupport;
 import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.anydata.AnydataStatementSupport;
 import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.anyxml.AnyxmlStatementSupport;
@@ -149,6 +147,7 @@ import org.opendaylight.yangtools.yang.parser.spi.source.SupportedFeaturesNamesp
 import org.opendaylight.yangtools.yang.parser.spi.validation.ValidationBundlesNamespace;
 import org.opendaylight.yangtools.yang.parser.spi.validation.ValidationBundlesNamespace.ValidationBundleType;
 import org.opendaylight.yangtools.yang.parser.stmt.reactor.CrossSourceStatementReactor;
+import org.opendaylight.yangtools.yang.xpath.api.YangXPathParserFactory;
 
 /**
  * Utility class holding entrypoints for assembling RFC6020/RFC7950 statement {@link CrossSourceStatementReactor}s.
@@ -262,68 +261,6 @@ public final class RFC7950Reactors {
             .addSupport(StatementDefinitionNamespace.BEHAVIOUR)
             .build();
 
-    private static final StatementSupportBundle FULL_DECL_BUNDLE = StatementSupportBundle
-            .derivedFrom(STMT_DEF_BUNDLE)
-            .addSupport(LeafStatementSupport.getInstance())
-            .addSupport(ConfigStatementSupport.getInstance())
-            .addSupport(DeviationStatementSupport.getInstance())
-            .addVersionSpecificSupport(VERSION_1, DeviateStatementRFC6020Support.getInstance())
-            .addVersionSpecificSupport(VERSION_1_1, DeviateStatementRFC7950Support.getInstance())
-            .addVersionSpecificSupport(VERSION_1, ChoiceStatementRFC6020Support.getInstance())
-            .addVersionSpecificSupport(VERSION_1_1, ChoiceStatementRFC7950Support.getInstance())
-            .addVersionSpecificSupport(VERSION_1, CaseStatementRFC6020Support.getInstance())
-            .addVersionSpecificSupport(VERSION_1_1, CaseStatementRFC7950Support.getInstance())
-            .addSupport(MustStatementSupport.getInstance())
-            .addSupport(MandatoryStatementSupport.getInstance())
-            .addSupport(AnyxmlStatementSupport.getInstance())
-            .addVersionSpecificSupport(VERSION_1_1, AnydataStatementSupport.getInstance())
-            .addSupport(FeatureNamespace.BEHAVIOUR)
-            .addSupport(IfFeatureStatementSupport.getInstance())
-            .addSupport(UsesStatementSupport.getInstance())
-            .addSupport(GroupingNamespace.BEHAVIOUR)
-            .addSupport(ErrorMessageStatementSupport.getInstance())
-            .addSupport(ErrorAppTagStatementSupport.getInstance())
-            .addVersionSpecificSupport(VERSION_1, LeafListStatementRFC6020Support.getInstance())
-            .addVersionSpecificSupport(VERSION_1_1, LeafListStatementRFC7950Support.getInstance())
-            .addSupport(PresenceStatementSupport.getInstance())
-            .addSupport(MaxElementsStatementSupport.getInstance())
-            .addSupport(MinElementsStatementSupport.getInstance())
-            .addSupport(OrderedByStatementSupport.getInstance())
-            .addSupport(WhenStatementSupport.getInstance())
-            .addSupport(AugmentImplicitHandlingNamespace.BEHAVIOUR)
-            .addVersionSpecificSupport(VERSION_1, AugmentStatementRFC6020Support.getInstance())
-            .addVersionSpecificSupport(VERSION_1_1, AugmentStatementRFC7950Support.getInstance())
-            .addVersionSpecificSupport(VERSION_1, RefineStatementRFC6020Support.getInstance())
-            .addVersionSpecificSupport(VERSION_1_1, RefineStatementRFC7950Support.getInstance())
-            .addSupport(FeatureStatementSupport.getInstance())
-            .addSupport(PositionStatementSupport.getInstance())
-            .addSupport(ValueStatementSupport.getInstance())
-            .build();
-
-    private static final Map<ModelProcessingPhase, StatementSupportBundle> RFC7950_BUNDLES =
-            ImmutableMap.<ModelProcessingPhase, StatementSupportBundle>builder()
-            .put(ModelProcessingPhase.INIT, INIT_BUNDLE)
-            .put(ModelProcessingPhase.SOURCE_PRE_LINKAGE, PRE_LINKAGE_BUNDLE)
-            .put(ModelProcessingPhase.SOURCE_LINKAGE, LINKAGE_BUNDLE)
-            .put(ModelProcessingPhase.STATEMENT_DEFINITION, STMT_DEF_BUNDLE)
-            .put(ModelProcessingPhase.FULL_DECLARATION, FULL_DECL_BUNDLE)
-            .put(ModelProcessingPhase.EFFECTIVE_MODEL, FULL_DECL_BUNDLE)
-            .build();
-
-    private static final Map<ValidationBundleType, Collection<StatementDefinition>> RFC6020_VALIDATION_BUNDLE =
-            ImmutableMap.<ValidationBundleType, Collection<StatementDefinition>>builder()
-            .put(ValidationBundleType.SUPPORTED_REFINE_SUBSTATEMENTS,
-                YangValidationBundles.SUPPORTED_REFINE_SUBSTATEMENTS)
-            .put(ValidationBundleType.SUPPORTED_AUGMENT_TARGETS, YangValidationBundles.SUPPORTED_AUGMENT_TARGETS)
-
-            // FIXME: 5.0.0: we do not seem to need this validation bundle
-            .put(ValidationBundleType.SUPPORTED_CASE_SHORTHANDS, YangValidationBundles.SUPPORTED_CASE_SHORTHANDS)
-
-            .put(ValidationBundleType.SUPPORTED_DATA_NODES, YangValidationBundles.SUPPORTED_DATA_NODES)
-            .build();
-
-    private static final CrossSourceStatementReactor DEFAULT_RFC6020_RFC7950_REACTOR = defaultReactorBuilder().build();
-    private static final CrossSourceStatementReactor VANILLA_RFC6020_RFC7950_REACTOR = vanillaReactorBuilder().build();
 
     private RFC7950Reactors() {
         // Hidden on purpose
@@ -336,8 +273,8 @@ public final class RFC7950Reactors {
      *
      * @return A shared reactor instance.
      */
-    public static CrossSourceStatementReactor defaultReactor() {
-        return DEFAULT_RFC6020_RFC7950_REACTOR;
+    public static @NonNull CrossSourceStatementReactor defaultReactor() {
+        return ServiceLoaderState.DefaultReactor.INSTANCE;
     }
 
     /**
@@ -346,8 +283,18 @@ public final class RFC7950Reactors {
      *
      * @return A new {@link CustomCrossSourceStatementReactorBuilder}.
      */
-    public static CustomCrossSourceStatementReactorBuilder defaultReactorBuilder() {
-        return vanillaReactorBuilder()
+    public static @NonNull CustomCrossSourceStatementReactorBuilder defaultReactorBuilder() {
+        return addExtensions(vanillaReactorBuilder());
+    }
+
+    public static @NonNull CustomCrossSourceStatementReactorBuilder defaultReactorBuilder(
+            final YangXPathParserFactory xpathFactory) {
+        return addExtensions(vanillaReactorBuilder(xpathFactory));
+    }
+
+    private static @NonNull CustomCrossSourceStatementReactorBuilder addExtensions(
+            final @NonNull CustomCrossSourceStatementReactorBuilder builder) {
+        return builder
                 // Semantic version support
                 .addStatementSupport(ModelProcessingPhase.SOURCE_LINKAGE, OpenConfigVersionSupport.getInstance())
                 .addNamespaceSupport(ModelProcessingPhase.SOURCE_LINKAGE, SemanticVersionNamespace.BEHAVIOUR)
@@ -363,8 +310,8 @@ public final class RFC7950Reactors {
      *
      * @return A shared reactor instance.
      */
-    public static CrossSourceStatementReactor vanillaReactor() {
-        return VANILLA_RFC6020_RFC7950_REACTOR;
+    public static @NonNull CrossSourceStatementReactor vanillaReactor() {
+        return ServiceLoaderState.VanillaReactor.INSTANCE;
     }
 
     /**
@@ -373,15 +320,75 @@ public final class RFC7950Reactors {
      *
      * @return A new {@link CustomCrossSourceStatementReactorBuilder}.
      */
-    public static CustomCrossSourceStatementReactorBuilder vanillaReactorBuilder() {
-        return addDefaultRFC7950Bundles(new CustomCrossSourceStatementReactorBuilder(SUPPORTED_VERSIONS));
+    public static @NonNull CustomCrossSourceStatementReactorBuilder vanillaReactorBuilder() {
+        return vanillaReactorBuilder(ServiceLoaderState.XPath.INSTANCE);
+    }
+
+    public static @NonNull CustomCrossSourceStatementReactorBuilder vanillaReactorBuilder(
+            final @NonNull YangXPathParserFactory xpathFactory) {
+        return vanillaReactorBuilder(new XPathSupport(xpathFactory));
     }
 
-    private static CustomCrossSourceStatementReactorBuilder addDefaultRFC7950Bundles(
-            final CustomCrossSourceStatementReactorBuilder builder) {
-        RFC7950_BUNDLES.entrySet().forEach(entry -> builder.addAllSupports(entry.getKey(), entry.getValue()));
-        RFC6020_VALIDATION_BUNDLE.entrySet().forEach(
-            entry -> builder.addValidationBundle(entry.getKey(), entry.getValue()));
-        return builder;
+    private static @NonNull CustomCrossSourceStatementReactorBuilder vanillaReactorBuilder(
+            final @NonNull XPathSupport xpathSupport) {
+        final StatementSupportBundle fullDeclarationBundle = fullDeclarationBundle(xpathSupport);
+        return new CustomCrossSourceStatementReactorBuilder(SUPPORTED_VERSIONS)
+                .addAllSupports(ModelProcessingPhase.INIT, INIT_BUNDLE)
+                .addAllSupports(ModelProcessingPhase.SOURCE_PRE_LINKAGE, PRE_LINKAGE_BUNDLE)
+                .addAllSupports(ModelProcessingPhase.SOURCE_LINKAGE, LINKAGE_BUNDLE)
+                .addAllSupports(ModelProcessingPhase.STATEMENT_DEFINITION, STMT_DEF_BUNDLE)
+                .addAllSupports(ModelProcessingPhase.FULL_DECLARATION, fullDeclarationBundle)
+                .addAllSupports(ModelProcessingPhase.EFFECTIVE_MODEL, fullDeclarationBundle)
+                .addValidationBundle(ValidationBundleType.SUPPORTED_REFINE_SUBSTATEMENTS,
+                    YangValidationBundles.SUPPORTED_REFINE_SUBSTATEMENTS)
+                .addValidationBundle(ValidationBundleType.SUPPORTED_AUGMENT_TARGETS,
+                    YangValidationBundles.SUPPORTED_AUGMENT_TARGETS)
+
+                // FIXME: 5.0.0: we do not seem to need this validation bundle
+                .addValidationBundle(ValidationBundleType.SUPPORTED_CASE_SHORTHANDS,
+                    YangValidationBundles.SUPPORTED_CASE_SHORTHANDS)
+
+                .addValidationBundle(ValidationBundleType.SUPPORTED_DATA_NODES,
+                    YangValidationBundles.SUPPORTED_DATA_NODES);
+    }
+
+    private static @NonNull StatementSupportBundle fullDeclarationBundle(final XPathSupport xpathSupport) {
+        return StatementSupportBundle
+            .derivedFrom(STMT_DEF_BUNDLE)
+            .addSupport(LeafStatementSupport.getInstance())
+            .addSupport(ConfigStatementSupport.getInstance())
+            .addSupport(DeviationStatementSupport.getInstance())
+            .addVersionSpecificSupport(VERSION_1, DeviateStatementRFC6020Support.getInstance())
+            .addVersionSpecificSupport(VERSION_1_1, DeviateStatementRFC7950Support.getInstance())
+            .addVersionSpecificSupport(VERSION_1, ChoiceStatementRFC6020Support.getInstance())
+            .addVersionSpecificSupport(VERSION_1_1, ChoiceStatementRFC7950Support.getInstance())
+            .addVersionSpecificSupport(VERSION_1, CaseStatementRFC6020Support.getInstance())
+            .addVersionSpecificSupport(VERSION_1_1, CaseStatementRFC7950Support.getInstance())
+            .addSupport(MustStatementSupport.createInstance(xpathSupport))
+            .addSupport(MandatoryStatementSupport.getInstance())
+            .addSupport(AnyxmlStatementSupport.getInstance())
+            .addVersionSpecificSupport(VERSION_1_1, AnydataStatementSupport.getInstance())
+            .addSupport(FeatureNamespace.BEHAVIOUR)
+            .addSupport(IfFeatureStatementSupport.getInstance())
+            .addSupport(UsesStatementSupport.getInstance())
+            .addSupport(GroupingNamespace.BEHAVIOUR)
+            .addSupport(ErrorMessageStatementSupport.getInstance())
+            .addSupport(ErrorAppTagStatementSupport.getInstance())
+            .addVersionSpecificSupport(VERSION_1, LeafListStatementRFC6020Support.getInstance())
+            .addVersionSpecificSupport(VERSION_1_1, LeafListStatementRFC7950Support.getInstance())
+            .addSupport(PresenceStatementSupport.getInstance())
+            .addSupport(MaxElementsStatementSupport.getInstance())
+            .addSupport(MinElementsStatementSupport.getInstance())
+            .addSupport(OrderedByStatementSupport.getInstance())
+            .addSupport(WhenStatementSupport.createInstance(xpathSupport))
+            .addSupport(AugmentImplicitHandlingNamespace.BEHAVIOUR)
+            .addVersionSpecificSupport(VERSION_1, AugmentStatementRFC6020Support.getInstance())
+            .addVersionSpecificSupport(VERSION_1_1, AugmentStatementRFC7950Support.getInstance())
+            .addVersionSpecificSupport(VERSION_1, RefineStatementRFC6020Support.getInstance())
+            .addVersionSpecificSupport(VERSION_1_1, RefineStatementRFC7950Support.getInstance())
+            .addSupport(FeatureStatementSupport.getInstance())
+            .addSupport(PositionStatementSupport.getInstance())
+            .addSupport(ValueStatementSupport.getInstance())
+            .build();
     }
 }
diff --git a/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/reactor/ServiceLoaderState.java b/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/reactor/ServiceLoaderState.java
new file mode 100644 (file)
index 0000000..c62b316
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2020 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.rfc7950.reactor;
+
+import java.util.ServiceLoader;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.XPathSupport;
+import org.opendaylight.yangtools.yang.parser.stmt.reactor.CrossSourceStatementReactor;
+import org.opendaylight.yangtools.yang.xpath.api.YangXPathParserFactory;
+
+/**
+ * State derived from ServiceLoader. We statically bind to this state. If you need more dynamics, you should not be
+ * showing up here at all.
+ */
+@NonNullByDefault
+final class ServiceLoaderState {
+    static final class DefaultReactor {
+        static final CrossSourceStatementReactor INSTANCE = RFC7950Reactors.defaultReactorBuilder().build();
+    }
+
+    static final class VanillaReactor {
+        static final CrossSourceStatementReactor INSTANCE = RFC7950Reactors.vanillaReactorBuilder().build();
+    }
+
+    static final class XPath {
+        static final XPathSupport INSTANCE = new XPathSupport(ServiceLoader.load(YangXPathParserFactory.class)
+            .findFirst().orElseThrow(() -> new ExceptionInInitializerError("No YangXPathParserFactory found")));
+    }
+}
index 942650519f8a5065e30e8d78e3e4b648c1246e40..5ed39e397599ce985bc24f076ecc1cd68c2376ce 100644 (file)
@@ -16,7 +16,6 @@ import java.util.regex.Pattern;
 import org.checkerframework.checker.regex.qual.Regex;
 import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath;
 import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
 import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier;
 import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
@@ -77,10 +76,6 @@ public final class ArgumentUtils {
         }
     }
 
-    public static RevisionAwareXPath parseXPath(final StmtContext<?, ?, ?> ctx, final String path) {
-        return XPathSupport.parseXPath(ctx, path);
-    }
-
     public static boolean isAbsoluteXPath(final String path) {
         return PATH_ABS.matcher(path).matches();
     }
index c9f60274ce13d01f9c82988dc4c20b7c0a5828d4..a5bc3f462e57e690badf854b3e319633a8c0d178 100644 (file)
@@ -7,8 +7,9 @@
  */
 package org.opendaylight.yangtools.yang.parser.rfc7950.stmt;
 
-import java.util.Iterator;
-import java.util.ServiceLoader;
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.annotations.Beta;
 import javax.xml.xpath.XPathExpressionException;
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath;
@@ -18,62 +19,36 @@ import org.opendaylight.yangtools.yang.xpath.api.YangXPathExpression.QualifiedBo
 import org.opendaylight.yangtools.yang.xpath.api.YangXPathParser;
 import org.opendaylight.yangtools.yang.xpath.api.YangXPathParserFactory;
 import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
+@Beta
 @NonNullByDefault
-abstract class XPathSupport {
-    private static final Logger LOG = org.slf4j.LoggerFactory.getLogger(XPathSupport.class);
-
-    private static final XPathSupport INSTANCE;
-
-    static {
-        final Iterator<YangXPathParserFactory> it = ServiceLoader.load(YangXPathParserFactory.class).iterator();
-        if (!it.hasNext()) {
-            LOG.warn("Failed to find XPath parser factory, no XPath validation will be performed");
-            INSTANCE = new Noop();
-        } else {
-            INSTANCE = new XPathImpl(it.next());
-        }
-    }
+public final class XPathSupport {
+    private static final Logger LOG = LoggerFactory.getLogger(XPathSupport.class);
 
-    static RevisionAwareXPath parseXPath(final StmtContext<?, ?, ?> ctx, final String xpath) {
-        return INSTANCE.parseXPath(xpath, ctx);
-    }
-
-    abstract RevisionAwareXPath parseXPath(String xpath, StmtContext<?, ?, ?> ctx);
+    private final YangXPathParserFactory factory;
 
-    private static final class Noop extends XPathSupport {
-        @Override
-        RevisionAwareXPath parseXPath(final String xpath, final StmtContext<?, ?, ?> ctx) {
-            return new RevisionAwareXPathImpl(xpath, ArgumentUtils.isAbsoluteXPath(xpath));
-        }
+    public XPathSupport(final YangXPathParserFactory factory) {
+        this.factory = requireNonNull(factory);
     }
 
-    private static final class XPathImpl extends XPathSupport {
-        private final YangXPathParserFactory factory;
-
-        XPathImpl(final YangXPathParserFactory factory) {
-            this.factory = factory;
+    public RevisionAwareXPath parseXPath(final StmtContext<?, ?, ?> ctx, final String xpath) {
+        final boolean isAbsolute = ArgumentUtils.isAbsoluteXPath(xpath);
+        final YangXPathParser.QualifiedBound parser = factory.newParser(new StmtNamespaceContext(ctx));
+        final QualifiedBound parsed;
+        try {
+            parsed = parser.parseExpression(xpath);
+        } catch (XPathExpressionException e) {
+            LOG.warn("Argument \"{}\" is not valid XPath string at \"{}\"", xpath,
+                ctx.getStatementSourceReference(), e);
+            return new RevisionAwareXPathImpl(xpath, isAbsolute);
         }
 
-        @Override
-        RevisionAwareXPath parseXPath(final String xpath, final StmtContext<?, ?, ?> ctx) {
-            final boolean isAbsolute = ArgumentUtils.isAbsoluteXPath(xpath);
-            final YangXPathParser.QualifiedBound parser = factory.newParser(new StmtNamespaceContext(ctx));
-            final QualifiedBound parsed;
-            try {
-                parsed = parser.parseExpression(xpath);
-            } catch (XPathExpressionException e) {
-                LOG.warn("Argument \"{}\" is not valid XPath string at \"{}\"", xpath,
-                    ctx.getStatementSourceReference(), e);
-                return new RevisionAwareXPathImpl(xpath, isAbsolute);
-            }
-
-            if (ctx.getRootVersion().compareTo(parsed.getYangVersion()) < 0) {
-                LOG.warn("{} features required in {} context to parse expression '{}' [at {}]",
-                    parsed.getYangVersion().getReference(), ctx.getRootVersion().getReference(), xpath,
-                    ctx.getStatementSourceReference());
-            }
-            return new WithExpressionImpl(xpath, isAbsolute, parsed);
+        if (ctx.getRootVersion().compareTo(parsed.getYangVersion()) < 0) {
+            LOG.warn("{} features required in {} context to parse expression '{}' [at {}]",
+                parsed.getYangVersion().getReference(), ctx.getRootVersion().getReference(), xpath,
+                ctx.getStatementSourceReference());
         }
+        return new WithExpressionImpl(xpath, isAbsolute, parsed);
     }
 }
index bdaf2fbbef96f7e2eb7734a8926138f2fbf225cc..8ce4e2cd193dad9143f4daa2a9468360aa2464e1 100644 (file)
@@ -7,11 +7,14 @@
  */
 package org.opendaylight.yangtools.yang.parser.rfc7950.stmt.must;
 
+import static java.util.Objects.requireNonNull;
+
+import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath;
 import org.opendaylight.yangtools.yang.model.api.YangStmtMapping;
 import org.opendaylight.yangtools.yang.model.api.stmt.MustEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.MustStatement;
-import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.ArgumentUtils;
+import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.XPathSupport;
 import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractStatementSupport;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
 import org.opendaylight.yangtools.yang.parser.spi.meta.SubstatementValidator;
@@ -25,19 +28,21 @@ public final class MustStatementSupport
         .addOptional(YangStmtMapping.ERROR_MESSAGE)
         .addOptional(YangStmtMapping.REFERENCE)
         .build();
-    private static final MustStatementSupport INSTANCE = new MustStatementSupport();
 
-    private MustStatementSupport() {
+    private final @NonNull XPathSupport xpathSupport;
+
+    private MustStatementSupport(final XPathSupport xpathSupport) {
         super(YangStmtMapping.MUST);
+        this.xpathSupport = requireNonNull(xpathSupport);
     }
 
-    public static MustStatementSupport getInstance() {
-        return INSTANCE;
+    public static MustStatementSupport createInstance(final XPathSupport xpathSupport) {
+        return new MustStatementSupport(xpathSupport);
     }
 
     @Override
     public RevisionAwareXPath parseArgumentValue(final StmtContext<?, ?, ?> ctx, final String value) {
-        return ArgumentUtils.parseXPath(ctx, value);
+        return xpathSupport.parseXPath(ctx, value);
     }
 
     @Override
index 4f862d3d73c40f3142bf7757bb10dd064d8f46dc..060a4665ca753c2e9775b08e6172bfc1c80c1ae8 100644 (file)
@@ -7,11 +7,14 @@
  */
 package org.opendaylight.yangtools.yang.parser.rfc7950.stmt.when;
 
+import static java.util.Objects.requireNonNull;
+
+import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath;
 import org.opendaylight.yangtools.yang.model.api.YangStmtMapping;
 import org.opendaylight.yangtools.yang.model.api.stmt.WhenEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.WhenStatement;
-import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.ArgumentUtils;
+import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.XPathSupport;
 import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractStatementSupport;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
 import org.opendaylight.yangtools.yang.parser.spi.meta.SubstatementValidator;
@@ -23,19 +26,21 @@ public final class WhenStatementSupport
         .addOptional(YangStmtMapping.DESCRIPTION)
         .addOptional(YangStmtMapping.REFERENCE)
         .build();
-    private static final WhenStatementSupport INSTANCE = new WhenStatementSupport();
 
-    private WhenStatementSupport() {
+    private final @NonNull XPathSupport xpathSupport;
+
+    private WhenStatementSupport(final XPathSupport xpathSupport) {
         super(YangStmtMapping.WHEN);
+        this.xpathSupport = requireNonNull(xpathSupport);
     }
 
-    public static WhenStatementSupport getInstance() {
-        return INSTANCE;
+    public static WhenStatementSupport createInstance(final XPathSupport xpathSupport) {
+        return new WhenStatementSupport(xpathSupport);
     }
 
     @Override
     public RevisionAwareXPath parseArgumentValue(final StmtContext<?, ?, ?> ctx, final String value) {
-        return ArgumentUtils.parseXPath(ctx, value);
+        return xpathSupport.parseXPath(ctx, value);
     }
 
     @Override
index bc60526563a347095abe91d5c7607500a8c82c82..eccdd51fb02f207d798b098da2dc31336a872d24 100644 (file)
@@ -55,7 +55,7 @@
         </dependency>
         <dependency>
             <groupId>org.osgi</groupId>
-            <artifactId>org.osgi.core</artifactId>
+            <artifactId>osgi.cmpn</artifactId>
         </dependency>
     </dependencies>
 
@@ -68,7 +68,6 @@
                 <configuration>
                     <instructions>
                         <Automatic-Module-Name>org.opendaylight.yangtools.yang.xpath.impl</Automatic-Module-Name>
-                        <Bundle-Activator>org.opendaylight.yangtools.yang.xpath.impl.Activator</Bundle-Activator>
                     </instructions>
                 </configuration>
             </plugin>
diff --git a/yang/yang-xpath-impl/src/main/java/org/opendaylight/yangtools/yang/xpath/impl/Activator.java b/yang/yang-xpath-impl/src/main/java/org/opendaylight/yangtools/yang/xpath/impl/Activator.java
deleted file mode 100644 (file)
index 0ab894f..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2017 Pantheon Technologies, 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.xpath.impl;
-
-import org.eclipse.jdt.annotation.Nullable;
-import org.opendaylight.yangtools.yang.xpath.api.YangXPathParserFactory;
-import org.osgi.framework.BundleActivator;
-import org.osgi.framework.BundleContext;
-
-/**
- * YANG XPath implementation activator. Publishes a {@link YangXPathParserFactory} implementation on bundle start.
- *
- * @author Robert Varga
- */
-public final class Activator implements BundleActivator {
-    @Override
-    public void start(final @Nullable BundleContext context) throws Exception {
-        context.registerService(YangXPathParserFactory.class, new AntlrXPathParserFactory(), null);
-    }
-
-    @Override
-    public void stop(final @Nullable BundleContext context) throws Exception {
-        // No-op, framework will unregister our services
-    }
-}
index 52f77cdab3a550daf9408d46bdbe09dd0a209f5f..0569374538bf30b9f7514d10fd824764b7c164bb 100644 (file)
@@ -16,10 +16,18 @@ import org.opendaylight.yangtools.yang.xpath.api.YangXPathParser;
 import org.opendaylight.yangtools.yang.xpath.api.YangXPathParser.QualifiedBound;
 import org.opendaylight.yangtools.yang.xpath.api.YangXPathParser.UnqualifiedBound;
 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.Deactivate;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 @MetaInfServices
 @Singleton
+@Component(immediate = true)
 public final class AntlrXPathParserFactory implements YangXPathParserFactory {
+    private static final Logger LOG = LoggerFactory.getLogger(AntlrXPathParserFactory.class);
+
     @Override
     public YangXPathParser newParser(final YangXPathMathMode mathMode) {
         return new AntlrXPathParser.Base(mathMode);
@@ -35,4 +43,16 @@ public final class AntlrXPathParserFactory implements YangXPathParserFactory {
             final QNameModule defaultNamespace) {
         return new AntlrXPathParser.Unqualified(mathMode, namespaceContext, defaultNamespace);
     }
+
+    @Activate
+    @SuppressWarnings("static-method")
+    void activate() {
+        LOG.info("XPath Parser activated");
+    }
+
+    @Deactivate
+    @SuppressWarnings("static-method")
+    void deactivate() {
+        LOG.info("XPath Parser deactivated");
+    }
 }