/*
* JBoss, Home of Professional Open Source.
*
* See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing.
*
* See the AUTHORS.txt file distributed with this work for a full listing of individual contributors.
*/
package org.teiid.designer.advisor.ui.core.status;
import java.util.ArrayList;
import java.util.Collection;
import java.util.EventObject;
import java.util.Iterator;
import java.util.List;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IMarkerDelta;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import org.eclipse.swt.widgets.Display;
import org.teiid.core.designer.event.EventObjectListener;
import org.teiid.core.designer.event.EventSourceException;
import org.teiid.core.designer.event.IChangeListener;
import org.teiid.core.designer.event.IChangeNotifier;
import org.teiid.designer.advisor.ui.AdvisorUiConstants;
import org.teiid.designer.advisor.ui.views.status.StatusListener;
import org.teiid.designer.core.ModelerCore;
import org.teiid.designer.ui.UiPlugin;
import org.teiid.designer.ui.common.viewsupport.JobUtils;
import org.teiid.designer.ui.event.ModelResourceEvent;
/**
*
*/
public class AdvisorStatusManager implements IChangeListener, IStatusManager {
private Object currentObject;
private static final String ID = "DefaultStatusManager"; //$NON-NLS-1$
private static final String ADVISOR_JOB_NAME = "Workspace Advisor Validation"; //$NON-NLS-1$
private static final String AUTOBUILD_JOB_NAME = "Building workspace"; //$NON-NLS-1$
public static final Object FAMILY_ADVISOR_STATUS = new Object();
private static Collection statusListeners;
private EventObjectListener modelResourceListener;
private IResourceChangeListener resourceListener;
private AdvisorStatus currentStatus;
private AdvisorStatusUpdateJob statusRefreshJob;
private AutoBuildJobListener autoBuildJobListener;
boolean isListeningForBuildComplete = false;
public AdvisorStatusManager() {
super();
setup();
statusListeners = new ArrayList();
this.autoBuildJobListener = new AutoBuildJobListener();
// viewWorker = VdbViewUtil.getVdbViewWorker();
this.statusRefreshJob = getNewStatusUpdateJob();
// Connect to VdbView
registerAsListener();
// System.out.println(" WebServicesValidationManager.init() calling updateStatus()");
updateStatus(false);
}
public void addListener( IAdvisorStatusListener listener ) {
if (statusListeners == null) {
statusListeners = new ArrayList();
}
statusListeners.add(listener);
// System.out.println(" WebServicesValidationManager.addListener() calling updateStatus()");
updateStatus(false);
}
/**
* Method for plugin to call during stop() so this class can unregister itself as a listener.
*
* @since 4.3
*/
public void dispose() {
ModelerCore.getWorkspace().removeResourceChangeListener(resourceListener);
try {
UiPlugin.getDefault().getEventBroker().removeListener(ModelResourceEvent.class, modelResourceListener);
} catch (EventSourceException e) {
AdvisorUiConstants.UTIL.log(IStatus.ERROR, e, e.getMessage());
}
}
protected void generateNewStatus() {
System.out.println("AdvisorStatusManager.generateNewStatus() (NO OP METHOD)"); //$NON-NLS-1$
}
/**
* @return Returns the currentStatus.
* @since 4.3
*/
public AdvisorStatus getCurrentStatus() {
return this.currentStatus;
}
public void setCurrentStatus( AdvisorStatus status ) {
this.currentStatus = status;
}
/**
* @return currentObject
*/
public Object getCurrentObject() {
return currentObject;
}
/**
* String ID defined for the specific contribution to AdvisorStatusExtensionManger Should be overridden
*
* @return Id the unique string ID of the status manager contribution
*/
public String getId() {
return ID;
}
protected Object getJobFamily() {
return FAMILY_ADVISOR_STATUS;
}
protected String getJobName() {
return ADVISOR_JOB_NAME;
}
/**
* Utility method to get a snapshot status of the current Vdb Context.
*
* @return
* @since 5.0
*/
public AdvisorStatus getStatusSnapshot() {
return null;
}
public AdvisorStatusUpdateJob getNewStatusUpdateJob() {
return new AdvisorStatusUpdateJob(getJobName(), this);
}
protected void setup() {
// NO OP
}
protected void notifyStatusChanged( AdvisorStatus status ) {
this.currentStatus = status;
if (shouldNotify()) {
for (Iterator iter = statusListeners.iterator(); iter.hasNext();) {
((IAdvisorStatusListener)iter.next()).notifyStatusChanged(status);
}
}
}
private void registerAsListener() {
// ----------------------------------------------------------
// REGISTER for VDB Context changes from VdbViewWorker and fire updateStatus
// ----------------------------------------------------------
// registerWithVdbViewWorker();
// -----------------------------------------------------------
// REGISTER for Resources changes and fire updateStatus when
// resources are added/removed, changed or reloaded
// -----------------------------------------------------------
modelResourceListener = new EventObjectListener() {
@Override
public void processEvent( EventObject obj ) {
final ModelResourceEvent event = (ModelResourceEvent)obj;
if (event.getType() == ModelResourceEvent.ADDED || event.getType() == ModelResourceEvent.CHANGED
|| event.getType() == ModelResourceEvent.RELOADED || event.getType() == ModelResourceEvent.REMOVED) {
// System.out.println(" WebServicesValidationManager.processEvent() calling updateStatus()");
updateStatus(false);
}
}
};
try {
org.teiid.designer.ui.UiPlugin.getDefault().getEventBroker().addListener(ModelResourceEvent.class,
modelResourceListener);
} catch (EventSourceException e) {
AdvisorUiConstants.UTIL.log(IStatus.ERROR, e, e.getMessage());
}
// -----------------------------------------------------------
// REGISTER for Resources Changes changes and fire updateStatus when
// deltas relating to vdb resources have changed
// -----------------------------------------------------------
resourceListener = new MarkerDeltaListener();
ModelerCore.getWorkspace().addResourceChangeListener(resourceListener);
}
public void removeListener( StatusListener listener ) {
if (statusListeners == null) {
statusListeners = new ArrayList();
}
statusListeners.remove(listener);
if (!statusListeners.isEmpty()) {
// System.out.println(" WebServicesValidationManager.removeListener() calling updateStatus()");
updateStatus(false);
}
}
/**
* @param currentObject Sets currentObject to the specified value.
*/
public boolean setCurrentObject( Object focusedObject ) {
if (currentObject != focusedObject) {
this.currentObject = focusedObject;
return true;
}
return false;
}
/**
* This method checks the job manager to determine if there is already a job in the QUEUE or not. We don't want more than ONE
* job in the queue (i.e. NOT running) so we don't do too much validation.
*
* @return
* @since 5.0
*/
private boolean shouldAddJob() {
boolean result = false;
Job[] wsJobs = Job.getJobManager().find(getJobFamily());
int nJobs = wsJobs.length;
if (JobUtils.jobIsRunning(getJobFamily())) {
// If Job is running, only return TRUE if there is Only One Job. If there are more than one, then
// there is already a queued job, so FALSE is OK
if (nJobs == 1) {
result = true;
}
} else if (nJobs == 0) {
// If NO Job is running, only return TRUE if there are NO Jobs in the queue.
result = true;
}
return result;
}
// /////////////////////////////////////////////////////////////////////////////////////////////
// JobListener INNER CLASSes
// /////////////////////////////////////////////////////////////////////////////////////////////
private boolean shouldNotify() {
boolean result = true;
// if (statusListeners != null && !statusListeners.isEmpty()) {
// // Check the workbench state
// WorkbenchState state = ProductCustomizerMgr.getInstance().getProductCharacteristics().getWorkbenchState();
// if (state.isStandard() || state.isStartingUp() && viewWorker != null) {
// if (viewWorker.isVdbOpen() && viewWorker.getCurrentVdbContext().getVirtualDatabase() != null) {
// result = true;
// } else if (!viewWorker.isVdbOpen()) {
// result = true;
// }
// }
// }
return result;
}
/**
* Need to be wired up to the current VDB Context.
*
* @see org.teiid.core.designer.event.IChangeListener#stateChanged(org.teiid.core.designer.event.IChangeNotifier)
* @since 5.0
*/
@Override
public void stateChanged( IChangeNotifier theSource ) {
// Just update, don't worry about state of context because updateStatus() will take care of changes
// System.out.println(" WebServicesValidationManager.stateChanged() calling updateStatus()");
updateStatus(false);
}
public void updateStatus( boolean forceUpdate ) {
// First check if the workbench state is OK and that there are listeners who care...
// IF NOT, then RETURN and DO NOTHING
if (!shouldNotify()) {
return;
}
// if (!registeredWithVdbViewWorker) {
// registerWithVdbViewWorker();
// }
if (JobUtils.validationJobsExist()) {
if (!isListeningForBuildComplete) {
if (ModelerCore.getWorkspace().isAutoBuilding()) {
// System.out.println(" WSVM.updateStatus(): ##### validation running #####. AUTOBUILD = " +
// ModelerCore.getWorkspace().isAutoBuilding());
Job.getJobManager().addJobChangeListener(this.autoBuildJobListener);
isListeningForBuildComplete = true;
} else {
isListeningForBuildComplete = false;
}
}
return;
}
// Update the status
boolean workspaceChanged = false;
boolean forceJob = false;
if (forceJob || shouldAddJob() || forceUpdate) {
// On startup, the Default display thread may not be available, so ....
if (Display.getDefault() == null) {
// System.out.println(" WSVM.updateStatus() No Default Thread, so update without it");
generateNewStatus();
if (getCurrentStatus() != null) {
// status.setWorkspaceChanged(workspaceChanged);
notifyStatusChanged(getCurrentStatus());
}
} else {
Display.getDefault().asyncExec(new Runnable() {
@Override
public void run() {
// System.out.println(" ---->>>> WSVM.updateStatus(): scheduling new JOB");
statusRefreshJob.schedule(400);
}
});
}
}
}
protected class AutoBuildJobListener extends JobChangeAdapter {
//
// methods
//
@Override
public void done( IJobChangeEvent theEvent ) {
if (!JobUtils.validationJobsExist() && theEvent.getJob().getName().equals(AUTOBUILD_JOB_NAME)) {
// System.out.println(" AutoBuildJobListener.done(): ##### validation Finished. ##### AUTOBUILD = " +
// ModelerCore.getWorkspace().isAutoBuilding());
updateStatus(false);
isListeningForBuildComplete = false;
}
}
}
protected final class MarkerDeltaListener implements IResourceChangeListener {
private void examineDelta( IMarkerDelta[] deltas,
List changes ) {
for (int idx = 0; idx < deltas.length; idx++) {
IMarkerDelta delta = deltas[idx];
int kind = delta.getKind();
if (kind == IResourceDelta.CHANGED) {
changes.add(deltas[idx].getMarker());
} // endif
} // endfor
}
@Override
public void resourceChanged( IResourceChangeEvent event ) {
// TODO find out if this handles both the enterprise and lightweight cases.
boolean refreshNeeded = false;
IMarkerDelta[] markerDeltas = event.findMarkerDeltas(IMarker.PROBLEM, true);
List<IMarkerDelta> changes = new ArrayList<IMarkerDelta>(markerDeltas.length);
examineDelta(markerDeltas, changes);
if (markerDeltas.length != changes.size()) {
refreshNeeded = true;
}
// Refresh everything if markers were added or removed
if (refreshNeeded) {
// System.out.println(" WebServicesValidationManager.resourceChanged(MARKERS) calling updateStatus()");
updateStatus(false);
} // endif
}
} // endclass MarkerDeltaListener
@Override
public void shutdown() {
// TODO Auto-generated method stub
}
@Override
public void startup() {
// TODO Auto-generated method stub
}
}