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.
50 public class ListenerDispatcher<U, T extends IListener<U>> {
51 protected static Logger logger = LoggerFactory
52 .getLogger(ListenerDispatcher.class);
53 volatile List<T> listeners = new ArrayList<T>();
55 private void visit(List<T> newlisteners, U type, HashSet<T> visited,
56 List<T> ordering, T listener) {
57 if (!visited.contains(listener)) {
58 visited.add(listener);
60 for (T i : newlisteners) {
61 if (ispre(type, i, listener)) {
62 visit(newlisteners, type, visited, ordering, i);
65 ordering.add(listener);
69 private boolean ispre(U type, T l1, T l2) {
70 return (l2.isCallbackOrderingPrereq(type, l1.getName()) || l1
71 .isCallbackOrderingPostreq(type, l2.getName()));
75 * Add a listener to the list of listeners
79 public void addListener(U type, T listener) {
80 List<T> newlisteners = new ArrayList<T>();
81 if (listeners != null)
82 newlisteners.addAll(listeners);
84 newlisteners.add(listener);
85 // Find nodes without outgoing edges
86 List<T> terminals = new ArrayList<T>();
87 for (T i : newlisteners) {
88 boolean isterm = true;
89 for (T j : newlisteners) {
90 if (ispre(type, i, j)) {
100 if (terminals.size() == 0) {
101 logger.error("No listener dependency solution: "
102 + "No listeners without incoming dependencies");
103 listeners = newlisteners;
107 // visit depth-first traversing in the opposite order from
108 // the dependencies. Note we will not generally detect cycles
109 HashSet<T> visited = new HashSet<T>();
110 List<T> ordering = new ArrayList<T>();
111 for (T term : terminals) {
112 visit(newlisteners, type, visited, ordering, term);
114 listeners = ordering;
118 * Remove the given listener
121 * the listener to remove
123 public void removeListener(T listener) {
124 if (listeners != null) {
125 List<T> newlisteners = new ArrayList<T>();
126 newlisteners.addAll(listeners);
127 newlisteners.remove(listener);
128 listeners = newlisteners;
133 * Clear all listeners
135 public void clearListeners() {
136 listeners = new ArrayList<T>();
140 * Get the ordered list of listeners ordered by dependencies
144 public List<T> getOrderedListeners() {