/*******************************************************************************
* Copyright (c) 2012 Andrey.
* 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
* Contributor: Andrey Loskutov - initial API and implementation
*******************************************************************************/
package de.loskutov.anyedit.ui.wizards;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.List;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IPath;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.IElementFactory;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.IWorkingSet;
import org.eclipse.ui.IWorkingSetManager;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.XMLMemento;
import org.eclipse.ui.internal.IWorkbenchConstants;
import de.loskutov.anyedit.AnyEditToolsPlugin;
import de.loskutov.anyedit.IAnyEditConstants;
import de.loskutov.anyedit.util.EclipseUtils;
/**
* @author Andrey
*/
public class ImportPage extends WSPage {
private static final String TITLE = "Import working sets from the local file system";
private static final String DESCRIPTION = "Select the file path to import working " +
"sets from and working sets to import";
protected boolean isMerge;
protected ImportPage(String pageName) {
super(pageName, TITLE, DESCRIPTION, "icons/import_wiz.gif");
isMerge = true;
}
@Override
public void createControl(Composite parent) {
super.createControl(parent);
final Button chooserBtn = new Button(comp, SWT.CHECK);
chooserBtn.setSelection(isMerge);
chooserBtn.setText("Merge with existing working sets");
chooserBtn.addSelectionListener(new SelectionListener() {
@Override
public void widgetDefaultSelected(SelectionEvent e) {
// ignored
}
@Override
public void widgetSelected(SelectionEvent e) {
isMerge = chooserBtn.getSelection();
}
});
}
private String readSets() {
String pathname = getFileString();
if (pathname == null) {
return "Please select file";
}
File file = new File(pathname);
FileInputStream input = null;
BufferedReader reader;
IMemento memento;
try {
input = new FileInputStream(file);
reader = new BufferedReader(new InputStreamReader(input, "utf-8"));
memento = XMLMemento.createReadRoot(reader);
} catch (FileNotFoundException e) {
return "Couldn't read working set file: " + file + ": " + e.getMessage();
} catch (IOException e) {
return "Couldn't read working set file: " + file + ": " + e.getMessage();
} catch (CoreException e) {
return "Couldn't read working set file: " + file + ": " + e.getMessage();
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
AnyEditToolsPlugin.logError(null, e);
}
}
}
IMemento[] mementos = memento.getChildren("workingSet");
List<IWorkingSet> sets = new ArrayList<IWorkingSet>();
for (int i = 0; i < mementos.length; i++) {
IWorkingSet set = restoreWorkingSet(mementos[i]);
if (set != null) {
sets.add(set);
}
}
setInput(sets.toArray(new IWorkingSet[sets.size()]));
try {
String lastUsedFile = file.getCanonicalPath();
IPreferenceStore store = AnyEditToolsPlugin.getDefault().getPreferenceStore();
store.setValue(IAnyEditConstants.LAST_USED_WS_FILE, lastUsedFile);
} catch (IOException e) {
AnyEditToolsPlugin.logError(null, e);
}
return null;
}
// see org.eclipse.ui.internal.AbstractWorkingSet
protected IWorkingSet restoreWorkingSet(IMemento memento) {
String factoryID = memento.getString(IWorkbenchConstants.TAG_FACTORY_ID);
if (factoryID == null) {
// if the factory id was not set in the memento
// then assume that the memento was created using
// IMemento.saveState, and should be restored using WorkingSetFactory
factoryID = "org.eclipse.ui.internal.WorkingSetFactory";
}
IElementFactory factory = PlatformUI.getWorkbench().getElementFactory(factoryID);
if (factory == null) {
AnyEditToolsPlugin.logError(
"Unable to restore working set - cannot instantiate factory: "
+ factoryID, null);
return null;
}
IAdaptable adaptable = factory.createElement(memento);
if (adaptable == null) {
AnyEditToolsPlugin.logError(
"Unable to restore working set - cannot instantiate working set: "
+ factoryID, null);
return null;
}
if (!(adaptable instanceof IWorkingSet)) {
AnyEditToolsPlugin.logError(
"Unable to restore working set - element is not an IWorkingSet: "
+ factoryID, null);
return null;
}
return (IWorkingSet) adaptable;
}
public boolean finish() {
importSelectedSets();
return true;
}
private void importSelectedSets() {
Object[] selected = getSelectedWorkingSets();
if (selected == null) {
return;
}
IWorkingSetManager workingSetManager = PlatformUI.getWorkbench()
.getWorkingSetManager();
List<IWorkingSet> added = new ArrayList<IWorkingSet>();
for (int i = 0; i < selected.length; i++) {
IWorkingSet workingSet = (IWorkingSet) selected[i];
IWorkingSet oldWorkingSet = workingSetManager.getWorkingSet(workingSet.getName());
if (oldWorkingSet == null) {
removeNonExistingChildren(workingSet);
workingSetManager.addWorkingSet(workingSet);
added.add(workingSet);
} else if(isMerge) {
removeNonExistingChildren(workingSet);
mergeWorkingSets(oldWorkingSet, workingSet);
}
}
if (added.size() > 0) {
try {
/*
* Reflection required because some people do not have JDT installed, and
* thus current class would not be loaded at all with the direct reference
* to the action
*/
Class<?> actClass = Class.forName(
"de.loskutov.anyedit.jdt.SelectWorkingSetsAction", true,
getClass().getClassLoader());
IWSAction action = (IWSAction) actClass.newInstance();
action.setWorkingSets(added);
action.run();
} catch (NoClassDefFoundError e) {
AnyEditToolsPlugin.logError("JDT not installed", e);
} catch (ClassNotFoundException e) {
AnyEditToolsPlugin.logError("JDT not installed", e);
} catch (Throwable e) {
AnyEditToolsPlugin.logError("Failed to activate imported working sets"
+ " in Package Explorer view", e);
}
}
}
private static void removeNonExistingChildren(IWorkingSet workingSet) {
IAdaptable[] elements = workingSet.getElements();
List<IResource> existing = new ArrayList<>();
for (int i = 0; i < elements.length; i++) {
IResource resource = EclipseUtils.getResource(elements[i]);
if (resource != null && resource.exists()) {
existing.add(resource);
}
}
workingSet.setElements(existing.toArray(new IAdaptable[existing.size()]));
}
public static class WorkingSetContentProvider implements ITreeContentProvider {
private IWorkingSet[] workingSets;
@Override
public void dispose() {
// noop
}
@Override
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
if (newInput instanceof IWorkingSet[]) {
workingSets = (IWorkingSet[]) newInput;
}
}
@Override
public Object[] getElements(Object inputElement) {
if (workingSets == null) {
return new Object[0];
}
List<IWorkingSet> sets = new ArrayList<IWorkingSet>();
for (int i = 0; i < workingSets.length; i++) {
IWorkingSet workingSet = workingSets[i];
if (!workingSet.isAggregateWorkingSet()) {
sets.add(workingSet);
}
}
return sets.toArray(new IWorkingSet[sets.size()]);
}
@Override
public Object[] getChildren(Object parentElement) {
return new Object[0];
}
@Override
public Object getParent(Object element) {
return null;
}
@Override
public boolean hasChildren(Object element) {
return false;
}
}
@Override
protected IStructuredContentProvider createContentProvider() {
return new WorkingSetContentProvider();
}
@Override
protected void selectionChanged() {
String errorMessage = null;
if (getSelectedWorkingSets().length == 0) {
errorMessage = "Please select at least one working set";
}
setErrorMessage(errorMessage);
setPageComplete(errorMessage == null);
}
@Override
protected boolean validateInput() {
String errorMessage = null;
String text = getFileString();
if (text == null) {
errorMessage = "Please select file";
}
if (errorMessage != null) {
setInput(new IWorkingSet[0]);
setErrorMessage(errorMessage);
setPageComplete(false);
return false;
}
errorMessage = readSets();
if (errorMessage != null) {
errorMessage = "Working set import failed: " + errorMessage;
} else if (getSelectedWorkingSets().length == 0) {
errorMessage = "Please select at least one working set";
}
setErrorMessage(errorMessage);
setPageComplete(errorMessage == null);
if (errorMessage != null) {
setInput(new IWorkingSet[0]);
}
return errorMessage == null;
}
public void setInitialSelection(IStructuredSelection selection) {
if(selection == null) {
return;
}
IResource resource = EclipseUtils.getResource(selection);
if(resource == null) {
return;
}
IPath location = resource.getLocation();
if(location != null && "wst".equals(location.getFileExtension()) &&
location.toFile().isFile()) {
usedFiles.add(location.toOSString());
}
}
private void mergeWorkingSets(IWorkingSet oldWorkingSet, IWorkingSet newWorkingSet) {
if(!oldWorkingSet.isEditable()) {
return;
}
IAdaptable[] elementsOld = oldWorkingSet.getElements();
IAdaptable[] elementsNew = newWorkingSet.getElements();
if(elementsNew == null || elementsOld == null || elementsNew.length == 0) {
return;
}
LinkedHashSet<IAdaptable> set = new LinkedHashSet<IAdaptable>(Arrays.asList(elementsOld));
ArrayList<IAdaptable> newList = new ArrayList<IAdaptable>(Arrays.asList(elementsNew));
newList.removeAll(set);
if(newList.size() == 0) {
return;
}
elementsNew = oldWorkingSet.adaptElements(newList.toArray(new IAdaptable[newList.size()]));
newList = new ArrayList<IAdaptable>(Arrays.asList(elementsNew));
newList.removeAll(set);
if(newList.size() == 0) {
return;
}
set.addAll(newList);
oldWorkingSet.setElements(set.toArray(new IAdaptable[set.size()]));
}
}