blob: c0aeca3b9a2cc35ff105fb806c4374e89bbd6e58 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2016 Red Hat Inc. 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:
* Mickael Istria (Red Hat Inc.) - initial API and implementation
*******************************************************************************/
package org.eclipse.epp.internal.mpc.ui.discovery;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import org.eclipse.core.runtime.jobs.JobGroup;
import org.eclipse.epp.internal.mpc.ui.MarketplaceClientUiPlugin;
import org.eclipse.epp.internal.mpc.ui.Messages;
import org.eclipse.epp.mpc.core.model.INode;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.ui.IStartup;
public class MissingNatureDetector implements IStartup, IPropertyChangeListener {
public static final String ENABLEMENT_PROPERTY = "org.eclipse.epp.mpc.naturelookup"; //$NON-NLS-1$
private JobGroup allJobs;
private final Set<String> detectedNatures = new HashSet<String>();
private final Set<LookupByNatureJob> lookupJobs = new HashSet<LookupByNatureJob>();
private final IResourceChangeListener projectOpenListener = new IResourceChangeListener() {
public void resourceChanged(IResourceChangeEvent event) {
if (event.getDelta() == null) {
return;
}
try {
CollectMissingNaturesVisitor visitor = new CollectMissingNaturesVisitor();
event.getDelta().accept(visitor);
for (String natureId : visitor.getMissingNatures()) {
triggerNatureLookup(natureId);
}
if (!visitor.getMissingNatures().isEmpty()) {
showProposalsIfReady();
}
} catch (CoreException e) {
MarketplaceClientUiPlugin.getInstance().getLog().log(
new Status(IStatus.ERROR, MarketplaceClientUiPlugin.getInstance().getBundle().getSymbolicName(),
e.getLocalizedMessage(), e));
}
}
};
public MissingNatureDetector() {
super();
}
private void triggerNatureLookup(final String natureId) {
synchronized (lookupJobs) {
if (detectedNatures.contains(natureId)) {
return;
} else {
LookupByNatureJob mpcJob = new LookupByNatureJob(natureId);
mpcJob.setSystem(false);
mpcJob.setUser(false);
mpcJob.setJobGroup(allJobs);
mpcJob.addJobChangeListener(new JobChangeAdapter() {
@Override
public void done(IJobChangeEvent event) {
showProposalsIfReady();
}
});
lookupJobs.add(mpcJob);
//schedule() needs to happen inside synchronized(...).
//Otherwise it's not guaranteed that allJobs.getActiveJobs() will consider it,
//and we might end up with processing unfinished jobs in showProposalsIfReady()
mpcJob.schedule();
}
}
}
private void showProposalsIfReady() {
Map<String, Collection<INode>> candidates;
synchronized (lookupJobs) {
if (!allJobs.getActiveJobs().isEmpty()) {
return;
}
candidates = new HashMap<String, Collection<INode>>();
for (LookupByNatureJob lookupJob : lookupJobs) {
Collection<INode> entryCandidates = lookupJob.getCandidates();
if (entryCandidates != null && !entryCandidates.isEmpty()) {
candidates.put(lookupJob.getNatureId(), entryCandidates);
}
}
lookupJobs.clear();
}
if (!candidates.isEmpty()) {
new ShowNatureProposalsJob(candidates).schedule();
}
}
public void earlyStartup() {
allJobs = new JobGroup(Messages.MissingNatureDetector_Title, 3, 0);
IPreferenceStore preferenceStore = MarketplaceClientUiPlugin.getInstance().getPreferenceStore();
preferenceStore.addPropertyChangeListener(this);
boolean preferenceValue = preferenceStore.getBoolean(ENABLEMENT_PROPERTY);
if (preferenceValue) {
ResourcesPlugin.getWorkspace().addResourceChangeListener(projectOpenListener);
}
}
public void propertyChange(PropertyChangeEvent event) {
if (ENABLEMENT_PROPERTY.equals(event.getProperty())) {
IWorkspace workspace = ResourcesPlugin.getWorkspace();
if ((Boolean) event.getNewValue()) {
workspace.addResourceChangeListener(this.projectOpenListener);
} else {
workspace.removeResourceChangeListener(this.projectOpenListener);
}
}
}
}