Fix raw type warnings and null safety errors
[mdsal.git] / dom / mdsal-dom-broker / src / main / java / org / opendaylight / mdsal / dom / broker / AbstractDOMRoutingTableEntry.java
1 /*
2  * Copyright (c) 2018 ZTE Corp. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.mdsal.dom.broker;
9
10 import com.google.common.annotations.Beta;
11 import com.google.common.annotations.VisibleForTesting;
12 import com.google.common.base.Preconditions;
13 import com.google.common.collect.ImmutableMap;
14 import com.google.common.collect.ImmutableMap.Builder;
15 import java.util.ArrayList;
16 import java.util.Comparator;
17 import java.util.EventListener;
18 import java.util.List;
19 import java.util.Map;
20 import java.util.Map.Entry;
21 import java.util.Set;
22 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
23
24 /**
25  * Abstract routing table entry definition for Action and RPC.
26  * @param <D> identifier type of RPC or Acton
27  * @param <M> implementation type of RPC or Acton
28  * @param <L> listener type of RPC or Acton
29  */
30 @Beta
31 abstract class AbstractDOMRoutingTableEntry<D, M, L extends EventListener> {
32     private final Map<D, List<M>> implementations;
33     private final SchemaPath type;
34
35     AbstractDOMRoutingTableEntry(final SchemaPath type, final Map<D, List<M>> implementations) {
36         this.type = Preconditions.checkNotNull(type);
37         this.implementations = Preconditions.checkNotNull(implementations);
38     }
39
40     SchemaPath getType() {
41         return type;
42     }
43
44     List<M> getImplementations(final D identifier) {
45         return implementations.get(identifier);
46     }
47
48     Map<D, List<M>> getImplementations() {
49         return implementations;
50     }
51
52     @VisibleForTesting
53     Set<D> registeredIdentifiers() {
54         return implementations.keySet();
55     }
56
57     protected abstract Set<D> registeredIdentifiers(L listener);
58
59     /**
60      * This method adds the given DOMOperationImplementation instance for the given list operation identifiers.
61      *
62      * @param implementation the DOMOperationImplementation instance to add
63      * @param newOprs  the List of new RPCs/Actions that the DOMOperationImplementation provides, must be mutable
64      * @return a new instance of DOMActionRoutingTableEntry with the additions
65      */
66     AbstractDOMRoutingTableEntry<D, M, L> add(final M implementation, final List<D> newOprs) {
67         final Builder<D, List<M>> vb = ImmutableMap.builder();
68         for (final Entry<D, List<M>> ve : implementations.entrySet()) {
69             if (newOprs.remove(ve.getKey())) {
70                 final List<M> i = new ArrayList<>(ve.getValue().size() + 1);
71                 i.addAll(ve.getValue());
72                 i.add(implementation);
73
74                 // New implementation is at the end, this will move it to be the last among implementations
75                 // with equal cost -- relying on sort() being stable.
76                 i.sort(implComparator());
77                 vb.put(ve.getKey(), i);
78             } else {
79                 vb.put(ve);
80             }
81         }
82         for (final D ii : newOprs) {
83             final List<M> impl = new ArrayList<>(1);
84             impl.add(implementation);
85             vb.put(ii, impl);
86         }
87
88         return newInstance(vb.build());
89     }
90
91     AbstractDOMRoutingTableEntry<D, M, L> remove(final M implementation, final List<D> removed) {
92         final Builder<D, List<M>> vb = ImmutableMap.builder();
93         for (final Entry<D, List<M>> ve : implementations.entrySet()) {
94             if (removed.remove(ve.getKey())) {
95                 final List<M> i = new ArrayList<>(ve.getValue());
96                 i.remove(implementation);
97                 // We could trimToSize(), but that may perform another copy just to get rid
98                 // of a single element. That is probably not worth the trouble.
99                 if (!i.isEmpty()) {
100                     vb.put(ve.getKey(), i);
101                 }
102             } else {
103                 vb.put(ve);
104             }
105         }
106
107         final Map<D, List<M>> v = vb.build();
108         return v.isEmpty() ? null : newInstance(vb.build());
109     }
110
111     protected abstract Comparator<M> implComparator();
112
113     protected abstract AbstractDOMRoutingTableEntry<D, M, L> newInstance(Map<D, List<M>> impls);
114 }