blob: 409c744dd4178017659c82427fcab202a6ef5988 [file] [log] [blame]
package org.eclipse.jst.jsf.common.internal.locator;
import java.util.concurrent.CopyOnWriteArrayList;
import org.eclipse.jst.jsf.common.internal.locator.ILocatorChangeListener.LocatorChangeEvent;
/**
* The abstract base class of all ILocator implementations.
*
* @author cbateman
*
* @param <LOCATORTYPE>
* @param <CONTEXTTYPE>
* @param <IDTYPE>
*/
public abstract class AbstractLocator<LOCATORTYPE, CONTEXTTYPE, IDTYPE>
implements ILocator<LOCATORTYPE, CONTEXTTYPE, IDTYPE>
{
/**
* The default value used for "no result".
*/
protected static final Object DEFAULT_NO_RESULT_VALUE = null;
private final CopyOnWriteArrayList<ILocatorChangeListener> _listeners;
private final LOCATORTYPE _noResultValue;
private final IDTYPE _id;
private final String _displayName;
private boolean _isStarted;
private Exception _startTrace;
/**
* Available for sub-classes that want to use reasonable defaults and only provide
* mandatory data.
*
* No result value is null.
* A new instance of CopyOnWriteArrayList is used and held private.
*
* @param id
* @param displayName
*
*/
public AbstractLocator(final IDTYPE id, final String displayName)
{
this(id,
displayName,
null,
new CopyOnWriteArrayList<ILocatorChangeListener>());
}
/**
* Available for sub-classes to manually inject dependencies.
*
* @param id
* @param displayName
* @param noResultValue
* @param mutableListenerList
*/
protected AbstractLocator(
final IDTYPE id,
final String displayName,
final LOCATORTYPE noResultValue,
final CopyOnWriteArrayList<ILocatorChangeListener> mutableListenerList)
{
_id = id;
_displayName = displayName;
_listeners = mutableListenerList;
_noResultValue = noResultValue;
}
public final LOCATORTYPE perform(final CONTEXTTYPE context)
throws Exception
{
return locate(context);
}
public LOCATORTYPE getNoResult()
{
return _noResultValue;
}
public IDTYPE getId()
{
return _id;
}
public String getDisplayName()
{
return _displayName;
}
public LOCATORTYPE locate(final CONTEXTTYPE context)
{
if (isStarted())
{
return doLocate(context);
}
throw new IllegalStateException("Locator not started"); //$NON-NLS-1$
}
/**
* @param context
* @return the located type.
*/
protected abstract LOCATORTYPE doLocate(CONTEXTTYPE context);
public void start(final CONTEXTTYPE initialContext)
{
if (isStarted())
{
throw new IllegalStateException("Locator was already started", _startTrace); //$NON-NLS-1$
}
// set the started flag
setStarted(true);
_startTrace = new Exception("Locator was started on this trace"); //$NON-NLS-1$
}
public void stop()
{
// set the started flag
// clear all listeners
_listeners.clear();
setStarted(false);
_startTrace = null;
}
/**
* @param listener
*/
public void addListener(final ILocatorChangeListener listener)
{
_listeners.addIfAbsent(listener);
}
/**
* @param listener
*/
public void removeListener(final ILocatorChangeListener listener)
{
_listeners.remove(listener);
}
/**
* @param event
*/
protected void fireChangeEvent(final LocatorChangeEvent event)
{
for (final ILocatorChangeListener listener : _listeners)
{
listener.changed(event);
}
}
public final boolean isStarted()
{
return _isStarted;
}
public boolean canStart()
{
if (isStarted())
{
return false;
}
return true;
}
/**
* @param newValue
*/
protected final void setStarted(final boolean newValue)
{
_isStarted = newValue;
}
}