ServiceGroupIdentifier should be a record 51/109251/4
authorRobert Varga <robert.varga@pantheon.tech>
Sat, 9 Dec 2023 11:17:32 +0000 (12:17 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Sat, 9 Dec 2023 12:22:27 +0000 (13:22 +0100)
Using a record here allows us to perform proper validation, improve
serialization format and ditch the dependency on yangtools.util.

While we are here, also strengthen the check to reject blank strings.

JIRA: MDSAL-843
Change-Id: Ic1342f1cc8090fbb9892d608d03bea0b64e2e5c7
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
replicate/mdsal-replicate-netty/src/main/java/org/opendaylight/mdsal/replicate/netty/SinkSingletonService.java
replicate/mdsal-replicate-netty/src/main/java/org/opendaylight/mdsal/replicate/netty/SourceSingletonService.java
singleton-service/mdsal-singleton-common-api/pom.xml
singleton-service/mdsal-singleton-common-api/src/main/java/module-info.java
singleton-service/mdsal-singleton-common-api/src/main/java/org/opendaylight/mdsal/singleton/common/api/ServiceGroupIdentifier.java
singleton-service/mdsal-singleton-common-api/src/test/java/org/opendaylight/mdsal/singleton/common/api/ServiceGroupIdentifierTest.java [new file with mode: 0644]
singleton-service/mdsal-singleton-dom-impl/src/main/java/org/opendaylight/mdsal/singleton/dom/impl/ActiveServiceGroup.java
singleton-service/mdsal-singleton-dom-impl/src/main/java/org/opendaylight/mdsal/singleton/dom/impl/EOSClusterSingletonServiceProvider.java
singleton-service/mdsal-singleton-dom-impl/src/test/java/org/opendaylight/mdsal/singleton/dom/impl/AbstractEOSClusterSingletonServiceProviderTest.java
singleton-service/mdsal-singleton-dom-impl/src/test/java/org/opendaylight/mdsal/singleton/dom/impl/ActiveServiceGroupTest.java

index be90e36130c9b6ff46025bbf6006e365c8ebd298..975d75f6bf4163c14e57455ef5efd3b69621d0b9 100644 (file)
@@ -42,8 +42,7 @@ import org.slf4j.LoggerFactory;
 
 final class SinkSingletonService extends ChannelInitializer<SocketChannel> implements ClusterSingletonService {
     private static final Logger LOG = LoggerFactory.getLogger(SinkSingletonService.class);
-    private static final ServiceGroupIdentifier SGID =
-            ServiceGroupIdentifier.create(SinkSingletonService.class.getName());
+    private static final ServiceGroupIdentifier SGID = new ServiceGroupIdentifier(SinkSingletonService.class.getName());
     // TODO: allow different trees?
     private static final DOMDataTreeIdentifier TREE = new DOMDataTreeIdentifier(LogicalDatastoreType.CONFIGURATION,
         YangInstanceIdentifier.of());
@@ -90,7 +89,7 @@ final class SinkSingletonService extends ChannelInitializer<SocketChannel> imple
     @Override
     public synchronized void instantiateServiceInstance() {
         LOG.info("Replication sink started with source {}", sourceAddress);
-        this.bs = bootstrapSupport.newBootstrap();
+        bs = bootstrapSupport.newBootstrap();
         doConnect();
     }
 
index d707fd1407e42f21f8791cefaf77d89c7d9c79cf..c86423e72ddbc7cbad77a7ddf8ac04ed621c3db8 100644 (file)
@@ -40,7 +40,7 @@ import org.slf4j.LoggerFactory;
 final class SourceSingletonService extends ChannelInitializer<SocketChannel> implements ClusterSingletonService {
     private static final Logger LOG = LoggerFactory.getLogger(SourceSingletonService.class);
     private static final ServiceGroupIdentifier SGID =
-            ServiceGroupIdentifier.create(SourceSingletonService.class.getName());
+        new ServiceGroupIdentifier(SourceSingletonService.class.getName());
 
     private final BootstrapSupport bootstrapSupport;
     private final DOMDataTreeChangeService dtcs;
index e1163accc30ab1aa8dd13330e5bfd16d0ced7ed1..ec7c0a4b0396c0081571b90419ef6136a13f27b5 100644 (file)
             <groupId>org.opendaylight.yangtools</groupId>
             <artifactId>concepts</artifactId>
         </dependency>
-        <dependency>
-            <groupId>org.opendaylight.yangtools</groupId>
-            <artifactId>util</artifactId>
-        </dependency>
 
         <dependency>
             <groupId>org.opendaylight.yangtools</groupId>
index b2d5fbd07e26be45e1cb2939803e885761410f3b..b704978e31271e2a7b40bf7d4434fcec54808799 100644 (file)
@@ -9,7 +9,6 @@ module org.opendaylight.mdsal.singleton.common.api {
     exports org.opendaylight.mdsal.singleton.common.api;
 
     requires transitive org.opendaylight.yangtools.concepts;
-    requires org.opendaylight.yangtools.util;
 
     // Annotations
     requires static transitive org.eclipse.jdt.annotation;
index 0a7ca41f827c7e933de05a89a4c39cebbfb497bc..1e2aa4659dd3b6f4641ce40d8f28a61ddd5832a0 100644 (file)
@@ -7,32 +7,21 @@
  */
 package org.opendaylight.mdsal.singleton.common.api;
 
-import java.io.Serial;
 import org.eclipse.jdt.annotation.NonNull;
-import org.opendaylight.yangtools.util.AbstractStringIdentifier;
+import org.opendaylight.yangtools.concepts.Identifier;
 
 /**
- * Identifier represents a service group competence. It's based on String.
+ * An {@link Identifier} of a group of {@link ClusterSingletonService}s.
+ *
+ * @param value String value, must not be {@link String#isBlank()}
  */
-public class ServiceGroupIdentifier extends AbstractStringIdentifier<ServiceGroupIdentifier> {
-    @Serial
-    private static final long serialVersionUID = 6853612584804702662L;
-
-    protected ServiceGroupIdentifier(final @NonNull String string) {
-        super(string);
-    }
-
-    /**
-     * Method to create immutable instances of {@link ServiceGroupIdentifier}.
-     *
-     * @param name the String identifier for the ServiceGroupIdentifier instance
-     * @return {@link ServiceGroupIdentifier} new instance
-     */
-    public static @NonNull ServiceGroupIdentifier create(final String name) {
-        return new ServiceGroupIdentifier(name);
-    }
+public record ServiceGroupIdentifier(@NonNull String value) implements Identifier {
+    @java.io.Serial
+    private static final long serialVersionUID = 1L;
 
-    public final @NonNull String getName() {
-        return getValue();
+    public ServiceGroupIdentifier {
+        if (value.isBlank()) {
+            throw new IllegalArgumentException("Value must not be blank");
+        }
     }
 }
diff --git a/singleton-service/mdsal-singleton-common-api/src/test/java/org/opendaylight/mdsal/singleton/common/api/ServiceGroupIdentifierTest.java b/singleton-service/mdsal-singleton-common-api/src/test/java/org/opendaylight/mdsal/singleton/common/api/ServiceGroupIdentifierTest.java
new file mode 100644 (file)
index 0000000..4b32174
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * 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.mdsal.singleton.common.api;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import org.junit.jupiter.api.Test;
+
+class ServiceGroupIdentifierTest {
+    @Test
+    void rejectEmptyValue() {
+        final var ex = assertThrows(IllegalArgumentException.class, () -> new ServiceGroupIdentifier(""));
+        assertEquals("Value must not be blank", ex.getMessage());
+    }
+
+    @Test
+    void rejectNullValue() {
+        assertThrows(NullPointerException.class, () -> new ServiceGroupIdentifier(null));
+    }
+}
index 457474c112dd15f4f0d6fc5b46b444924eef0ba6..6e75cecf923ed4da5b83e72283f2e94b7ec5faec 100644 (file)
@@ -288,7 +288,7 @@ final class ActiveServiceGroup extends ServiceGroup {
 
     private ClusterSingletonService verifyRegistration(final ServiceRegistration reg) {
         final var service = reg.getInstance();
-        verify(identifier.equals(service.getIdentifier().getName()));
+        verify(identifier.equals(service.getIdentifier().value()));
         return service;
     }
 
index 23d4ccdc805d1580a518588157f06aae7b4e70c2..98d7e70ab732b25e458f3e3a239324754dff71ad 100644 (file)
@@ -7,13 +7,11 @@
  */
 package org.opendaylight.mdsal.singleton.dom.impl;
 
-import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Verify.verify;
 import static com.google.common.base.Verify.verifyNotNull;
 import static java.util.Objects.requireNonNull;
 
 import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Strings;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.MoreExecutors;
@@ -104,10 +102,7 @@ public final class EOSClusterSingletonServiceProvider
     public synchronized Registration registerClusterSingletonService(final ClusterSingletonService service) {
         LOG.debug("Call registrationService {} method for ClusterSingletonService Provider {}", service, this);
 
-        final String serviceIdentifier = service.getIdentifier().getName();
-        checkArgument(!Strings.isNullOrEmpty(serviceIdentifier),
-            "ClusterSingletonService identifier may not be null nor empty");
-
+        final var serviceIdentifier = service.getIdentifier().value();
         final ServiceGroup serviceGroup;
         final var existing = serviceGroupMap.get(serviceIdentifier);
         if (existing == null) {
@@ -165,7 +160,7 @@ public final class EOSClusterSingletonServiceProvider
             LOG.debug("Closing service group {}", serviceIdentifier);
             placeHolder = new PlaceholderServiceGroup(lookup, future);
 
-            final var identifier = reg.getInstance().getIdentifier().getName();
+            final var identifier = reg.getInstance().getIdentifier().value();
             verify(serviceGroupMap.replace(identifier, lookup, placeHolder));
             LOG.debug("Replaced group {} with {}", serviceIdentifier, placeHolder);
 
index 5d41916ed15144563077c6feeed2a6ac1c5ed9c5..8f4c22fff0e60073b445d9ddd2418686999de652 100644 (file)
@@ -60,7 +60,7 @@ abstract class AbstractEOSClusterSingletonServiceProviderTest {
     }
 
     static class TestClusterSingletonService implements ClusterSingletonService {
-        private static final @NonNull ServiceGroupIdentifier SERVICE_ID = ServiceGroupIdentifier.create(SERVICE_NAME);
+        private static final @NonNull ServiceGroupIdentifier SERVICE_ID = new ServiceGroupIdentifier(SERVICE_NAME);
 
         private TestClusterSingletonServiceState serviceState = TestClusterSingletonServiceState.INITIALIZED;
 
index cfaee231f07f5ec2f5f48bb302926a2200d4f93b..f9a919fdae93806546cceff75f0c7db8af46a7bb 100644 (file)
@@ -46,8 +46,8 @@ import org.opendaylight.yangtools.concepts.Registration;
  */
 @RunWith(MockitoJUnitRunner.StrictStubs.class)
 public class ActiveServiceGroupTest {
-    public static final String SERVICE_IDENTIFIER = "TestServiceIdent";
-    public static final ServiceGroupIdentifier SERVICE_GROUP_IDENT = ServiceGroupIdentifier.create(SERVICE_IDENTIFIER);
+    private static final String SERVICE_IDENTIFIER = "TestServiceIdent";
+    private static final ServiceGroupIdentifier SERVICE_GROUP_IDENT = new ServiceGroupIdentifier(SERVICE_IDENTIFIER);
 
     public static final @NonNull DOMEntity MAIN_ENTITY = new DOMEntity(SERVICE_ENTITY_TYPE, SERVICE_IDENTIFIER);
     public static final @NonNull DOMEntity CLOSE_ENTITY = new DOMEntity(CLOSE_SERVICE_ENTITY_TYPE, SERVICE_IDENTIFIER);