Merge "Bug 1029: Remove dead code: samples/clustersession"
[controller.git] / opendaylight / adsal / sal / api / src / main / java / org / opendaylight / controller / sal / utils / ListenerDispatcher.java
1 /*
2  * Copyright (c) 2011 Big Switch Networks, Inc.
3  *
4  * Licensed under the Eclipse Public License, Version 1.0 (the
5  * "License"); you may not use this file except in compliance with the
6  * License. You may obtain a copy of the License at
7  *
8  *      http://www.eclipse.org/legal/epl-v10.html
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
13  * implied. See the License for the specific language governing
14  * permissions and limitations under the License.
15  *
16  * This file incorporates work covered by the following copyright and
17  * permission notice:
18  *
19  *    Originally created by David Erickson, Stanford University
20  *
21  *    Licensed under the Apache License, Version 2.0 (the "License");
22  *    you may not use this file except in compliance with the
23  *    License. You may obtain a copy of the License at
24  *
25  *         http://www.apache.org/licenses/LICENSE-2.0
26  *
27  *    Unless required by applicable law or agreed to in writing,
28  *    software distributed under the License is distributed on an "AS
29  *    IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
30  *    express or implied. See the License for the specific language
31  *    governing permissions and limitations under the License.
32  */
33
34 package org.opendaylight.controller.sal.utils;
35
36 import java.util.ArrayList;
37 import java.util.HashSet;
38 import java.util.List;
39
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
42
43 /**
44  * Maintain lists of listeners ordered by dependency.
45  *
46  * @author readams
47  *
48  */
49 public class ListenerDispatcher<U, T extends IListener<U>> {
50     protected static Logger logger = LoggerFactory
51             .getLogger(ListenerDispatcher.class);
52     volatile List<T> listeners = new ArrayList<T>();
53
54     private void visit(List<T> newlisteners, U type, HashSet<T> visited,
55             List<T> ordering, T listener) {
56         if (!visited.contains(listener)) {
57             visited.add(listener);
58
59             for (T i : newlisteners) {
60                 if (ispre(type, i, listener)) {
61                     visit(newlisteners, type, visited, ordering, i);
62                 }
63             }
64             ordering.add(listener);
65         }
66     }
67
68     private boolean ispre(U type, T l1, T l2) {
69         return (l2.isCallbackOrderingPrereq(type, l1.getName()) || l1
70                 .isCallbackOrderingPostreq(type, l2.getName()));
71     }
72
73     /**
74      * Add a listener to the list of listeners
75      *
76      * @param listener
77      */
78     public void addListener(U type, T listener) {
79         List<T> newlisteners = new ArrayList<T>();
80         if (listeners != null)
81             newlisteners.addAll(listeners);
82
83         newlisteners.add(listener);
84         // Find nodes without outgoing edges
85         List<T> terminals = new ArrayList<T>();
86         for (T i : newlisteners) {
87             boolean isterm = true;
88             for (T j : newlisteners) {
89                 if (ispre(type, i, j)) {
90                     isterm = false;
91                     break;
92                 }
93             }
94             if (isterm) {
95                 terminals.add(i);
96             }
97         }
98
99         if (terminals.size() == 0) {
100             logger.error("No listener dependency solution: "
101                     + "No listeners without incoming dependencies");
102             listeners = newlisteners;
103             return;
104         }
105
106         // visit depth-first traversing in the opposite order from
107         // the dependencies. Note we will not generally detect cycles
108         HashSet<T> visited = new HashSet<T>();
109         List<T> ordering = new ArrayList<T>();
110         for (T term : terminals) {
111             visit(newlisteners, type, visited, ordering, term);
112         }
113         listeners = ordering;
114     }
115
116     /**
117      * Remove the given listener
118      *
119      * @param listener
120      *            the listener to remove
121      */
122     public void removeListener(T listener) {
123         if (listeners != null) {
124             List<T> newlisteners = new ArrayList<T>();
125             newlisteners.addAll(listeners);
126             newlisteners.remove(listener);
127             listeners = newlisteners;
128         }
129     }
130
131     /**
132      * Clear all listeners
133      */
134     public void clearListeners() {
135         listeners = new ArrayList<T>();
136     }
137
138     /**
139      * Get the ordered list of listeners ordered by dependencies
140      *
141      * @return
142      */
143     public List<T> getOrderedListeners() {
144         return listeners;
145     }
146 }