Fix some sonars in policy-models
[policy/models.git] / models-interactions / model-actors / actorServiceProvider / src / main / java / org / onap / policy / controlloop / actorserviceprovider / pipeline / ListenerManager.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP
4  * ================================================================================
5  * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.policy.controlloop.actorserviceprovider.pipeline;
22
23 import java.util.ArrayList;
24 import java.util.HashMap;
25 import java.util.Map;
26 import lombok.Getter;
27 import lombok.NoArgsConstructor;
28 import org.onap.policy.controlloop.actorserviceprovider.Util;
29
30 /**
31  * Listener manager, used by operations within the pipeline to determine if they should
32  * continue to run. When {@link #stop()} is called, the listeners are executed. The
33  * various methods synchronize on "this" while they manipulate internal data structures.
34  */
35 @NoArgsConstructor
36 public class ListenerManager {
37
38     @Getter
39     private volatile boolean running = true;
40
41     /**
42      * Listeners to be executed when {@link #stop()} is invoked.
43      */
44     private final Map<Runnable, Void> listeners = new HashMap<>(5);
45
46     /**
47      * Indicates that operations within the pipeline should stop executing.
48      */
49     public void stop() {
50         ArrayList<Runnable> items;
51
52         synchronized (this) {
53             if (!running) {
54                 return;
55             }
56
57             running = false;
58             items = new ArrayList<>(listeners.keySet());
59             listeners.clear();
60         }
61
62         items.forEach(this::runListener);
63     }
64
65     /**
66      * Adds a listener that is to be invoked when this controller is stopped. Note: if the
67      * controller is already stopped, then the listener will be invoked immediately,
68      * within the invoking thread.
69      *
70      * @param listener listener to be added
71      */
72     public void add(Runnable listener) {
73         if (!addOnly(listener)) {
74             runListener(listener);
75         }
76     }
77
78     /**
79      * Adds a listener that is to be invoked when this controller is stopped. Note: if the
80      * controller is already stopped, then the listener will be invoked immediately,
81      * within the invoking thread.
82      *
83      * @param listener listener to be added
84      * @return {@code true} if the the listener was added, {@code false} if it could not
85      *         be added because this manager has already been stopped
86      */
87     protected boolean addOnly(Runnable listener) {
88         synchronized (this) {
89             if (running) {
90                 listeners.put(listener, null);
91                 return true;
92             }
93         }
94
95         return false;
96     }
97
98     /**
99      * Runs a listener, catching any exceptions that it may throw.
100      *
101      * @param listener listener to be executed
102      */
103     protected void runListener(Runnable listener) {
104         Util.runFunction(listener, "pipeline listener {} threw an exception", listener);
105     }
106
107     /**
108      * Removes a listener so that it is not invoked when this controller is stopped.
109      *
110      * @param listener listener to be removed
111      */
112     public synchronized void remove(Runnable listener) {
113         listeners.remove(listener);
114     }
115 }