/*=============================================================================#
# Copyright (c) 2012-2016 Stephan Wahlbrink (WalWare.de) 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:
# Stephan Wahlbrink - initial API and implementation
#=============================================================================*/
package de.walware.statet.r.console.ui.tools;
import java.util.List;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IWorkbenchPage;
import org.osgi.framework.Version;
import de.walware.ecommons.preferences.PreferencesUtil;
import de.walware.ecommons.preferences.core.Preference.StringPref2;
import de.walware.ecommons.ts.ISystemRunnable;
import de.walware.ecommons.ts.ITool;
import de.walware.ecommons.ui.util.UIAccess;
import de.walware.statet.nico.ui.NicoUI;
import de.walware.statet.nico.ui.util.ToolMessageDialog;
import de.walware.statet.r.console.core.AbstractRController;
import de.walware.statet.r.console.core.AbstractRDataRunnable;
import de.walware.statet.r.console.core.IRDataAdapter;
import de.walware.statet.r.console.core.RProcess;
import de.walware.statet.r.core.pkgmanager.IRPkgInfoAndData;
import de.walware.statet.r.core.pkgmanager.IRPkgList;
import de.walware.statet.r.core.pkgmanager.IRPkgManager;
import de.walware.statet.r.core.pkgmanager.IRPkgSet;
import de.walware.statet.r.core.renv.IREnvConfiguration;
import de.walware.statet.r.core.renv.IREnvManager;
import de.walware.statet.r.core.renv.IRLibraryLocation;
import de.walware.statet.r.internal.console.ui.Messages;
import de.walware.statet.r.nico.impl.RjsController;
import de.walware.statet.r.ui.pkgmanager.RPkgManagerUI;
import de.walware.statet.r.ui.pkgmanager.StartAction;
public class REnvAutoUpdater extends AbstractRDataRunnable implements ISystemRunnable {
public static void connect(final RjsController controller, final IRPkgManager manager) {
if (controller == null || manager == null) {
return;
}
final REnvAutoUpdater checker= new REnvAutoUpdater(manager);
controller.getTool().getQueue().addOnIdle(checker, 1000);
}
private final IRPkgManager manager;
private boolean initial= true;
private boolean versionChecked;
private int checkStamp;
private REnvAutoUpdater(final IRPkgManager manager) {
super("r/renv/check", Messages.REnvIndex_Check_task); //$NON-NLS-1$
this.manager= manager;
}
@Override
public boolean changed(final int event, final ITool tool) {
if (event == MOVING_FROM) {
return false;
}
return true;
}
@Override
protected void run(final IRDataAdapter r, final IProgressMonitor monitor) throws CoreException {
final AbstractRController rjs= (AbstractRController) r;
if (rjs.isBusy() || !r.isDefaultPrompt() || r.getChangeStamp() == this.checkStamp) {
return;
}
int flags= 0;
if (this.initial) {
this.initial= false;
flags |= IRPkgManager.INITIAL;
}
this.manager.check(flags, r, monitor);
this.checkStamp= r.getChangeStamp();
if (!this.versionChecked) {
this.versionChecked= true;
checkRVersion(r, monitor);
}
}
private void checkRVersion(final IRDataAdapter r, final IProgressMonitor monitor) throws CoreException {
final Version rVersion= r.getPlatform().getRVersion();
final IREnvConfiguration rConfig= this.manager.getREnv().getConfig();
if (rConfig == null) {
return;
}
final StringPref2 pref= new StringPref2(
IREnvManager.PREF_QUALIFIER + '/' + rConfig.getReference().getId(),
"CheckedR.version" ); //$NON-NLS-1$
final String s= PreferencesUtil.getInstancePrefs().getPreferenceValue(pref);
if (s != null) {
final Version checkedVersion= new Version(s);
if (!checkedVersion.equals(rVersion)) {
PreferencesUtil.setPrefValue(InstanceScope.INSTANCE, pref, rVersion.toString());
if (checkedVersion.getMajor() != rVersion.getMajor()
|| checkedVersion.getMinor() != rVersion.getMinor() ) {
final IRPkgManager.Ext rPkgManager= (IRPkgManager.Ext) this.manager;
if (rPkgManager.requiresUpdate()) {
rPkgManager.update(r, monitor);
}
if (hasNonBasePackages(rPkgManager.getExtRPkgSet())) {
handleNewVersion(rConfig, r.getTool(), rPkgManager,
checkedVersion, rVersion );
}
}
}
}
else {
PreferencesUtil.setPrefValue(InstanceScope.INSTANCE, pref, rVersion.toString());
}
}
private static String mainVersionString(final Version version) {
final StringBuilder sb= new StringBuilder(8);
sb.append(version.getMajor());
sb.append('.');
sb.append(version.getMinor());
return sb.toString();
}
private boolean hasNonBasePackages(final IRPkgSet.Ext pkgSet) {
final List<? extends IRPkgList<? extends IRPkgInfoAndData>> all= pkgSet.getInstalled().getAll();
for (final IRPkgList<? extends IRPkgInfoAndData> pkgList : all) {
for (final IRPkgInfoAndData pkg : pkgList) {
if ((pkg.getLibraryLocation() == null || pkg.getLibraryLocation().getSource() != IRLibraryLocation.EPLUGIN)
&& !"base".equals(pkg.getPriority())) { //$NON-NLS-1$
return true;
}
}
}
return false;
}
private void handleNewVersion(final IREnvConfiguration rConfig, final RProcess tool,
final IRPkgManager.Ext rPkgManager, final Version oldVersion, final Version newVersion) {
final IWorkbenchPage page= NicoUI.getToolRegistry().findWorkbenchPage(tool);
final Shell shell= page.getWorkbenchWindow().getShell();
final Display display= UIAccess.getDisplay(shell);
display.asyncExec(new Runnable() {
@Override
public void run() {
if (ToolMessageDialog.openQuestion(tool, shell, Messages.REnvIndex_NewVersion_title,
NLS.bind(Messages.REnvIndex_NewVersion_message, new Object[] {
rConfig.getName(), mainVersionString(oldVersion),
mainVersionString(newVersion) }))) {
RPkgManagerUI.openDialog(rPkgManager, tool, shell,
new StartAction(StartAction.REINSTALL) );
}
}
});
}
}