--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009, 2013 Ericsson 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:
+ * Francois Chouinard - Initial API and implementation
+ * Francois Chouinard - Got rid of dependency on internal platform class
+ * Francois Chouinard - Complete re-design
+ * Anna Dushistova(Montavista) - [383047] NPE while importing a CFT trace
+ * Matthew Khouzam - Moved out some common functions
+ * Patrick Tasse - Add sorting of file system elements
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.tmf.ui.project.wizards.importtrace;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.viewers.CheckStateChangedEvent;
+import org.eclipse.jface.viewers.CheckboxTreeViewer;
+import org.eclipse.jface.viewers.ICheckStateListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.linuxtools.internal.tmf.ui.Activator;
+import org.eclipse.linuxtools.tmf.core.TmfProjectNature;
+import org.eclipse.linuxtools.tmf.core.project.model.TmfTraceType;
+import org.eclipse.linuxtools.tmf.core.project.model.TraceTypeHelper;
+import org.eclipse.linuxtools.tmf.ui.project.model.TmfProjectElement;
+import org.eclipse.linuxtools.tmf.ui.project.model.TmfProjectRegistry;
+import org.eclipse.linuxtools.tmf.ui.project.model.TmfTraceElement;
+import org.eclipse.linuxtools.tmf.ui.project.model.TmfTraceFolder;
+import org.eclipse.linuxtools.tmf.ui.project.model.TmfTraceTypeUIUtils;
+import org.eclipse.linuxtools.tmf.ui.project.wizards.Messages;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.BusyIndicator;
+import org.eclipse.swt.events.FocusEvent;
+import org.eclipse.swt.events.FocusListener;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.KeyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.DirectoryDialog;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.dialogs.FileSystemElement;
+import org.eclipse.ui.dialogs.WizardResourceImportPage;
+import org.eclipse.ui.model.WorkbenchContentProvider;
+import org.eclipse.ui.model.WorkbenchLabelProvider;
+import org.eclipse.ui.wizards.datatransfer.FileSystemStructureProvider;
+import org.eclipse.ui.wizards.datatransfer.IImportStructureProvider;
+import org.eclipse.ui.wizards.datatransfer.ImportOperation;
+
+/**
+ * A variant of the standard resource import wizard with the following changes:
+ * <ul>
+ * <li>A folder/file combined checkbox tree viewer to select traces
+ * <li>Cherry-picking of traces in the file structure without re-creating the
+ * file hierarchy
+ * <li>A trace types dropbox for optional characterization
+ * </ul>
+ * For our purpose, a trace can either be a single file or a whole directory
+ * sub-tree, whichever is reached first from the root directory.
+ * <p>
+ *
+ * @version 1.0
+ * @author Francois Chouinard
+ * @since 2.0
+ */
+public class ImportTraceWizardPage extends WizardResourceImportPage {
+
+ // ------------------------------------------------------------------------
+ // Classes
+ // ------------------------------------------------------------------------
+
+ private static class FileSystemElementComparator implements Comparator<Object> {
+
+ FileSystemStructureProvider provider = FileSystemStructureProvider.INSTANCE;
+
+ @Override
+ public int compare(Object o1, Object o2) {
+ String label1 = provider.getLabel(o1);
+ String label2 = provider.getLabel(o2);
+ return label1.compareTo(label2);
+ }
+
+ }
+
+ // ------------------------------------------------------------------------
+ // Constants
+ // ------------------------------------------------------------------------
+
+ private static final String IMPORT_WIZARD_PAGE = "ImportTraceWizardPage"; //$NON-NLS-1$
+ private static final FileSystemElementComparator FILE_SYSTEM_ELEMENT_COMPARATOR = new FileSystemElementComparator();
+
+ // ------------------------------------------------------------------------
+ // Attributes
+ // ------------------------------------------------------------------------
+
+ // Folder navigation start point (saved between invocations)
+ private static String fRootDirectory = null;
+
+ // Navigation folder content viewer and selector
+ private CheckboxTreeViewer fFolderViewer;
+
+ // Target import directory ('Traces' folder)
+ private IFolder fTargetFolder;
+ private static final String SEPARATOR = ":"; //$NON-NLS-1$
+
+ // ------------------------------------------------------------------------
+ // Constructors
+ // ------------------------------------------------------------------------
+
+ /**
+ * Constructor. Creates the trace wizard page.
+ *
+ * @param name
+ * The name of the page.
+ * @param selection
+ * The current selection
+ */
+ protected ImportTraceWizardPage(String name, IStructuredSelection selection) {
+ super(name, selection);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param workbench
+ * The workbench reference.
+ * @param selection
+ * The current selection
+ */
+ public ImportTraceWizardPage(IWorkbench workbench, IStructuredSelection selection) {
+ this(IMPORT_WIZARD_PAGE, selection);
+ setTitle(Messages.ImportTraceWizard_FileSystemTitle);
+ setDescription(Messages.ImportTraceWizard_ImportTrace);
+
+ // Locate the target trace folder
+ IFolder traceFolder = null;
+ Object element = selection.getFirstElement();
+
+ if (element instanceof TmfTraceFolder) {
+ TmfTraceFolder tmfTraceFolder = (TmfTraceFolder) element;
+ tmfTraceFolder.getProject().getResource();
+ traceFolder = tmfTraceFolder.getResource();
+ } else if (element instanceof IProject) {
+ IProject project = (IProject) element;
+ try {
+ if (project.hasNature(TmfProjectNature.ID)) {
+ traceFolder = (IFolder) project.findMember(TmfTraceFolder.TRACE_FOLDER_NAME);
+ }
+ } catch (CoreException e) {
+ }
+ }
+
+ // Set the target trace folder
+ if (traceFolder != null) {
+ fTargetFolder = traceFolder;
+ String path = traceFolder.getFullPath().toOSString();
+ setContainerFieldValue(path);
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // WizardResourceImportPage
+ // ------------------------------------------------------------------------
+
+ @Override
+ public void createControl(Composite parent) {
+ super.createControl(parent);
+ // Restore last directory if applicable
+ if (fRootDirectory != null) {
+ directoryNameField.setText(fRootDirectory);
+ updateFromSourceField();
+ }
+ }
+
+ @Override
+ protected void createSourceGroup(Composite parent) {
+ createDirectorySelectionGroup(parent);
+ createFileSelectionGroup(parent);
+ createTraceTypeGroup(parent);
+ validateSourceGroup();
+ }
+
+ @Override
+ protected void createFileSelectionGroup(Composite parent) {
+
+ // This Composite is only used for widget alignment purposes
+ Composite composite = new Composite(parent, SWT.NONE);
+ composite.setFont(parent.getFont());
+ GridLayout layout = new GridLayout();
+ composite.setLayout(layout);
+ composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ final int PREFERRED_LIST_HEIGHT = 150;
+
+ fFolderViewer = new CheckboxTreeViewer(composite, SWT.BORDER);
+ GridData data = new GridData(GridData.FILL_BOTH);
+ data.heightHint = PREFERRED_LIST_HEIGHT;
+ fFolderViewer.getTree().setLayoutData(data);
+ fFolderViewer.getTree().setFont(parent.getFont());
+
+ fFolderViewer.setContentProvider(getFileProvider());
+ fFolderViewer.setLabelProvider(new WorkbenchLabelProvider());
+ fFolderViewer.addCheckStateListener(new ICheckStateListener() {
+ @Override
+ public void checkStateChanged(CheckStateChangedEvent event) {
+ Object elem = event.getElement();
+ if (elem instanceof FileSystemElement) {
+ FileSystemElement element = (FileSystemElement) elem;
+ if (fFolderViewer.getGrayed(element)) {
+ fFolderViewer.setSubtreeChecked(element, false);
+ fFolderViewer.setGrayed(element, false);
+ } else if (event.getChecked()) {
+ fFolderViewer.setSubtreeChecked(event.getElement(), true);
+ } else {
+ fFolderViewer.setParentsGrayed(element, true);
+ if (!element.isDirectory()) {
+ fFolderViewer.setGrayed(element, false);
+ }
+ }
+ updateWidgetEnablements();
+ }
+ }
+ });
+ }
+
+ @Override
+ protected ITreeContentProvider getFolderProvider() {
+ return null;
+ }
+
+ @Override
+ protected ITreeContentProvider getFileProvider() {
+ return new WorkbenchContentProvider() {
+ @Override
+ public Object[] getChildren(Object o) {
+ if (o instanceof FileSystemElement) {
+ FileSystemElement element = (FileSystemElement) o;
+ populateChildren(element);
+ // For our purpose, we need folders + files
+ Object[] folders = element.getFolders().getChildren();
+ Object[] files = element.getFiles().getChildren();
+
+ List<Object> result = new LinkedList<>();
+ for (Object folder : folders) {
+ result.add(folder);
+ }
+ for (Object file : files) {
+ result.add(file);
+ }
+
+ return result.toArray();
+ }
+ return new Object[0];
+ }
+ };
+ }
+
+ private static void populateChildren(FileSystemElement parent) {
+ // Do not re-populate if the job was done already...
+ FileSystemStructureProvider provider = FileSystemStructureProvider.INSTANCE;
+ if (parent.getFolders().size() == 0 && parent.getFiles().size() == 0) {
+ Object fileSystemObject = parent.getFileSystemObject();
+ List<?> children = provider.getChildren(fileSystemObject);
+ if (children != null) {
+ Collections.sort(children, FILE_SYSTEM_ELEMENT_COMPARATOR);
+ Iterator<?> iterator = children.iterator();
+ while (iterator.hasNext()) {
+ Object child = iterator.next();
+ String label = provider.getLabel(child);
+ FileSystemElement element = new FileSystemElement(label, parent, provider.isFolder(child));
+ element.setFileSystemObject(child);
+ }
+ }
+ }
+ }
+
+ @Override
+ protected List<FileSystemElement> getSelectedResources() {
+ List<FileSystemElement> resources = new ArrayList<>();
+ Object[] checkedItems = fFolderViewer.getCheckedElements();
+ for (Object item : checkedItems) {
+ if (item instanceof FileSystemElement && !fFolderViewer.getGrayed(item)) {
+ resources.add((FileSystemElement) item);
+ }
+ }
+ return resources;
+ }
+
+ // ------------------------------------------------------------------------
+ // Directory Selection Group (forked WizardFileSystemResourceImportPage1)
+ // ------------------------------------------------------------------------
+
+ /**
+ * The directory name field
+ */
+ protected Combo directoryNameField;
+ /**
+ * The directory browse button.
+ */
+ protected Button directoryBrowseButton;
+
+ private boolean entryChanged = false;
+
+ /**
+ * creates the directory selection group.
+ *
+ * @param parent
+ * the parent composite
+ */
+ protected void createDirectorySelectionGroup(Composite parent) {
+
+ Composite directoryContainerGroup = new Composite(parent, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 3;
+ directoryContainerGroup.setLayout(layout);
+ directoryContainerGroup.setFont(parent.getFont());
+ directoryContainerGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+
+ // Label ("Trace directory:")
+ Label groupLabel = new Label(directoryContainerGroup, SWT.NONE);
+ groupLabel.setText(Messages.ImportTraceWizard_DirectoryLocation);
+ groupLabel.setFont(parent.getFont());
+
+ // Directory name entry field
+ directoryNameField = new Combo(directoryContainerGroup, SWT.BORDER);
+ GridData data = new GridData(SWT.FILL, SWT.FILL, true, false);
+ data.widthHint = SIZING_TEXT_FIELD_WIDTH;
+ directoryNameField.setLayoutData(data);
+ directoryNameField.setFont(parent.getFont());
+
+ directoryNameField.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ updateFromSourceField();
+ }
+ });
+
+ directoryNameField.addKeyListener(new KeyListener() {
+ @Override
+ public void keyPressed(KeyEvent e) {
+ // If there has been a key pressed then mark as dirty
+ entryChanged = true;
+ if (e.character == SWT.CR) { // Windows...
+ entryChanged = false;
+ updateFromSourceField();
+ }
+ }
+
+ @Override
+ public void keyReleased(KeyEvent e) {
+ }
+ });
+
+ directoryNameField.addFocusListener(new FocusListener() {
+ @Override
+ public void focusGained(FocusEvent e) {
+ // Do nothing when getting focus
+ }
+
+ @Override
+ public void focusLost(FocusEvent e) {
+ // Clear the flag to prevent constant update
+ if (entryChanged) {
+ entryChanged = false;
+ updateFromSourceField();
+ }
+ }
+ });
+
+ // Browse button
+ directoryBrowseButton = new Button(directoryContainerGroup, SWT.PUSH);
+ directoryBrowseButton.setText(Messages.ImportTraceWizard_BrowseButton);
+ directoryBrowseButton.addListener(SWT.Selection, this);
+ directoryBrowseButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
+ directoryBrowseButton.setFont(parent.getFont());
+ setButtonLayoutData(directoryBrowseButton);
+ }
+
+ // ------------------------------------------------------------------------
+ // Browse for the source directory
+ // ------------------------------------------------------------------------
+
+ @Override
+ public void handleEvent(Event event) {
+ if (event.widget == directoryBrowseButton) {
+ handleSourceDirectoryBrowseButtonPressed();
+ }
+ super.handleEvent(event);
+ }
+
+ /**
+ * Handle the button pressed event
+ */
+ protected void handleSourceDirectoryBrowseButtonPressed() {
+ String currentSource = directoryNameField.getText();
+ DirectoryDialog dialog = new DirectoryDialog(directoryNameField.getShell(), SWT.SAVE | SWT.SHEET);
+ dialog.setText(Messages.ImportTraceWizard_SelectTraceDirectoryTitle);
+ dialog.setMessage(Messages.ImportTraceWizard_SelectTraceDirectoryMessage);
+ dialog.setFilterPath(getSourceDirectoryName(currentSource));
+
+ String selectedDirectory = dialog.open();
+ if (selectedDirectory != null) {
+ // Just quit if the directory is not valid
+ if ((getSourceDirectory(selectedDirectory) == null) || selectedDirectory.equals(currentSource)) {
+ return;
+ }
+ // If it is valid then proceed to populate
+ setErrorMessage(null);
+ setSourceName(selectedDirectory);
+ }
+ }
+
+ private File getSourceDirectory() {
+ return getSourceDirectory(directoryNameField.getText());
+ }
+
+ private static File getSourceDirectory(String path) {
+ File sourceDirectory = new File(getSourceDirectoryName(path));
+ if (!sourceDirectory.exists() || !sourceDirectory.isDirectory()) {
+ return null;
+ }
+
+ return sourceDirectory;
+ }
+
+ private static String getSourceDirectoryName(String sourceName) {
+ IPath result = new Path(sourceName.trim());
+ if (result.getDevice() != null && result.segmentCount() == 0) {
+ result = result.addTrailingSeparator();
+ } else {
+ result = result.removeTrailingSeparator();
+ }
+ return result.toOSString();
+ }
+
+ private String getSourceDirectoryName() {
+ return getSourceDirectoryName(directoryNameField.getText());
+ }
+
+ private void updateFromSourceField() {
+ setSourceName(directoryNameField.getText());
+ updateWidgetEnablements();
+ }
+
+ private void setSourceName(String path) {
+ if (path.length() > 0) {
+ String[] currentItems = directoryNameField.getItems();
+ int selectionIndex = -1;
+ for (int i = 0; i < currentItems.length; i++) {
+ if (currentItems[i].equals(path)) {
+ selectionIndex = i;
+ }
+ }
+ if (selectionIndex < 0) {
+ int oldLength = currentItems.length;
+ String[] newItems = new String[oldLength + 1];
+ System.arraycopy(currentItems, 0, newItems, 0, oldLength);
+ newItems[oldLength] = path;
+ directoryNameField.setItems(newItems);
+ selectionIndex = oldLength;
+ }
+ directoryNameField.select(selectionIndex);
+ }
+ resetSelection();
+ }
+
+ // ------------------------------------------------------------------------
+ // File Selection Group (forked WizardFileSystemResourceImportPage1)
+ // ------------------------------------------------------------------------
+
+ private void resetSelection() {
+ FileSystemElement root = getFileSystemTree();
+ populateListViewer(root);
+ }
+
+ private void populateListViewer(final Object treeElement) {
+ fFolderViewer.setInput(treeElement);
+ }
+
+ private FileSystemElement getFileSystemTree() {
+ File sourceDirectory = getSourceDirectory();
+ if (sourceDirectory == null) {
+ return null;
+ }
+ return selectFiles(sourceDirectory, FileSystemStructureProvider.INSTANCE);
+ }
+
+ private FileSystemElement selectFiles(final Object rootFileSystemObject, final IImportStructureProvider structureProvider) {
+ final FileSystemElement[] results = new FileSystemElement[1];
+ BusyIndicator.showWhile(getShell().getDisplay(), new Runnable() {
+ @Override
+ public void run() {
+ // Create the root element from the supplied file system object
+ results[0] = createRootElement(rootFileSystemObject, structureProvider);
+ }
+ });
+ return results[0];
+ }
+
+ private static FileSystemElement createRootElement(Object fileSystemObject,
+ IImportStructureProvider provider) {
+
+ boolean isContainer = provider.isFolder(fileSystemObject);
+ String elementLabel = provider.getLabel(fileSystemObject);
+
+ FileSystemElement dummyParent = new FileSystemElement("", null, true); //$NON-NLS-1$
+ FileSystemElement element = new FileSystemElement(elementLabel, dummyParent, isContainer);
+ element.setFileSystemObject(fileSystemObject);
+
+ // Get the first level
+ populateChildren(element);
+
+ return dummyParent;
+ }
+
+ // ------------------------------------------------------------------------
+ // Trace Type Group
+ // ------------------------------------------------------------------------
+
+ private Combo fTraceTypes;
+
+ private final void createTraceTypeGroup(Composite parent) {
+ Composite composite = new Composite(parent, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 3;
+ layout.makeColumnsEqualWidth = false;
+ composite.setLayout(layout);
+ composite.setFont(parent.getFont());
+ GridData buttonData = new GridData(SWT.FILL, SWT.FILL, true, false);
+ composite.setLayoutData(buttonData);
+
+ // Trace type label ("Trace Type:")
+ Label typeLabel = new Label(composite, SWT.NONE);
+ typeLabel.setText(Messages.ImportTraceWizard_TraceType);
+ typeLabel.setFont(parent.getFont());
+
+ // Trace type combo
+ fTraceTypes = new Combo(composite, SWT.BORDER);
+ GridData data = new GridData(SWT.FILL, SWT.FILL, true, false, 2, 1);
+ fTraceTypes.setLayoutData(data);
+ fTraceTypes.setFont(parent.getFont());
+
+ String[] availableTraceTypes = TmfTraceType.getInstance().getAvailableTraceTypes();
+ fTraceTypes.setItems(availableTraceTypes);
+
+ fTraceTypes.addSelectionListener(new SelectionListener() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ updateWidgetEnablements();
+ }
+
+ @Override
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+ });
+ }
+
+ // ------------------------------------------------------------------------
+ // Options
+ // ------------------------------------------------------------------------
+
+ private Button overwriteExistingResourcesCheckbox;
+ private Button createLinksInWorkspaceButton;
+
+ @Override
+ protected void createOptionsGroupButtons(Group optionsGroup) {
+
+ // Overwrite checkbox
+ overwriteExistingResourcesCheckbox = new Button(optionsGroup, SWT.CHECK);
+ overwriteExistingResourcesCheckbox.setFont(optionsGroup.getFont());
+ overwriteExistingResourcesCheckbox.setText(Messages.ImportTraceWizard_OverwriteExistingTrace);
+ overwriteExistingResourcesCheckbox.setSelection(false);
+
+ // Create links checkbox
+ createLinksInWorkspaceButton = new Button(optionsGroup, SWT.CHECK);
+ createLinksInWorkspaceButton.setFont(optionsGroup.getFont());
+ createLinksInWorkspaceButton.setText(Messages.ImportTraceWizard_CreateLinksInWorkspace);
+ createLinksInWorkspaceButton.setSelection(true);
+
+ createLinksInWorkspaceButton.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ updateWidgetEnablements();
+ }
+ });
+
+ updateWidgetEnablements();
+ }
+
+ // ------------------------------------------------------------------------
+ // Determine if the finish button can be enabled
+ // ------------------------------------------------------------------------
+
+ @Override
+ public boolean validateSourceGroup() {
+
+ File sourceDirectory = getSourceDirectory();
+ if (sourceDirectory == null) {
+ setMessage(Messages.ImportTraceWizard_SelectTraceSourceEmpty);
+ return false;
+ }
+
+ if (sourceConflictsWithDestination(new Path(sourceDirectory.getPath()))) {
+ setMessage(null);
+ setErrorMessage(getSourceConflictMessage());
+ return false;
+ }
+
+ List<FileSystemElement> resourcesToImport = getSelectedResources();
+ if (resourcesToImport.size() == 0) {
+ setMessage(null);
+ setErrorMessage(Messages.ImportTraceWizard_SelectTraceNoneSelected);
+ return false;
+ }
+
+ IContainer container = getSpecifiedContainer();
+ if (container != null && container.isVirtual()) {
+ if (Platform.getPreferencesService().getBoolean(Activator.PLUGIN_ID, ResourcesPlugin.PREF_DISABLE_LINKING, false, null)) {
+ setMessage(null);
+ setErrorMessage(Messages.ImportTraceWizard_CannotImportFilesUnderAVirtualFolder);
+ return false;
+ }
+ if (createLinksInWorkspaceButton == null || !createLinksInWorkspaceButton.getSelection()) {
+ setMessage(null);
+ setErrorMessage(Messages.ImportTraceWizard_HaveToCreateLinksUnderAVirtualFolder);
+ return false;
+ }
+ }
+
+ // Perform trace validation
+ String traceTypeName = fTraceTypes.getText();
+ String tokens[] = traceTypeName.split(SEPARATOR, 2);
+ if (tokens.length >= 2) {
+ String id = TmfTraceType.getInstance().getTraceTypeId(tokens[0], tokens[1]);
+ if (!TmfTraceTypeUIUtils.validateTrace(TmfTraceType.getInstance(), id, getSelectedResources())) {
+ setMessage(null);
+ setErrorMessage(Messages.ImportTraceWizard_TraceValidationFailed);
+ return false;
+ }
+ }
+ setErrorMessage(null);
+ return true;
+ }
+
+ // ------------------------------------------------------------------------
+ // Import the trace(s)
+ // ------------------------------------------------------------------------
+
+ /**
+ * Finish the import.
+ *
+ * @return <code>true</code> if successful else false
+ */
+ public boolean finish() {
+ // Ensure source is valid
+ File sourceDir = new File(getSourceDirectoryName());
+ if (!sourceDir.isDirectory()) {
+ setErrorMessage(Messages.ImportTraceWizard_InvalidTraceDirectory);
+ return false;
+ }
+
+ try {
+ sourceDir.getCanonicalPath();
+ } catch (IOException e) {
+ MessageDialog.openInformation(getContainer().getShell(), Messages.ImportTraceWizard_Information,
+ Messages.ImportTraceWizard_InvalidTraceDirectory);
+ return false;
+ }
+
+ // Save directory for next import operation
+ fRootDirectory = getSourceDirectoryName();
+
+ List<FileSystemElement> selectedResources = getSelectedResources();
+ Iterator<FileSystemElement> resources = selectedResources.iterator();
+
+ // Use a map to end up with unique resources (getSelectedResources() can
+ // return duplicates)
+ Map<String, File> fileSystemObjects = new HashMap<>();
+ while (resources.hasNext()) {
+ File file = (File) resources.next().getFileSystemObject();
+ String key = file.getAbsolutePath();
+ fileSystemObjects.put(key, file);
+ }
+
+ if (fileSystemObjects.size() > 0) {
+ boolean ok = importResources(fileSystemObjects);
+ String traceTypeName = fTraceTypes.getText();
+ boolean traceTypeOK = false;
+ TraceTypeHelper traceTypeHelper = null;
+
+ if (!traceTypeName.isEmpty()) {
+ // Trace type was selected
+ String temp[] = traceTypeName.split(SEPARATOR, 2);
+ if (temp.length < 2) {
+ Activator.getDefault().logError("Error with trace type " + traceTypeName); //$NON-NLS-1$
+ return false;
+ }
+ final String traceId = TmfTraceType.getInstance().getTraceTypeId(temp[0], temp[1]);
+ if (traceId != null) {
+ traceTypeHelper = TmfTraceType.getInstance().getTraceType(traceId);
+ if (traceTypeHelper == null || !TmfTraceTypeUIUtils.validateTrace(TmfTraceType.getInstance(), traceId, getSelectedResources())) {
+ setMessage(null);
+ setErrorMessage(Messages.ImportTraceWizard_TraceValidationFailed);
+ return false;
+ }
+
+ traceTypeOK = true;
+ } else {
+ setMessage(null);
+ setErrorMessage(Messages.ImportTraceWizard_TraceValidationFailed);
+ return false;
+ }
+ }
+
+ if (ok && traceTypeOK) {
+ // Tag the selected traces with their type
+ List<String> files = new ArrayList<>(fileSystemObjects.keySet());
+ Collections.sort(files, new Comparator<String>() {
+ @Override
+ public int compare(String o1, String o2) {
+ String v1 = o1 + File.separatorChar;
+ String v2 = o2 + File.separatorChar;
+ return v1.compareTo(v2);
+ }
+ });
+ // After sorting, traces correspond to the unique prefixes
+ String prefix = null;
+ for (int i = 0; i < files.size(); i++) {
+ File file = fileSystemObjects.get(files.get(i));
+ String name = file.getAbsolutePath() + File.separatorChar;
+ if (fTargetFolder != null && (prefix == null || !name.startsWith(prefix))) {
+ prefix = name; // new prefix
+ IResource resource = fTargetFolder.findMember(file.getName());
+ if (resource != null) {
+ try {
+ TmfTraceTypeUIUtils.setTraceType(resource.getFullPath(), traceTypeHelper);
+
+ TmfProjectElement tmfProject = TmfProjectRegistry.getProject(resource.getProject());
+ if (tmfProject != null) {
+ for (TmfTraceElement traceElement : tmfProject.getTracesFolder().getTraces()) {
+ if (traceElement.getName().equals(resource.getName())) {
+ traceElement.refreshTraceType();
+ break;
+ }
+ }
+ }
+ } catch (CoreException e) {
+ Activator.getDefault().logError("Error importing trace resource " + resource.getName(), e); //$NON-NLS-1$
+ }
+ }
+ }
+ }
+ }
+ return ok;
+ }
+
+ MessageDialog.openInformation(getContainer().getShell(), Messages.ImportTraceWizard_Information,
+ Messages.ImportTraceWizard_SelectTraceNoneSelected);
+ return false;
+ }
+
+ private boolean importResources(Map<String, File> fileSystemObjects) {
+
+ // Determine the sorted canonical list of items to import
+ List<File> fileList = new ArrayList<>();
+ for (Entry<String, File> entry : fileSystemObjects.entrySet()) {
+ fileList.add(entry.getValue());
+ }
+ Collections.sort(fileList, new Comparator<File>() {
+ @Override
+ public int compare(File o1, File o2) {
+ String v1 = o1.getAbsolutePath() + File.separatorChar;
+ String v2 = o2.getAbsolutePath() + File.separatorChar;
+ return v1.compareTo(v2);
+ }
+ });
+
+ // Perform a distinct import operation for everything that has the same
+ // prefix
+ // (distinct prefixes correspond to traces - we don't want to re-create
+ // parent structures)
+ boolean ok = true;
+ boolean isLinked = createLinksInWorkspaceButton.getSelection();
+ for (int i = 0; i < fileList.size(); i++) {
+ File resource = fileList.get(i);
+ File parentFolder = new File(resource.getParent());
+
+ List<File> subList = new ArrayList<>();
+ subList.add(resource);
+ if (resource.isDirectory()) {
+ String prefix = resource.getAbsolutePath() + File.separatorChar;
+ boolean hasSamePrefix = true;
+ for (int j = i + 1; j < fileList.size() && hasSamePrefix; j++) {
+ File res = fileList.get(j);
+ hasSamePrefix = res.getAbsolutePath().startsWith(prefix);
+ if (hasSamePrefix) {
+ // Import children individually if not linked
+ if (!isLinked) {
+ subList.add(res);
+ }
+ i = j;
+ }
+ }
+ }
+
+ // Perform the import operation for this subset
+ FileSystemStructureProvider fileSystemStructureProvider = FileSystemStructureProvider.INSTANCE;
+ ImportOperation operation = new ImportOperation(getContainerFullPath(), parentFolder, fileSystemStructureProvider, this,
+ subList);
+ operation.setContext(getShell());
+ ok = executeImportOperation(operation);
+ }
+
+ return ok;
+ }
+
+ private boolean executeImportOperation(ImportOperation op) {
+ initializeOperation(op);
+
+ try {
+ getContainer().run(true, true, op);
+ } catch (InterruptedException e) {
+ return false;
+ } catch (InvocationTargetException e) {
+ displayErrorDialog(e.getTargetException());
+ return false;
+ }
+
+ IStatus status = op.getStatus();
+ if (!status.isOK()) {
+ ErrorDialog.openError(getContainer().getShell(), Messages.ImportTraceWizard_ImportProblem, null, status);
+ return false;
+ }
+
+ return true;
+ }
+
+ private void initializeOperation(ImportOperation op) {
+ op.setCreateContainerStructure(false);
+ op.setOverwriteResources(overwriteExistingResourcesCheckbox.getSelection());
+ op.setCreateLinks(createLinksInWorkspaceButton.getSelection());
+ op.setVirtualFolders(false);
+ }
+
+}