2 * Copyright (c) 2011 Big Switch Networks, Inc.
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
8 * http://www.eclipse.org/legal/epl-v10.html
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.
16 * This file incorporates work covered by the following copyright and
19 * Originally created by David Erickson, Stanford University
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
25 * http://www.apache.org/licenses/LICENSE-2.0
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.
34 package org.opendaylight.controller.sal.utils;
36 import java.util.ArrayList;
37 import java.util.HashSet;
38 import java.util.List;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
44 * Maintain lists of listeners ordered by dependency.
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>();
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);
59 for (T i : newlisteners) {
60 if (ispre(type, i, listener)) {
61 visit(newlisteners, type, visited, ordering, i);
64 ordering.add(listener);
68 private boolean ispre(U type, T l1, T l2) {
69 return (l2.isCallbackOrderingPrereq(type, l1.getName()) || l1
70 .isCallbackOrderingPostreq(type, l2.getName()));
74 * Add a listener to the list of listeners
78 public void addListener(U type, T listener) {
79 List<T> newlisteners = new ArrayList<T>();
80 if (listeners != null)
81 newlisteners.addAll(listeners);
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)) {
99 if (terminals.size() == 0) {
100 logger.error("No listener dependency solution: "
101 + "No listeners without incoming dependencies");
102 listeners = newlisteners;
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);
113 listeners = ordering;
117 * Remove the given listener
120 * the listener to remove
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;
132 * Clear all listeners
134 public void clearListeners() {
135 listeners = new ArrayList<T>();
139 * Get the ordered list of listeners ordered by dependencies
143 public List<T> getOrderedListeners() {