/******************************************************************************* * Copyright (c) 2001, 2005 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Jens Lukowski/Innoopract - initial renaming/restructuring * *******************************************************************************/ package org.eclipse.wst.sse.core.internal.model; import org.eclipse.wst.sse.core.internal.Logger; import org.eclipse.wst.sse.core.internal.provisional.IModelLifecycleListener; import org.eclipse.wst.sse.core.internal.util.Utilities; /** * For "internal use" only by AbstractStructuredModel */ class LifecycleNotificationManager { private Object[] fListeners; LifecycleNotificationManager() { super(); } /** * Adds a new copy of the given listener to the list of Life Cycle * Listeners. * * Multiple copies of the same listener are allowed. This is required to * support threaded listener management properly and for model-driven move * to work. For example, two adds and a single remove should result in the * listener still listening for events. * * @param listener */ void addListener(IModelLifecycleListener listener) { if (Logger.DEBUG && Utilities.contains(fListeners, listener)) { Logger.log(Logger.WARNING, "IModelLifecycleListener " + listener + " listening more than once"); //$NON-NLS-1$ //$NON-NLS-2$ } int oldSize = 0; if (fListeners != null) { // normally won't be null, but we need to be sure, for first // time through oldSize = fListeners.length; } int newSize = oldSize + 1; Object[] newListeners = new Object[newSize]; if (fListeners != null) { System.arraycopy(fListeners, 0, newListeners, 0, oldSize); } // add listener to last position newListeners[newSize - 1] = listener; // // now switch new for old fListeners = newListeners; } /** * Removes a single copy of the given listener from the list of Life Cycle * Listeners. * * @param listener */ void removeListener(IModelLifecycleListener listener) { if (Utilities.contains(fListeners, listener)) { // if its not in the listeners, we'll ignore the request int oldSize = fListeners.length; int newSize = oldSize - 1; Object[] newListeners = new Object[newSize]; int index = 0; boolean removedOnce = false; for (int i = 0; i < oldSize; i++) { if (fListeners[i] == listener && !removedOnce) { // ignore on the first match removedOnce = true; } else { // copy old to new if it's not the one we are removing newListeners[index++] = fListeners[i]; } } // now that we have a new array, let's switch it for the old // one fListeners = newListeners; } if (Logger.DEBUG && Utilities.contains(fListeners, listener)) { Logger.log(Logger.WARNING, "IModelLifecycleListener " + listener + " removed once but still listening"); //$NON-NLS-1$ //$NON-NLS-2$ } } void signalLifecycleEvent(ModelLifecycleEvent event) { if (Logger.DEBUG_LIFECYCLE) { Logger.log(Logger.INFO, "ModelLifecycleEvent fired for " + event.getModel().getId() + ": " + event.toString()); //$NON-NLS-1$ //$NON-NLS-2$ System.out.println("ModelLifecycleEvent fired for " + event.getModel().getId() + ": " + event.toString()); //$NON-NLS-1$ //$NON-NLS-2$ } // We must assign listeners to local variable, since the add and // remove listener methods can change the actual instance of the // listener array from another thread if (fListeners != null) { Object[] holdListeners = fListeners; for (int i = 0; i < holdListeners.length; i++) { IModelLifecycleListener listener = (IModelLifecycleListener) holdListeners[i]; // only one type of listener for now ... this could become // more complex if ((event.getInternalType() & ModelLifecycleEvent.PRE_EVENT) == ModelLifecycleEvent.PRE_EVENT) { listener.processPreModelEvent(event); } if ((event.getInternalType() & ModelLifecycleEvent.POST_EVENT) == ModelLifecycleEvent.POST_EVENT) { listener.processPostModelEvent(event); } } } } }