1 /*******************************************************************************
2  * Copyright (c) 2000, 2014 IBM Corporation and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *     IBM Corporation - initial API and implementation
13  *******************************************************************************/
14 package org.eclipse.ui.wizards.datatransfer;
15 
16 import java.util.ArrayList;
17 import java.util.Iterator;
18 import java.util.List;
19 
20 import org.eclipse.core.runtime.IProgressMonitor;
21 import org.eclipse.jface.operation.IRunnableWithProgress;
22 import org.eclipse.jface.operation.ModalContext;
23 import org.eclipse.ui.dialogs.FileSystemElement;
24 import org.eclipse.ui.internal.wizards.datatransfer.DataTransferMessages;
25 
26 /**
27  *	Operation responsible for traversing a specified file system position
28  *	recursively and building
29  *	-	a tree that represents the container structure
30  *	-	a collection containing all files meeting a specified extension criteria
31  *
32  *	This is implemented as an Operation in order to provide an escape to the user
33  *	(the Cancel button) if the operation drags on for too long
34  */
35 public class SelectFilesOperation implements IRunnableWithProgress {
36 	IProgressMonitor monitor;
37 
38 	Object root;
39 
40 	IImportStructureProvider provider;
41 
42 	String desiredExtensions[];
43 
44 	FileSystemElement result;
45 
46 	/**
47 	 * Creates a new <code>SelectFilesOperation</code>.
48 	 */
SelectFilesOperation(Object rootObject, IImportStructureProvider structureProvider)49 	public SelectFilesOperation(Object rootObject,
50 			IImportStructureProvider structureProvider) {
51 		super();
52 		root = rootObject;
53 		provider = structureProvider;
54 	}
55 
56 	/**
57 	 * Creates and returns a <code>FileSystemElement</code> if the specified
58 	 * file system object merits one.  The criteria for this are:
59 	 * - if the file system object is a container then it must have either a
60 	 *   child container or an associated file
61 	 * - if the file system object is a file then it must have an extension
62 	 *   suitable for selection
63 	 */
createElement(FileSystemElement parent, Object fileSystemObject)64 	protected FileSystemElement createElement(FileSystemElement parent,
65 			Object fileSystemObject) throws InterruptedException {
66 		ModalContext.checkCanceled(monitor);
67 		boolean isContainer = provider.isFolder(fileSystemObject);
68 		String elementLabel = parent == null ? provider
69 				.getFullPath(fileSystemObject) : provider
70 				.getLabel(fileSystemObject);
71 
72 		if (!isContainer && !hasDesiredExtension(elementLabel)) {
73 			return null;
74 		}
75 
76 		FileSystemElement result = new FileSystemElement(elementLabel, parent,
77 				isContainer);
78 		result.setFileSystemObject(fileSystemObject);
79 
80 		if (isContainer) {
81 			boolean haveChildOrFile = false;
82 			List children = provider.getChildren(fileSystemObject);
83 			if (children == null) {
84 				children = new ArrayList(1);
85 			}
86 			Iterator childrenEnum = children.iterator();
87 			while (childrenEnum.hasNext()) {
88 				if (createElement(result, childrenEnum.next()) != null) {
89 					haveChildOrFile = true;
90 				}
91 			}
92 
93 			if (!haveChildOrFile && parent != null) {
94 				parent.removeFolder(result);
95 				result = null;
96 			}
97 		}
98 
99 		return result;
100 	}
101 
102 	/**
103 	 * Returns the extension portion of the passed filename string.
104 	 */
getExtensionFor(String filename)105 	protected String getExtensionFor(String filename) {
106 		int nIndex = filename.lastIndexOf('.');
107 
108 		if (nIndex >= 0) {
109 			return filename.substring(nIndex + 1);
110 		}
111 
112 		return "";//$NON-NLS-1$
113 
114 	}
115 
116 	/**
117 	 * Returns the resulting root file system element.
118 	 */
getResult()119 	public FileSystemElement getResult() {
120 		return result;
121 	}
122 
123 	/**
124 	 * Returns a boolean indicating whether the extension of the passed filename
125 	 * is one of the extensions specified as desired by the filter.
126 	 */
hasDesiredExtension(String filename)127 	protected boolean hasDesiredExtension(String filename) {
128 		if (desiredExtensions == null) {
129 			return true;
130 		}
131 
132 		int extensionsSize = desiredExtensions.length;
133 		for (int i = 0; i < extensionsSize; i++) {
134 			if (getExtensionFor(filename)
135 					.equalsIgnoreCase(desiredExtensions[i])) {
136 				return true;
137 			}
138 		}
139 
140 		return false;
141 	}
142 
143 	/**
144 	 * Runs the operation.
145 	 */
146 	@Override
run(IProgressMonitor monitor)147 	public void run(IProgressMonitor monitor) throws InterruptedException {
148 		try {
149 			this.monitor = monitor;
150 			monitor.beginTask(DataTransferMessages.DataTransfer_scanningMatching, IProgressMonitor.UNKNOWN);
151 			result = createElement(null, root);
152 			if (result == null) {
153 				result = new FileSystemElement(provider.getLabel(root), null,
154 						provider.isFolder(root));
155 				result.setFileSystemObject(root);
156 			}
157 		} finally {
158 			monitor.done();
159 		}
160 	}
161 
162 	/**
163 	 * Sets the file extensions which are desired.  A value of <code>null</code>
164 	 * indicates that all files should be kept regardless of extension.
165 	 */
setDesiredExtensions(String[] extensions)166 	public void setDesiredExtensions(String[] extensions) {
167 		desiredExtensions = extensions;
168 	}
169 }
170