/**
* Aptana Studio
* Copyright (c) 2005-2011 by Appcelerator, Inc. All Rights Reserved.
* Licensed under the terms of the GNU Public License (GPL) v3 (with exceptions).
* Please see the license.html included with this distribution for details.
* Any modifications to this file must keep this entire header intact.
*/
package com.aptana.syncing.ui.wizards;
import java.io.File;
import java.io.FilenameFilter;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.wizard.Wizard;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.IImportWizard;
import org.eclipse.ui.IWorkbench;
import com.aptana.ide.core.io.ConnectionPoint;
import com.aptana.ide.core.io.CoreIOPlugin;
import com.aptana.ide.core.io.IConnectionPoint;
import com.aptana.ide.syncing.core.ISiteConnection;
import com.aptana.ide.syncing.core.SyncingPlugin;
import com.aptana.ui.util.UIUtils;
/**
* @author Michael Xia (mxia@appcelerator.com)
*/
public class ImportConnectionsWizard extends Wizard implements IImportWizard
{
private static final String STATE_LOCATION_ROOT = ".metadata/.plugins/"; //$NON-NLS-1$
private ImportConnectionsPage mainPage;
public ImportConnectionsWizard()
{
}
@Override
public void addPages()
{
addPage(mainPage = new ImportConnectionsPage());
}
@Override
public boolean performFinish()
{
IPath location = mainPage.getLocation();
int connectionCount = 0, siteCount = 0;
int[] applyToAllAction = new int[] { -1 };
if (mainPage.isWorkspaceSelected())
{
// importing from workspace
// imports connection points
IPath connectionPath = location.append(STATE_LOCATION_ROOT).append("com.aptana.ide.core.io"); //$NON-NLS-1$
File dir = connectionPath.toFile();
if (dir.isDirectory())
{
// this is a 2.0 workspace
connectionCount = loadConnectionPoints(dir, applyToAllAction);
if (connectionCount == -1)
{
return false;
}
}
else
{
// checks if it is a 3.0 workspace
connectionPath = location.append(STATE_LOCATION_ROOT).append(CoreIOPlugin.PLUGIN_ID);
dir = connectionPath.toFile();
if (dir.isDirectory())
{
connectionCount = loadConnectionPoints(dir, applyToAllAction);
if (connectionCount == -1)
{
return false;
}
}
}
// imports site connections
IPath sitePath = location.append(STATE_LOCATION_ROOT).append("com.aptana.ide.syncing.core"); //$NON-NLS-1$
dir = sitePath.toFile();
if (dir.isDirectory())
{
// this is a 2.0 workspace
siteCount = loadSiteConnections(dir, applyToAllAction);
}
else
{
// checks if it is a 3.0 workspace
sitePath = location.append(STATE_LOCATION_ROOT).append(SyncingPlugin.PLUGIN_ID);
dir = sitePath.toFile();
if (dir.isDirectory())
{
siteCount = loadSiteConnections(dir, applyToAllAction);
}
}
}
else
{
// importing from file
List<IConnectionPoint> connections = validateConnectionsFrom(location, applyToAllAction);
if (connections == null)
{
return false;
}
connectionCount = connections.size();
List<ISiteConnection> sites = validateSitesFrom(location, applyToAllAction);
siteCount = sites.size();
}
final int cCount = connectionCount;
final int sCount = siteCount;
UIUtils.getDisplay().asyncExec(new Runnable()
{
public void run()
{
MessageDialog.openInformation(getShell(), Messages.ImportConnectionsWizard_Info_Title,
MessageFormat.format(Messages.ImportConnectionsWizard_Info_Message, cCount, sCount));
}
});
return true;
}
public void init(IWorkbench workbench, IStructuredSelection selection)
{
setWindowTitle(Messages.ImportConnectionsWizard_Title);
}
private int loadConnectionPoints(File dir, final int[] applyToAllAction)
{
File[] files = dir.listFiles(new FilenameFilter()
{
public boolean accept(File dir, String name)
{
return name.startsWith("connections"); //$NON-NLS-1$
}
});
File file = getLatestFile(files);
if (file != null)
{
List<IConnectionPoint> acceptedConnections = validateConnectionsFrom(
Path.fromOSString(file.getAbsolutePath()), applyToAllAction);
if (acceptedConnections == null)
{
return -1;
}
return acceptedConnections.size();
}
return 0;
}
/**
* Validate logic: If the types are the same, prompt for override/skip. If the types are different, rename the
* connection
*
* @param filePath
* @return
*/
private List<IConnectionPoint> validateConnectionsFrom(IPath filePath, final int[] applyToAllAction)
{
int action = 0;
List<IConnectionPoint> acceptedConnections = new ArrayList<IConnectionPoint>();
List<IConnectionPoint> removedConnections = new ArrayList<IConnectionPoint>();
List<IConnectionPoint> newConnections = CoreIOPlugin.getConnectionPointManager().readConnectionsFrom(filePath);
Map<String, IConnectionPoint> renames = new HashMap<String, IConnectionPoint>();
Map<String, IConnectionPoint> currentNames = new HashMap<String, IConnectionPoint>();
IConnectionPoint[] currentPoints = CoreIOPlugin.getConnectionPointManager().getConnectionPoints();
for (IConnectionPoint current : currentPoints)
{
currentNames.put(current.getName(), current);
}
for (IConnectionPoint newConnection : newConnections)
{
boolean shouldAdd = true;
if (currentNames.containsKey(newConnection.getName()))
{
IConnectionPoint current = currentNames.get(newConnection.getName());
if (((ConnectionPoint) current).getType().equals(((ConnectionPoint) newConnection).getType()))
{
action = applyToAllAction[0];
if (action == -1)
{
action = promptConflictDialog(newConnection.getName(), applyToAllAction);
}
switch (action)
{
case 0:
shouldAdd = true;
removedConnections.add(current);
((ConnectionPoint) newConnection).setId(current.getId());
break;
case 1:
shouldAdd = false;
break;
case 2:
renames.put(newConnection.getName(), newConnection);
break;
default:
return null;
}
}
else
{
renames.put(newConnection.getName(), newConnection);
}
}
if (shouldAdd)
{
acceptedConnections.add(newConnection);
currentNames.put(newConnection.getName(), newConnection);
}
}
for (IConnectionPoint removed : removedConnections)
{
CoreIOPlugin.getConnectionPointManager().removeConnectionPoint(removed);
}
for (IConnectionPoint added : acceptedConnections)
{
CoreIOPlugin.getConnectionPointManager().addConnectionPoint(added);
}
for (String key : renames.keySet())
{
String name = key;
int count = 1;
ConnectionPoint point = (ConnectionPoint) renames.get(key);
while (currentNames.containsKey(name))
{
name = MessageFormat.format(Messages.ImportConnectionsWizard_Conflict_Renamed, key, count++);
}
currentNames.put(name, point);
point.setName(name);
}
return acceptedConnections;
}
private int loadSiteConnections(File dir, final int[] applyAllAction)
{
File[] files = dir.listFiles(new FilenameFilter()
{
public boolean accept(File dir, String name)
{
return name.startsWith("sites"); //$NON-NLS-1$
}
});
File file = getLatestFile(files);
if (file != null)
{
List<ISiteConnection> newSites = validateSitesFrom(Path.fromOSString(file.getAbsolutePath()),
applyAllAction);
return newSites.size();
}
return 0;
}
private static File getLatestFile(File[] files)
{
// picks the one with the largest number
File latestFile = null;
long maxNumber = 0;
for (File file : files)
{
String filename = file.getName();
int index = filename.lastIndexOf('.');
if (index > -1)
{
try
{
long number = Long.parseLong(filename.substring(index + 1));
if (number > maxNumber)
{
latestFile = file;
maxNumber = number;
}
}
catch (NumberFormatException e)
{
// should not happen, but just in case
}
}
}
return latestFile;
}
private List<ISiteConnection> validateSitesFrom(IPath filePath, final int[] applyToAllAction)
{
int action = 0;
List<ISiteConnection> acceptedConnections = new ArrayList<ISiteConnection>();
List<ISiteConnection> removedConnections = new ArrayList<ISiteConnection>();
List<ISiteConnection> newConnections = SyncingPlugin.getSiteConnectionManager().readConnectionsFrom(filePath);
Map<String, ISiteConnection> renames = new HashMap<String, ISiteConnection>();
Map<String, ISiteConnection> currentNames = new HashMap<String, ISiteConnection>();
ISiteConnection[] currentPoints = SyncingPlugin.getSiteConnectionManager().getSiteConnections();
for (ISiteConnection current : currentPoints)
{
currentNames.put(current.getName(), current);
}
for (ISiteConnection newConnection : newConnections)
{
boolean shouldAdd = true;
if (currentNames.containsKey(newConnection.getName()))
{
ISiteConnection current = currentNames.get(newConnection.getName());
action = applyToAllAction[0];
if (action == -1)
{
action = promptConflictDialog(newConnection.getName(), applyToAllAction);
}
switch (action)
{
case 0:
shouldAdd = true;
removedConnections.add(current);
break;
case 1:
shouldAdd = false;
break;
case 2:
renames.put(newConnection.getName(), newConnection);
default:
break;
}
}
if (shouldAdd)
{
acceptedConnections.add(newConnection);
currentNames.put(newConnection.getName(), newConnection);
}
}
for (ISiteConnection removed : removedConnections)
{
SyncingPlugin.getSiteConnectionManager().removeSiteConnection(removed);
}
for (ISiteConnection added : acceptedConnections)
{
SyncingPlugin.getSiteConnectionManager().addSiteConnection(added);
}
for (String key : renames.keySet())
{
String name = key;
int count = 1;
ISiteConnection point = (ISiteConnection) renames.get(key);
while (currentNames.containsKey(name))
{
name = MessageFormat.format(Messages.ImportConnectionsWizard_Conflict_Renamed, key, count++);
}
currentNames.put(name, point);
point.setName(name);
}
List<ISiteConnection> sites = SyncingPlugin.getSiteConnectionManager().readConnectionsFrom(filePath);
return sites;
}
private int promptConflictDialog(String name, final int[] applyToAllAction)
{
MessageDialog dialog = new MessageDialog(getShell(), Messages.ImportConnectionsWizard_Conflict_Title, null,
MessageFormat.format(Messages.ImportConnectionsWizard_Conflict_Message, name), 0, new String[] {
com.aptana.ui.IDialogConstants.OVERWRITE_LABEL, IDialogConstants.SKIP_LABEL,
com.aptana.ui.IDialogConstants.RENAME_LABEL }, 0)
{
@Override
protected Control createCustomArea(Composite parent)
{
final Button applyToAll = new Button(parent, SWT.CHECK);
GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
applyToAll.setLayoutData(data);
applyToAll.setText(Messages.ImportConnectionsWizard_Conflict_LBL_Apply);
applyToAll.addSelectionListener(new SelectionListener()
{
public void widgetSelected(SelectionEvent e)
{
if (applyToAll.getSelection())
{
applyToAllAction[0] = 0;
}
}
public void widgetDefaultSelected(SelectionEvent e)
{
}
});
return applyToAll;
}
};
int action = dialog.open();
if (applyToAllAction[0] == -1)
{
applyToAllAction[0] = action;
}
return action;
}
}