/* * Copyright (c) 2011 Big Switch Networks, Inc. * * Licensed under the Eclipse Public License, Version 1.0 (the * "License"); you may not use this file except in compliance with the * License. You may obtain a copy of the License at * * http://www.eclipse.org/legal/epl-v10.html * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * implied. See the License for the specific language governing * permissions and limitations under the License. * * This file incorporates work covered by the following copyright and * permission notice: * * Originally created by David Erickson, Stanford University * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the * License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS * IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the License for the specific language * governing permissions and limitations under the License. */ package org.opendaylight.controller.sal.utils; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Maintain lists of listeners ordered by dependency. * * @author readams * */ public class ListenerDispatcher> { protected static Logger logger = LoggerFactory .getLogger(ListenerDispatcher.class); volatile List listeners = new ArrayList(); private void visit(List newlisteners, U type, HashSet visited, List ordering, T listener) { if (!visited.contains(listener)) { visited.add(listener); for (T i : newlisteners) { if (ispre(type, i, listener)) { visit(newlisteners, type, visited, ordering, i); } } ordering.add(listener); } } private boolean ispre(U type, T l1, T l2) { return (l2.isCallbackOrderingPrereq(type, l1.getName()) || l1 .isCallbackOrderingPostreq(type, l2.getName())); } /** * Add a listener to the list of listeners * * @param listener */ public void addListener(U type, T listener) { List newlisteners = new ArrayList(); if (listeners != null) newlisteners.addAll(listeners); newlisteners.add(listener); // Find nodes without outgoing edges List terminals = new ArrayList(); for (T i : newlisteners) { boolean isterm = true; for (T j : newlisteners) { if (ispre(type, i, j)) { isterm = false; break; } } if (isterm) { terminals.add(i); } } if (terminals.size() == 0) { logger.error("No listener dependency solution: " + "No listeners without incoming dependencies"); listeners = newlisteners; return; } // visit depth-first traversing in the opposite order from // the dependencies. Note we will not generally detect cycles HashSet visited = new HashSet(); List ordering = new ArrayList(); for (T term : terminals) { visit(newlisteners, type, visited, ordering, term); } listeners = ordering; } /** * Remove the given listener * * @param listener * the listener to remove */ public void removeListener(T listener) { if (listeners != null) { List newlisteners = new ArrayList(); newlisteners.addAll(listeners); newlisteners.remove(listener); listeners = newlisteners; } } /** * Clear all listeners */ public void clearListeners() { listeners = new ArrayList(); } /** * Get the ordered list of listeners ordered by dependencies * * @return */ public List getOrderedListeners() { return listeners; } }