blob: ee2a932f519852e312d57e149bf6ebcc19be3449 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2001, 2004 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);
}
}
}
}
}