/*
* Copyright (c) 2010-2012 Research In Motion Limited. All rights reserved.
*
* This program and the accompanying materials are made available
* under the terms of the Eclipse Public License, Version 1.0,
* which accompanies this distribution and is available at
*
* http://www.eclipse.org/legal/epl-v10.html
*
*/
package net.rim.ejde.internal.validation;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;
import org.eclipse.core.resources.IProject;
import org.eclipse.emf.common.util.Diagnostic;
/**
* @author cbateman
*/
public class DiagnosticManager {
/** The logger. */
private static final Logger _logger = Logger.getLogger( DiagnosticManager.class );
private final Map< IProject, Map< Object, BBDiagnostic >> _registry = new HashMap< IProject, Map< Object, BBDiagnostic >>();
private final List< IDiagnosticManagerChangeListener > _listeners = new ArrayList< IDiagnosticManagerChangeListener >();
private boolean _firingEvents = false;
// TODO: review this way of doing it
// listeners that get added during event firing
// they are only added/removed *after* the existing listeners
// are all processed
private final List< IDiagnosticManagerChangeListener > _deferredAddListeners = new ArrayList< IDiagnosticManagerChangeListener >();
private final List< IDiagnosticManagerChangeListener > _deferredRemoveListeners = new ArrayList< IDiagnosticManagerChangeListener >();
protected synchronized void put( IProject project, Object forThisObject, BBDiagnostic diagnostic ) {
// This is extra logging to watch for null projects
if( project == null ) {
_logger.error( "Null Project has added a diagnostic: " + diagnostic.getMessage() + " for:" + forThisObject );
}
Map< Object, BBDiagnostic > projectRegistry = getProjectRegistry( project );
if( diagnostic.getSeverity() != Diagnostic.OK ) {
BBDiagnostic oldDiagnostic = projectRegistry.get( forThisObject );
if( oldDiagnostic == null || !oldDiagnostic.compare( diagnostic ) ) {
projectRegistry.put( forThisObject, diagnostic );
fireAddedEvent( project, forThisObject, diagnostic );
}
} else {
projectRegistry.remove( forThisObject );
fireRemovedEvent( project, forThisObject );
}
}
public BBDiagnostic get( IProject project, Object forThisObject ) {
BBDiagnostic wdiag = null;
Map< Object, BBDiagnostic > projectRegistry = getProjectRegistry( project );
wdiag = projectRegistry.get( forThisObject );
return wdiag;
}
private Map< Object, BBDiagnostic > getProjectRegistry( IProject project ) {
Map< Object, BBDiagnostic > registry = _registry.get( project );
if( registry == null ) {
registry = new HashMap< Object, BBDiagnostic >();
_registry.put( project, registry );
}
return registry;
}
protected void removeProjectRegistry( IProject project ) {
_registry.remove( project );
fireRemovedProject( project );
}
protected void cleanObjectDiags( IProject project, Object obj ) {
Map< Object, BBDiagnostic > omap = _registry.get( project );
if( omap != null && omap.size() > 0 ) {
omap.remove( obj );
}
}
public void addChangeListener( IDiagnosticManagerChangeListener listener ) {
// if this method is not being called nested in a event firing
if( !_firingEvents ) {
if( !_listeners.contains( listener ) ) {
_listeners.add( listener );
}
} else {
if( !_deferredAddListeners.contains( listener ) ) {
_deferredAddListeners.add( listener );
}
}
}
public void removeChangeListener( IDiagnosticManagerChangeListener listener ) {
if( !_firingEvents ) {
_listeners.remove( listener );
} else {
_deferredRemoveListeners.add( listener );
}
}
protected void fireAddedEvent( IProject project, Object target, BBDiagnostic diagnostic ) {
_firingEvents = true;
for( Iterator< IDiagnosticManagerChangeListener > it = _listeners.iterator(); it.hasNext(); ) {
IDiagnosticManagerChangeListener listener = it.next();
listener.addedDiagnostic( project, target, diagnostic );
}
processDeferredEvents();
}
protected void fireRemovedEvent( IProject project, Object target ) {
_firingEvents = true;
for( Iterator< IDiagnosticManagerChangeListener > it = _listeners.iterator(); it.hasNext(); ) {
IDiagnosticManagerChangeListener listener = it.next();
listener.removedDiagnostic( project, target );
}
processDeferredEvents();
}
protected void fireRemovedProject( IProject project ) {
_firingEvents = true;
for( Iterator< IDiagnosticManagerChangeListener > it = _listeners.iterator(); it.hasNext(); ) {
IDiagnosticManagerChangeListener listener = it.next();
listener.removedProject( project );
}
processDeferredEvents();
}
protected void processDeferredEvents() {
// removes take precendence
_firingEvents = false;
processDeferredAddEvents();
processDeferredRemoveEvents();
}
protected void processDeferredRemoveEvents() {
_firingEvents = false;
for( Iterator< IDiagnosticManagerChangeListener > it = _deferredRemoveListeners.iterator(); it.hasNext(); ) {
IDiagnosticManagerChangeListener listener = it.next();
removeChangeListener( listener );
it.remove();
}
}
protected void processDeferredAddEvents() {
for( Iterator< IDiagnosticManagerChangeListener > it = _deferredAddListeners.iterator(); it.hasNext(); ) {
IDiagnosticManagerChangeListener listener = it.next();
addChangeListener( listener );
it.remove();
}
}
}