--- /dev/null
+/*
+ * Copyright (c) 2023 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.netconf.api.capability;
+
+import java.net.URI;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.opendaylight.netconf.api.messages.HelloMessage;
+
+/**
+ * Contains capability URI announced by server hello message and optionally its
+ * corresponding yang schema that can be retrieved by get-schema rpc.
+ */
+@NonNullByDefault
+public sealed interface Capability permits SimpleCapability, ParameterizedCapability {
+ /**
+ * Return this capability's URN.
+ *
+ * @return An URN string
+ */
+ String urn();
+
+ /**
+ * Return this capability formatted as a URI, suitable for encoding as a {@link HelloMessage} advertisement.
+ *
+ * @return A URI
+ */
+ default URI toURI() {
+ return URI.create(urn());
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2023 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.netconf.api.capability;
+
+import com.google.common.collect.ImmutableSet;
+import java.util.Set;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.netconf.api.CapabilityURN;
+
+/**
+ * A capability representing a EXI Capability, as defined in
+ * <a href="https://datatracker.ietf.org/doc/html/draft-varga-netconf-exi-capability-02#section-3">
+ * Efficient XML Interchange Capability for NETCONF, section 3.1</a>.
+ */
+public record ExiCapability(
+ Integer compression,
+ ExiSchemas schemas,
+ @NonNull String urn) implements ParameterizedCapability {
+ private static final @NonNull String COMPRESSION_PARAM = "compression";
+ private static final @NonNull String SCHEMAS_PARAM = "schemas";
+ private static final @NonNull Set<String> PARAMETERS = ImmutableSet.of(COMPRESSION_PARAM, SCHEMAS_PARAM);
+
+ public ExiCapability(final Integer compression, final ExiSchemas schemas) {
+ this(compression, schemas, buildUrn(compression, schemas));
+ }
+
+ private static String buildUrn(final Integer compression, final ExiSchemas schemas) {
+ final var sb = new StringBuilder(CapabilityURN.EXI);
+ boolean isFirstParam = true;
+ if (compression != null) {
+ sb.append("?").append(COMPRESSION_PARAM).append("=").append(compression);
+ isFirstParam = false;
+ }
+ if (schemas != null) {
+ sb.append(isFirstParam ? "?" : "&");
+ sb.append(SCHEMAS_PARAM).append("=").append(schemas.getValue());
+ }
+ return sb.toString();
+ }
+
+ @Override
+ public String urn() {
+ return urn;
+ }
+
+ @Override
+ public Set<String> parameterNames() {
+ return PARAMETERS;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2024 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.netconf.api.capability;
+
+public enum ExiSchemas {
+ BUILTIN("builtin"),
+ BASE_1_1("base:1.1"),
+ DYNAMIC("dynamic");
+
+ private final String value;
+
+ ExiSchemas(final String value) {
+ this.value = value;
+ }
+
+ public String getValue() {
+ return value;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2023 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.netconf.api.capability;
+
+import java.util.Set;
+
+/**
+ * A {@link Capability} which defines a set of URI query parameters.
+ *
+ */
+public sealed interface ParameterizedCapability extends Capability
+ permits YangModuleCapability, ExiCapability {
+ Set<String> parameterNames();
+}
--- /dev/null
+/*
+ * Copyright (c) 2023 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.netconf.api.capability;
+
+import static java.util.Objects.requireNonNull;
+
+import java.net.URI;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.netconf.api.CapabilityURN;
+
+/**
+ * Enumeration of all simple
+ * <a href="https://www.iana.org/assignments/netconf-capability-urns/netconf-capability-urns.xhtml#netconf-capability-urns-1">
+ * NETCONF capabilities,</a>
+ * i.e. those which do not have any additional parameters.
+ */
+public enum SimpleCapability implements Capability {
+ /**
+ * The base NETCONF capability, as defined in
+ * <a href="https://www.rfc-editor.org/rfc/rfc4741.html#section-8.1">RFC4741, section 8.1</a>.
+ * @deprecated This capability identifies legacy NETCONF devices and has been superseded by {@link #BASE_1_1}, just
+ * as RFC6241 obsoletes RFC4741.
+ */
+ @Deprecated
+ BASE(":base:1.0", CapabilityURN.BASE),
+ /**
+ * The base NETCONF capability, as defined in
+ * <a href="https://www.rfc-editor.org/rfc/rfc6241.html#section-8.1">RFC6241, section 8.1</a>.
+ */
+ BASE_1_1(":base:1.1", CapabilityURN.BASE_1_1),
+ /**
+ * The Candidate Configuration Capability, as defined in
+ * <a href="https://www.rfc-editor.org/rfc/rfc6241.html#section-8.3">RFC6241, section 8.3</a>.
+ */
+ CANDIDATE(":candidate", CapabilityURN.CANDIDATE),
+ /**
+ * The Candidate Configuration Capability, as defined in
+ * <a href="https://www.rfc-editor.org/rfc/rfc4741.html#section-8.3">RFC4741, section 8.3</a>.
+ * @deprecated This capability is superseded by {@link #CONFIRMED_COMMIT_1_1}.
+ */
+ @Deprecated
+ CONFIRMED_COMMIT(":confirmed-commit", CapabilityURN.CONFIRMED_COMMIT),
+ /**
+ * The Rollback-on-Error Capability, as defined in
+ * <a href="https://www.rfc-editor.org/rfc/rfc6241.html#section-8.4">RFC6241, section 8.4</a>.
+ */
+ CONFIRMED_COMMIT_1_1(":confirmed-commit:1.1", CapabilityURN.CONFIRMED_COMMIT_1_1),
+ /**
+ * The Interleave Capability, as defined in
+ * <a href="https://www.rfc-editor.org/rfc/rfc5277.html#section-6">RFC5277, section 6</a>.
+ */
+ INTERLEAVE(":interleave", CapabilityURN.INTERLEAVE),
+ /**
+ * The Validate Capability, as defined in
+ * <a href="https://www.rfc-editor.org/rfc/rfc5277.html#section-3.1">RFC5277, section 3.1</a>.
+ */
+ NOTIFICATION(":notification", CapabilityURN.NOTIFICATION),
+ /**
+ * The Partial Locking Capability, as defined in
+ * <a href="https://www.rfc-editor.org/rfc/rfc5717.html#section-2">RFC5715, section 2</a>.
+ */
+ PARTIAL_LOCK(":partial-lock", CapabilityURN.PARTIAL_LOCK),
+ /**
+ * The Rollback-on-Error Capability, as defined in
+ * <a href="https://www.rfc-editor.org/rfc/rfc6241.html#section-8.5">RFC6241, section 8.5</a>.
+ */
+ ROLLBACK_ON_ERROR(":rollback-on-error", CapabilityURN.ROLLBACK_ON_ERROR),
+ /**
+ * The Distinct Startup Capability, as defined in
+ * <a href="https://www.rfc-editor.org/rfc/rfc6241.html#section-8.7">RFC6241, section 8.7</a>.
+ */
+ STARTUP(":startup", CapabilityURN.STARTUP),
+ /**
+ * The Time Capability, as defined in
+ * <a href="https://www.rfc-editor.org/rfc/rfc7758.html#section-4">RFC7758, section 4</a>.
+ */
+ TIME(":time:1.0", CapabilityURN.TIME),
+ /**
+ * The URL Capability, as defined in
+ * <a href="https://www.rfc-editor.org/rfc/rfc6241.html#section-8.8">RFC6241, section 8.8</a>.
+ */
+ URL(":url", CapabilityURN.URL),
+ /**
+ * The Validate Capability, as defined in
+ * <a href="https://www.rfc-editor.org/rfc/rfc4741.html#section-8.6">RFC4741, section 8.6</a>.
+ * @deprecated This capability is superseded by {@link #VALIDATE_1_1}.
+ */
+ @Deprecated
+ VALIDATE(":validate", CapabilityURN.VALIDATE),
+ /**
+ * The Validate Capability, as defined in
+ * <a href="https://www.rfc-editor.org/rfc/rfc6241.html#section-8.6">RFC6241, section 8.6</a>.
+ */
+ VALIDATE_1_1(":validate:1.1", CapabilityURN.VALIDATE_1_1),
+ /**
+ * The XPath Capability, as defined in
+ * <a href="https://www.rfc-editor.org/rfc/rfc6241.html#section-8.9">RFC6241, section 8.9</a>.
+ */
+ XPATH(":xpath", CapabilityURN.XPATH),
+ /**
+ * The YANG Module Library Capability, as defined in
+ * <a href="hhttps://www.rfc-editor.org/rfc/rfc7950.html#section-5.6.4">RFC7950, section 5.6.4</a> and further
+ * specified by <a href="https://www.rfc-editor.org/rfc/rfc7895">RFC7895</a>. Note this applies to NETCONF endpoints
+ * which DO NOT support Network Management Datastore Architecture as specified by
+ * <a href="https://www.rfc-editor.org/rfc/rfc8342">RFC8342</a>.
+ */
+ YANG_LIBRARY(":yang-library", CapabilityURN.YANG_LIBRARY),
+ /**
+ * The YANG Library Capability, as defined in
+ * <a href="https://www.rfc-editor.org/rfc/rfc8526.html#section-2">RFC8526, section 2</a> and further specified
+ * by <a href="https://www.rfc-editor.org/rfc/rfc8525">RFC8525</a>. Note this applies to NETCONF endpoints
+ * which DO support Network Management Datastore Architecture as specified by
+ * <a href="https://www.rfc-editor.org/rfc/rfc8342">RFC8342</a>.
+ */
+ YANG_LIBRARY_1_1(":yang-library:1.1", CapabilityURN.YANG_LIBRARY_1_1),
+ /**
+ * The With-defaults Capability, as defined in
+ * <a href="https://www.rfc-editor.org/rfc/rfc6243.html#section-4">RFC6243, section 4</a>.
+ */
+ WITH_DEFAULTS(":with-defaults", CapabilityURN.WITH_DEFAULTS),
+ /**
+ * The With-defaults Capability, as augmented by
+ * <a href="https://www.rfc-editor.org/rfc/rfc8526#section-3.1.1.2">RFC8526, section 3.1.1.2</a>.
+ */
+ WITH_OPERATIONAL_DEFAULTS(":with-operational-defaults", CapabilityURN.WITH_OPERATIONAL_DEFAULTS),
+ /**
+ * The Writable-Running Capability, as defined in
+ * <a href="https://www.rfc-editor.org/rfc/rfc6241.html#section-8.2">RFC6241, section 8.2</a>.
+ */
+ WRITABLE_RUNNING(":writable-running", CapabilityURN.WRITABLE_RUNNING);
+
+ private final @NonNull String capabilityName;
+ private final @NonNull String urn;
+ private final @NonNull URI uri;
+
+ SimpleCapability(final String capabilityName, final String urn) {
+ this.capabilityName = requireNonNull(capabilityName);
+ this.urn = requireNonNull(urn);
+ uri = URI.create(urn);
+ }
+
+ public @NonNull String capabilityName() {
+ return capabilityName;
+ }
+
+ @Override
+ public String urn() {
+ return urn;
+ }
+
+ @Override
+ public URI toURI() {
+ return uri;
+ }
+
+ /**
+ * Try to match a capability URN to a {@link SimpleCapability}.
+ *
+ * @param urn URN to match
+ * @return A {@link SimpleCapability}
+ * @throws IllegalArgumentException if {@code urn} is {@code null}
+ */
+ public static @NonNull SimpleCapability ofURN(final String urn) {
+ final var capability = forURN(urn);
+ if (capability == null) {
+ throw new IllegalArgumentException(urn + " does not match a known protocol capability");
+ }
+ return capability;
+ }
+
+ /**
+ * Match a capability URN to a {@link SimpleCapability}.
+ *
+ * @param urn URN to match
+ * @return A {@link SimpleCapability}, or {@code null} the URN does not match a known protocol capability
+ * @throws NullPointerException if {@code urn} is {@code null}
+ */
+ public static SimpleCapability forURN(final String urn) {
+ return switch (urn) {
+ case CapabilityURN.BASE -> BASE;
+ case CapabilityURN.BASE_1_1 -> BASE_1_1;
+ case CapabilityURN.CANDIDATE -> CANDIDATE;
+ case CapabilityURN.CONFIRMED_COMMIT -> CONFIRMED_COMMIT;
+ case CapabilityURN.CONFIRMED_COMMIT_1_1 -> CONFIRMED_COMMIT_1_1;
+ case CapabilityURN.INTERLEAVE -> INTERLEAVE;
+ case CapabilityURN.NOTIFICATION -> NOTIFICATION;
+ case CapabilityURN.PARTIAL_LOCK -> PARTIAL_LOCK;
+ case CapabilityURN.ROLLBACK_ON_ERROR -> ROLLBACK_ON_ERROR;
+ case CapabilityURN.STARTUP -> STARTUP;
+ case CapabilityURN.TIME -> TIME;
+ case CapabilityURN.URL -> URL;
+ case CapabilityURN.VALIDATE -> VALIDATE;
+ case CapabilityURN.VALIDATE_1_1 -> VALIDATE_1_1;
+ case CapabilityURN.WITH_DEFAULTS -> WITH_DEFAULTS;
+ case CapabilityURN.WITH_OPERATIONAL_DEFAULTS -> WITH_OPERATIONAL_DEFAULTS;
+ case CapabilityURN.WRITABLE_RUNNING -> WRITABLE_RUNNING;
+ case CapabilityURN.XPATH -> XPATH;
+ case CapabilityURN.YANG_LIBRARY -> YANG_LIBRARY;
+ case CapabilityURN.YANG_LIBRARY_1_1 -> YANG_LIBRARY_1_1;
+ default -> null;
+ };
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2023 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.netconf.api.capability;
+
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.collect.ImmutableSet;
+import java.util.List;
+import java.util.Set;
+import org.eclipse.jdt.annotation.NonNull;
+
+/**
+ * A capability representing a YANG module, as defined in
+ * <a href="https://datatracker.ietf.org/doc/html/rfc6020#section-5.6.4">RFC6020, section 5.6.4</a>.
+ */
+public record YangModuleCapability(
+ @NonNull String moduleNamespace,
+ String moduleName,
+ String revision,
+ List<String> features,
+ List<String> deviations,
+ String urn) implements ParameterizedCapability {
+ private static final @NonNull String MODULE_PARAM = "module";
+ private static final @NonNull String REVISION_PARAM = "revision";
+ private static final @NonNull String FEATURES_PARAM = "features";
+ private static final @NonNull String DEVIATIONS_PARAM = "deviations";
+ private static final @NonNull Set<String> PARAMETERS = ImmutableSet.of(MODULE_PARAM, REVISION_PARAM, FEATURES_PARAM,
+ DEVIATIONS_PARAM);
+
+ public YangModuleCapability(final @NonNull String moduleNamespace, final String moduleName,
+ final String revision, final List<String> features, final List<String> deviations) {
+ this(requireNonNull(moduleNamespace), moduleName, revision,
+ features == null || features.isEmpty() ? null : List.copyOf(features),
+ deviations == null || deviations.isEmpty() ? null : List.copyOf(deviations),
+ buildUrn(moduleNamespace, moduleName, revision, features, deviations));
+ }
+
+ private static String buildUrn(final String moduleNamespace, final String moduleName, final String revision,
+ final List<String> features, final List<String> deviations) {
+ final var sb = new StringBuilder().append(moduleNamespace);
+ boolean isFirstParam = true;
+ if (moduleName != null) {
+ sb.append("?").append(MODULE_PARAM).append("=").append(moduleName);
+ isFirstParam = false;
+ }
+ if (revision != null) {
+ sb.append(isFirstParam ? "?" : "&");
+ sb.append(REVISION_PARAM).append("=").append(revision);
+ isFirstParam = false;
+ }
+ if (features != null && !features.isEmpty()) {
+ sb.append(isFirstParam ? "?" : "&");
+ sb.append(FEATURES_PARAM).append("=").append(String.join(",", features));
+ isFirstParam = false;
+ }
+ if (deviations != null && !deviations.isEmpty()) {
+ sb.append(isFirstParam ? "?" : "&");
+ sb.append(DEVIATIONS_PARAM).append("=").append(String.join(",", deviations));
+ }
+ return sb.toString();
+ }
+
+ @Override
+ public String urn() {
+ return urn;
+ }
+
+ @Override
+ public Set<String> parameterNames() {
+ return PARAMETERS;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2023 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.netconf.api.capability;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Stream;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+class ParameterizedCapabilityTest {
+
+ @ParameterizedTest
+ @MethodSource("provideYangModuleCapabilityParams")
+ void testYangModuleCapabilityUrn(final String namespace, final String module, final String revision,
+ final List<String> features, final List<String> deviations, final String expectedUrn) {
+ final var capability = new YangModuleCapability(namespace, module, revision, features, deviations);
+ assertEquals(expectedUrn, capability.urn());
+ }
+
+ @ParameterizedTest
+ @MethodSource("provideExiCapabilityParams")
+ void testExiCapabilityUrn(final Integer compression, final ExiSchemas schema, final String expectedUrn) {
+ final var capability = new ExiCapability(compression, schema);
+ assertEquals(expectedUrn, capability.urn());
+ }
+
+ @ParameterizedTest
+ @MethodSource("provideExiCapabilityParams")
+ void testExiCapabilityEquals(final Integer compression, final ExiSchemas schema) {
+ assertEquals(new ExiCapability(compression, schema), new ExiCapability(compression, schema));
+ }
+
+ @ParameterizedTest
+ @MethodSource("provideYangModuleCapabilityParams")
+ void testYangModuleCapabilityEquals(final String namespace, final String module, final String revision,
+ final List<String> features, final List<String> deviations) {
+ assertEquals(new YangModuleCapability(namespace, module, revision, features, deviations),
+ new YangModuleCapability(namespace, module, revision, features, deviations));
+ }
+
+ static Stream<Arguments> provideExiCapabilityParams() {
+ return Stream.of(
+ Arguments.of(null, null, "urn:ietf:params:netconf:capability:exi:1.0"),
+ Arguments.of(1000, ExiSchemas.BUILTIN,
+ "urn:ietf:params:netconf:capability:exi:1.0?compression=1000&schemas=builtin"),
+ Arguments.of(1000, null, "urn:ietf:params:netconf:capability:exi:1.0?compression=1000"),
+ Arguments.of(null, ExiSchemas.BASE_1_1,
+ "urn:ietf:params:netconf:capability:exi:1.0?schemas=base:1.1"),
+ Arguments.of(null, ExiSchemas.DYNAMIC,
+ "urn:ietf:params:netconf:capability:exi:1.0?schemas=dynamic")
+ );
+ }
+
+ static Stream<Arguments> provideYangModuleCapabilityParams() {
+ return Stream.of(
+ Arguments.of("http://example.com", null, null, null, null, "http://example.com"),
+ Arguments.of("http://example.com", "module", "2023-08-21", List.of("feature1", "feature2"),
+ List.of("deviation1", "deviation2"), "http://example.com?module=module&revision=2023-08-21"
+ + "&features=feature1,feature2&deviations=deviation1,deviation2"),
+ Arguments.of("http://example.com", null, "2023-08-21", null, null,
+ "http://example.com?revision=2023-08-21"),
+ Arguments.of("http://example.com", null, "2023-08-21", List.of("feature"), List.of("deviation"),
+ "http://example.com?revision=2023-08-21&features=feature&deviations=deviation"),
+ Arguments.of("http://example.com", "module", null, List.of("feature"), List.of("deviation"),
+ "http://example.com?module=module&features=feature&deviations=deviation"),
+ Arguments.of("http://example.com", "module", "2023-08-21", null, List.of("deviation"),
+ "http://example.com?module=module&revision=2023-08-21&deviations=deviation"),
+ Arguments.of("http://example.com", "module", "2023-08-21", List.of("feature"), null,
+ "http://example.com?module=module&revision=2023-08-21&features=feature"),
+ Arguments.of("http://example.com", "module", "2023-08-21", Collections.emptyList(), List.of("deviation"),
+ "http://example.com?module=module&revision=2023-08-21&deviations=deviation"),
+ Arguments.of("http://example.com", "module", "2023-08-21", List.of("feature"), Collections.emptyList(),
+ "http://example.com?module=module&revision=2023-08-21&features=feature")
+ );
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2023 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.netconf.api.capability;
+
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.params.provider.Arguments.arguments;
+
+import java.util.stream.Stream;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+class ProtocolCapabilityTest {
+ @Test
+ void forUnknownURN() {
+ assertNull(SimpleCapability.forURN("tweedly dee"));
+ }
+
+ @Test
+ void forNullURN() {
+ assertThrows(NullPointerException.class, () -> SimpleCapability.forURN(null));
+ }
+
+ @Test
+ void ofUnknownURN() {
+ assertThrows(IllegalArgumentException.class, () -> SimpleCapability.ofURN("tweedly dum"));
+ assertThrows(NullPointerException.class, () -> SimpleCapability.ofURN(null));
+ }
+
+ @ParameterizedTest
+ @MethodSource("protocolCapabilities")
+ void forURN(final String urn, final SimpleCapability expected) {
+ assertSame(expected, SimpleCapability.forURN(urn));
+ }
+
+ static Stream<Arguments> protocolCapabilities() {
+ return Stream.of(
+ arguments("urn:ietf:params:netconf:base:1.0", SimpleCapability.BASE),
+ arguments("urn:ietf:params:netconf:base:1.1", SimpleCapability.BASE_1_1),
+ arguments("urn:ietf:params:netconf:capability:candidate:1.0", SimpleCapability.CANDIDATE),
+ arguments("urn:ietf:params:netconf:capability:confirmed-commit:1.0", SimpleCapability.CONFIRMED_COMMIT),
+ arguments("urn:ietf:params:netconf:capability:confirmed-commit:1.1",
+ SimpleCapability.CONFIRMED_COMMIT_1_1),
+ arguments("urn:ietf:params:netconf:capability:interleave:1.0", SimpleCapability.INTERLEAVE),
+ arguments("urn:ietf:params:netconf:capability:notification:1.0", SimpleCapability.NOTIFICATION),
+ arguments("urn:ietf:params:netconf:capability:partial-lock:1.0", SimpleCapability.PARTIAL_LOCK),
+ arguments("urn:ietf:params:netconf:capability:rollback-on-error:1.0", SimpleCapability.ROLLBACK_ON_ERROR),
+ arguments("urn:ietf:params:netconf:capability:startup:1.0", SimpleCapability.STARTUP),
+ arguments("urn:ietf:params:netconf:capability:time:1.0", SimpleCapability.TIME),
+ arguments("urn:ietf:params:netconf:capability:url:1.0", SimpleCapability.URL),
+ arguments("urn:ietf:params:netconf:capability:validate:1.0", SimpleCapability.VALIDATE),
+ arguments("urn:ietf:params:netconf:capability:validate:1.1", SimpleCapability.VALIDATE_1_1),
+ arguments("urn:ietf:params:netconf:capability:with-defaults:1.0", SimpleCapability.WITH_DEFAULTS),
+ arguments("urn:ietf:params:netconf:capability:with-operational-defaults:1.0",
+ SimpleCapability.WITH_OPERATIONAL_DEFAULTS),
+ arguments("urn:ietf:params:netconf:capability:writable-running:1.0", SimpleCapability.WRITABLE_RUNNING),
+ arguments("urn:ietf:params:netconf:capability:xpath:1.0", SimpleCapability.XPATH),
+ arguments("urn:ietf:params:netconf:capability:yang-library:1.0", SimpleCapability.YANG_LIBRARY),
+ arguments("urn:ietf:params:netconf:capability:yang-library:1.1", SimpleCapability.YANG_LIBRARY_1_1));
+ }
+}