Do not tolerate empty action instances
[mdsal.git] / dom / mdsal-dom-broker / src / main / java / org / opendaylight / mdsal / dom / broker / DOMRpcRouter.java
index 37713fd58cc2512e45ca0840f70c717254d93942..ef656b8634277e7749db92e32a32abff0255c954 100644 (file)
@@ -25,10 +25,8 @@ import com.google.common.collect.Sets;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.ThreadFactoryBuilder;
-import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
@@ -69,6 +67,7 @@ import org.opendaylight.yangtools.concepts.AbstractObjectRegistration;
 import org.opendaylight.yangtools.concepts.AbstractRegistration;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.concepts.ObjectRegistration;
+import org.opendaylight.yangtools.concepts.Registration;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
@@ -101,16 +100,16 @@ public final class DOMRpcRouter extends AbstractRegistration
     private final @NonNull DOMRpcService rpcService = new RpcServiceFacade();
 
     @GuardedBy("this")
-    private Collection<Registration<?>> listeners = Collections.emptyList();
+    private ImmutableList<RegImpl<?>> listeners = ImmutableList.of();
 
     @GuardedBy("this")
-    private Collection<ActionRegistration<?>> actionListeners = Collections.emptyList();
+    private ImmutableList<ActionRegistration<?>> actionListeners = ImmutableList.of();
 
     private volatile DOMRpcRoutingTable routingTable = DOMRpcRoutingTable.EMPTY;
 
     private volatile DOMActionRoutingTable actionRoutingTable = DOMActionRoutingTable.EMPTY;
 
-    private ListenerRegistration<?> listenerRegistration;
+    private Registration listenerRegistration;
 
     @Deprecated
     @VisibleForTesting
@@ -157,8 +156,6 @@ public final class DOMRpcRouter extends AbstractRegistration
         return rpcProviderService;
     }
 
-    @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
-            justification = "https://github.com/spotbugs/spotbugs/issues/811")
     private synchronized void removeRpcImplementation(final DOMRpcImplementation implementation,
             final Set<DOMRpcIdentifier> rpcs) {
         final DOMRpcRoutingTable oldTable = routingTable;
@@ -168,8 +165,6 @@ public final class DOMRpcRouter extends AbstractRegistration
         listenerNotifier.execute(() -> notifyRemoved(newTable, implementation));
     }
 
-    @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
-            justification = "https://github.com/spotbugs/spotbugs/issues/811")
     private synchronized void removeRpcImplementations(final Map<DOMRpcIdentifier, DOMRpcImplementation> map) {
         final DOMRpcRoutingTable oldTable = routingTable;
         final DOMRpcRoutingTable newTable = (DOMRpcRoutingTable) oldTable.removeAll(map);
@@ -178,8 +173,6 @@ public final class DOMRpcRouter extends AbstractRegistration
         listenerNotifier.execute(() -> notifyRemoved(newTable, map.values()));
     }
 
-    @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
-            justification = "https://github.com/spotbugs/spotbugs/issues/811")
     private synchronized void removeActionImplementation(final DOMActionImplementation implementation,
             final Set<DOMActionInstance> actions) {
         final DOMActionRoutingTable oldTable = actionRoutingTable;
@@ -189,50 +182,38 @@ public final class DOMRpcRouter extends AbstractRegistration
         listenerNotifier.execute(() -> notifyActionChanged(newTable, implementation));
     }
 
-    @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
-            justification = "https://github.com/spotbugs/spotbugs/issues/811")
     private synchronized void removeListener(final ListenerRegistration<? extends DOMRpcAvailabilityListener> reg) {
         listeners = ImmutableList.copyOf(Collections2.filter(listeners, input -> !reg.equals(input)));
     }
 
-    @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
-            justification = "https://github.com/spotbugs/spotbugs/issues/811")
     private synchronized void removeActionListener(final ListenerRegistration<? extends AvailabilityListener> reg) {
         actionListeners = ImmutableList.copyOf(Collections2.filter(actionListeners, input -> !reg.equals(input)));
     }
 
-    @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
-            justification = "https://github.com/spotbugs/spotbugs/issues/811")
     private synchronized void notifyAdded(final DOMRpcRoutingTable newTable, final DOMRpcImplementation impl) {
-        for (Registration<?> l : listeners) {
+        for (RegImpl<?> l : listeners) {
             l.addRpc(newTable, impl);
         }
     }
 
-    @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
-            justification = "https://github.com/spotbugs/spotbugs/issues/811")
     private synchronized void notifyAdded(final DOMRpcRoutingTable newTable,
             final Collection<? extends DOMRpcImplementation> impls) {
-        for (Registration<?> l : listeners) {
+        for (RegImpl<?> l : listeners) {
             for (DOMRpcImplementation impl : impls) {
                 l.addRpc(newTable, impl);
             }
         }
     }
 
-    @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
-            justification = "https://github.com/spotbugs/spotbugs/issues/811")
     private synchronized void notifyRemoved(final DOMRpcRoutingTable newTable, final DOMRpcImplementation impl) {
-        for (Registration<?> l : listeners) {
+        for (RegImpl<?> l : listeners) {
             l.removeRpc(newTable, impl);
         }
     }
 
-    @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
-            justification = "https://github.com/spotbugs/spotbugs/issues/811")
     private synchronized void notifyRemoved(final DOMRpcRoutingTable newTable,
             final Collection<? extends DOMRpcImplementation> impls) {
-        for (Registration<?> l : listeners) {
+        for (RegImpl<?> l : listeners) {
             for (DOMRpcImplementation impl : impls) {
                 l.removeRpc(newTable, impl);
             }
@@ -269,22 +250,25 @@ public final class DOMRpcRouter extends AbstractRegistration
     }
 
     @VisibleForTesting
-    synchronized Collection<?> listeners() {
+    synchronized List<?> listeners() {
         return listeners;
     }
 
+    @VisibleForTesting
+    synchronized List<?> actionListeners() {
+        return actionListeners;
+    }
+
     @VisibleForTesting
     DOMRpcRoutingTable routingTable() {
         return routingTable;
     }
 
-    private static final class Registration<T extends DOMRpcAvailabilityListener>
-        extends AbstractListenerRegistration<T> {
-
+    private static final class RegImpl<T extends DOMRpcAvailabilityListener> extends AbstractListenerRegistration<T> {
         private Map<QName, Set<YangInstanceIdentifier>> prevRpcs;
         private DOMRpcRouter router;
 
-        Registration(final DOMRpcRouter router, final T listener, final Map<QName, Set<YangInstanceIdentifier>> rpcs) {
+        RegImpl(final DOMRpcRouter router, final T listener, final Map<QName, Set<YangInstanceIdentifier>> rpcs) {
             super(listener);
             this.router = requireNonNull(router);
             this.prevRpcs = requireNonNull(rpcs);
@@ -297,7 +281,7 @@ public final class DOMRpcRouter extends AbstractRegistration
         }
 
         void initialTable() {
-            final Collection<DOMRpcIdentifier> added = new ArrayList<>();
+            final List<DOMRpcIdentifier> added = new ArrayList<>();
             for (Entry<QName, Set<YangInstanceIdentifier>> e : prevRpcs.entrySet()) {
                 added.addAll(Collections2.transform(e.getValue(), i -> DOMRpcIdentifier.create(e.getKey(), i)));
             }
@@ -315,7 +299,7 @@ public final class DOMRpcRouter extends AbstractRegistration
             final Map<QName, Set<YangInstanceIdentifier>> rpcs = verifyNotNull(newTable.getOperations(l));
             final MapDifference<QName, Set<YangInstanceIdentifier>> diff = Maps.difference(prevRpcs, rpcs);
 
-            final Collection<DOMRpcIdentifier> added = new ArrayList<>();
+            final List<DOMRpcIdentifier> added = new ArrayList<>();
             for (Entry<QName, Set<YangInstanceIdentifier>> e : diff.entriesOnlyOnRight().entrySet()) {
                 added.addAll(Collections2.transform(e.getValue(), i -> DOMRpcIdentifier.create(e.getKey(), i)));
             }
@@ -340,7 +324,7 @@ public final class DOMRpcRouter extends AbstractRegistration
             final Map<QName, Set<YangInstanceIdentifier>> rpcs = verifyNotNull(newTable.getOperations(l));
             final MapDifference<QName, Set<YangInstanceIdentifier>> diff = Maps.difference(prevRpcs, rpcs);
 
-            final Collection<DOMRpcIdentifier> removed = new ArrayList<>();
+            final List<DOMRpcIdentifier> removed = new ArrayList<>();
             for (Entry<QName, Set<YangInstanceIdentifier>> e : diff.entriesOnlyOnLeft().entrySet()) {
                 removed.addAll(Collections2.transform(e.getValue(), i -> DOMRpcIdentifier.create(e.getKey(), i)));
             }
@@ -377,7 +361,7 @@ public final class DOMRpcRouter extends AbstractRegistration
         }
 
         void initialTable() {
-            final Collection<DOMActionInstance> added = new ArrayList<>();
+            final List<DOMActionInstance> added = new ArrayList<>();
             for (Entry<Absolute, Set<DOMDataTreeIdentifier>> e : prevActions.entrySet()) {
                 added.addAll(Collections2.transform(e.getValue(), i -> DOMActionInstance.of(e.getKey(), i)));
             }
@@ -469,6 +453,7 @@ public final class DOMRpcRouter extends AbstractRegistration
         @Override
         public <T extends DOMActionImplementation> ObjectRegistration<T> registerActionImplementation(
                 final T implementation, final Set<DOMActionInstance> instances) {
+            checkArgument(!instances.isEmpty(), "Instances must not be empty");
 
             synchronized (DOMRpcRouter.this) {
                 final DOMActionRoutingTable oldTable = actionRoutingTable;
@@ -502,9 +487,8 @@ public final class DOMRpcRouter extends AbstractRegistration
         @Override
         public <T extends DOMRpcAvailabilityListener> ListenerRegistration<T> registerRpcListener(final T listener) {
             synchronized (DOMRpcRouter.this) {
-                final Registration<T> ret = new Registration<>(DOMRpcRouter.this, listener,
-                    routingTable.getOperations(listener));
-                listeners = ImmutableList.<Registration<?>>builder().addAll(listeners).add(ret).build();
+                final RegImpl<T> ret = new RegImpl<>(DOMRpcRouter.this, listener, routingTable.getOperations(listener));
+                listeners = ImmutableList.<RegImpl<?>>builder().addAll(listeners).add(ret).build();
 
                 listenerNotifier.execute(ret::initialTable);
                 return ret;
@@ -585,10 +569,10 @@ public final class DOMRpcRouter extends AbstractRegistration
             if (entry instanceof UnknownDOMRpcRoutingTableEntry) {
                 return Futures.immediateFailedFuture(
                     new DOMRpcImplementationNotAvailableException("%s is not resolved to an RPC", entry.getType()));
-            } else if (entry instanceof RoutedDOMRpcRoutingTableEntry) {
-                return invokeRoutedRpc((RoutedDOMRpcRoutingTableEntry) entry, input);
-            } else if (entry instanceof GlobalDOMRpcRoutingTableEntry) {
-                return invokeGlobalRpc((GlobalDOMRpcRoutingTableEntry) entry, input);
+            } else if (entry instanceof RoutedDOMRpcRoutingTableEntry routed) {
+                return invokeRoutedRpc(routed, input);
+            } else if (entry instanceof GlobalDOMRpcRoutingTableEntry global) {
+                return invokeGlobalRpc(global, input);
             }
 
             return Futures.immediateFailedFuture(
@@ -604,9 +588,7 @@ public final class DOMRpcRouter extends AbstractRegistration
             if (maybeKey.isPresent()) {
                 final NormalizedNode key = maybeKey.get();
                 final Object value = key.body();
-                if (value instanceof YangInstanceIdentifier) {
-                    final YangInstanceIdentifier iid = (YangInstanceIdentifier) value;
-
+                if (value instanceof YangInstanceIdentifier iid) {
                     // Find a DOMRpcImplementation for a specific iid
                     final List<DOMRpcImplementation> specificImpls = entry.getImplementations(iid);
                     if (specificImpls != null) {