1 /*******************************************************************************
2  * Copyright (c) 2010, 2017 BestSolution.at 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  * Tom Schindl <tom.schindl@bestsolution.at> - initial API and implementation
13  * Sopot Cela <sopotcela@gmail.com>
14  * Patrik Suzzi <psuzzi@gmail.com> - Bug 421066, 466491
15  ******************************************************************************/
16 package org.eclipse.e4.internal.tools.wizards.classes;
17 
18 import java.beans.PropertyChangeListener;
19 import java.beans.PropertyChangeSupport;
20 
21 import org.eclipse.core.databinding.Binding;
22 import org.eclipse.core.databinding.DataBindingContext;
23 import org.eclipse.core.databinding.UpdateValueStrategy;
24 import org.eclipse.core.databinding.beans.typed.BeanProperties;
25 import org.eclipse.core.databinding.conversion.Converter;
26 import org.eclipse.core.databinding.observable.value.IObservableValue;
27 import org.eclipse.core.databinding.validation.IValidator;
28 import org.eclipse.core.databinding.validation.MultiValidator;
29 import org.eclipse.core.databinding.validation.ValidationStatus;
30 import org.eclipse.core.resources.IFile;
31 import org.eclipse.core.resources.IFolder;
32 import org.eclipse.core.resources.IResource;
33 import org.eclipse.core.resources.IWorkspaceRoot;
34 import org.eclipse.core.runtime.IPath;
35 import org.eclipse.core.runtime.IStatus;
36 import org.eclipse.core.runtime.Status;
37 import org.eclipse.e4.internal.tools.Messages;
38 import org.eclipse.e4.internal.tools.ToolsPlugin;
39 import org.eclipse.jdt.core.ICompilationUnit;
40 import org.eclipse.jdt.core.IJavaElement;
41 import org.eclipse.jdt.core.IJavaModel;
42 import org.eclipse.jdt.core.IJavaProject;
43 import org.eclipse.jdt.core.IPackageFragment;
44 import org.eclipse.jdt.core.IPackageFragmentRoot;
45 import org.eclipse.jdt.core.JavaConventions;
46 import org.eclipse.jdt.core.JavaCore;
47 import org.eclipse.jdt.core.JavaModelException;
48 import org.eclipse.jdt.internal.ui.JavaPlugin;
49 import org.eclipse.jdt.internal.ui.wizards.NewWizardMessages;
50 import org.eclipse.jdt.internal.ui.wizards.TypedElementSelectionValidator;
51 import org.eclipse.jdt.internal.ui.wizards.TypedViewerFilter;
52 import org.eclipse.jdt.ui.JavaElementComparator;
53 import org.eclipse.jdt.ui.JavaElementLabelProvider;
54 import org.eclipse.jdt.ui.StandardJavaElementContentProvider;
55 import org.eclipse.jface.databinding.swt.ISWTObservableValue;
56 import org.eclipse.jface.databinding.swt.IWidgetValueProperty;
57 import org.eclipse.jface.databinding.swt.typed.WidgetProperties;
58 import org.eclipse.jface.databinding.wizard.WizardPageSupport;
59 import org.eclipse.jface.dialogs.IDialogSettings;
60 import org.eclipse.jface.resource.ImageDescriptor;
61 import org.eclipse.jface.viewers.ILabelProvider;
62 import org.eclipse.jface.viewers.IStructuredSelection;
63 import org.eclipse.jface.viewers.Viewer;
64 import org.eclipse.jface.viewers.ViewerFilter;
65 import org.eclipse.jface.window.Window;
66 import org.eclipse.jface.wizard.WizardPage;
67 import org.eclipse.swt.SWT;
68 import org.eclipse.swt.events.SelectionAdapter;
69 import org.eclipse.swt.events.SelectionEvent;
70 import org.eclipse.swt.graphics.Image;
71 import org.eclipse.swt.layout.GridData;
72 import org.eclipse.swt.layout.GridLayout;
73 import org.eclipse.swt.widgets.Button;
74 import org.eclipse.swt.widgets.Composite;
75 import org.eclipse.swt.widgets.Label;
76 import org.eclipse.swt.widgets.Text;
77 import org.eclipse.ui.dialogs.ElementListSelectionDialog;
78 import org.eclipse.ui.dialogs.ElementTreeSelectionDialog;
79 
80 @SuppressWarnings("restriction")
81 public abstract class AbstractNewClassPage extends WizardPage {
82 	private static final String BUNDLECLASS = "bundleclass://"; //$NON-NLS-1$
83 	private static final String FRAGMENT_ROOT = "fragmentRoot"; //$NON-NLS-1$
84 	public static final String PACKAGE_FRAGMENT = "packageFragment"; //$NON-NLS-1$
85 	public static final String PROPERTY_NAME = "name"; //$NON-NLS-1$
86 
87 	/** Name of the setting section for the new class wizard */
88 	private static final String SETTING_SECTION_NEW_CLASS = "org.eclipse.e4.tools.wizards.newclass"; //$NON-NLS-1$
89 	/** The package dialog setting */
90 	private static final String SETTING_PACKAGE = "package"; //$NON-NLS-1$
91 
92 	public static class JavaClass {
93 
94 		protected PropertyChangeSupport support = new PropertyChangeSupport(this);
95 
96 		private IPackageFragmentRoot fragmentRoot;
97 		private IPackageFragment packageFragment;
98 		private String name;
99 
JavaClass(IPackageFragmentRoot fragmentRoot)100 		public JavaClass(IPackageFragmentRoot fragmentRoot) {
101 			this.fragmentRoot = fragmentRoot;
102 		}
103 
getFragmentRoot()104 		public IPackageFragmentRoot getFragmentRoot() {
105 			return fragmentRoot;
106 		}
107 
setFragmentRoot(IPackageFragmentRoot fragmentRoot)108 		public void setFragmentRoot(IPackageFragmentRoot fragmentRoot) {
109 			support.firePropertyChange(FRAGMENT_ROOT, this.fragmentRoot, this.fragmentRoot = fragmentRoot);
110 		}
111 
getPackageFragment()112 		public IPackageFragment getPackageFragment() {
113 			return packageFragment;
114 		}
115 
setPackageFragment(IPackageFragment packageFragment)116 		public void setPackageFragment(IPackageFragment packageFragment) {
117 			support.firePropertyChange(PACKAGE_FRAGMENT, this.packageFragment, this.packageFragment = packageFragment);
118 		}
119 
getName()120 		public String getName() {
121 			return name;
122 		}
123 
setName(String name)124 		public void setName(String name) {
125 			support.firePropertyChange(PROPERTY_NAME, this.name, this.name = name);
126 		}
127 
addPropertyChangeListener(PropertyChangeListener listener)128 		public void addPropertyChangeListener(PropertyChangeListener listener) {
129 			support.addPropertyChangeListener(listener);
130 		}
131 
removePropertyChangeListener(PropertyChangeListener listener)132 		public void removePropertyChangeListener(PropertyChangeListener listener) {
133 			support.removePropertyChangeListener(listener);
134 		}
135 
exists(IPackageFragmentRoot pFragmentRoot, IPackageFragment pPackageFragment, String pName)136 		public static boolean exists(IPackageFragmentRoot pFragmentRoot, IPackageFragment pPackageFragment, String pName) {
137 
138 			if (pFragmentRoot == null) {
139 				return false;
140 			}
141 
142 			final String cuName = pName + ".java"; //$NON-NLS-1$
143 			IFile file;
144 
145 			if (pPackageFragment != null) {
146 				final ICompilationUnit unit = pPackageFragment.getCompilationUnit(cuName);
147 				final IResource resource = unit.getResource();
148 				file = (IFile) resource;
149 			} else {
150 				final IFolder p = (IFolder) pFragmentRoot.getResource();
151 				file = p.getFile(cuName);
152 			}
153 			return file.exists();
154 		}
155 	}
156 
157 	private JavaClass clazz;
158 	private IPackageFragmentRoot froot;
159 	private final IWorkspaceRoot fWorkspaceRoot;
160 	private String initialString;
161 	private String initialPackage;
162 
AbstractNewClassPage(String pageName, String title, String description, IPackageFragmentRoot froot, IWorkspaceRoot fWorkspaceRoot)163 	protected AbstractNewClassPage(String pageName, String title, String description, IPackageFragmentRoot froot,
164 			IWorkspaceRoot fWorkspaceRoot) {
165 		super(pageName);
166 		this.froot = froot;
167 		this.fWorkspaceRoot = fWorkspaceRoot;
168 
169 		setTitle(title);
170 		setDescription(description);
171 	}
172 
AbstractNewClassPage(String pageName, String title, String description, IPackageFragmentRoot froot, IWorkspaceRoot fWorkspaceRoot, String initialString)173 	protected AbstractNewClassPage(String pageName, String title, String description, IPackageFragmentRoot froot,
174 			IWorkspaceRoot fWorkspaceRoot, String initialString) {
175 		this(pageName, title, description, froot, fWorkspaceRoot);
176 		this.initialString = initialString;
177 	}
178 
179 	/**
180 	 * The wizard owning this page is responsible for calling this method with
181 	 * the current selection. The selection is used to initialize the fields of
182 	 * the wizard page.
183 	 *
184 	 * @param selection
185 	 *            used to initialize the fields
186 	 */
init(IStructuredSelection selection)187 	public void init(IStructuredSelection selection) {
188 		if (selection != null && !selection.isEmpty() && selection.getFirstElement() != null
189 				&& selection.getFirstElement() instanceof IPackageFragment) {
190 			final IPackageFragment pkg = (IPackageFragment) selection.getFirstElement();
191 			initialPackage = pkg.getElementName();
192 		} else {
193 			String settingPackage = getDialogSettings().get(SETTING_PACKAGE);
194 			if (settingPackage != null) {
195 				initialPackage = settingPackage;
196 			}
197 		}
198 	}
199 
200 	/**
201 	 * Gets called if the wizard is finished
202 	 */
performFinish()203 	public void performFinish() {
204 		String packageName = clazz.getPackageFragment().getElementName();
205 		getDialogSettings().put(SETTING_PACKAGE, packageName);
206 	}
207 
208 	@Override
getDialogSettings()209 	protected IDialogSettings getDialogSettings() {
210 		final IDialogSettings mainSettings = ToolsPlugin.getDefault().getDialogSettings();
211 		IDialogSettings settingsSection = mainSettings.getSection(SETTING_SECTION_NEW_CLASS);
212 		if (settingsSection == null) {
213 			settingsSection = mainSettings.addNewSection(SETTING_SECTION_NEW_CLASS);
214 		}
215 		return settingsSection;
216 	}
217 
218 	@Override
createControl(Composite parent)219 	public void createControl(Composite parent) {
220 		final Image img = new Image(parent.getDisplay(), getClass().getClassLoader().getResourceAsStream(
221 				"/icons/full/wizban/newclass_wiz.png")); //$NON-NLS-1$
222 		setImageDescriptor(ImageDescriptor.createFromImage(img));
223 
224 		parent.addDisposeListener(e -> {
225 			img.dispose();
226 			setImageDescriptor(null);
227 		});
228 
229 		parent = new Composite(parent, SWT.NULL);
230 		parent.setLayoutData(new GridData(GridData.FILL_BOTH));
231 		parent.setLayout(new GridLayout(3, false));
232 
233 		clazz = createInstance();
234 		if (froot != null && initialString != null) {
235 			clazz.setPackageFragment(froot.getPackageFragment(parseInitialStringForPackage(initialString) == null ? "" //$NON-NLS-1$
236 					: parseInitialStringForPackage(initialString)));
237 			clazz.setName(parseInitialStringForClassName(initialString));
238 		} else if (froot != null && initialPackage != null) {
239 			clazz.setPackageFragment(froot.getPackageFragment(initialPackage));
240 		}
241 		final DataBindingContext dbc = new DataBindingContext();
242 		WizardPageSupport.create(this, dbc);
243 
244 		{
245 			final Label l = new Label(parent, SWT.NONE);
246 			l.setText(Messages.AbstractNewClassPage_SourceFolder);
247 
248 			final Text t = new Text(parent, SWT.BORDER);
249 			t.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
250 			t.setEditable(false);
251 
252 			final Binding bd = dbc.bindValue(
253 					WidgetProperties.text().observe(t),
254 					BeanProperties.value(FRAGMENT_ROOT, IPackageFragmentRoot.class).observe(clazz),
255 					new UpdateValueStrategy<String, IPackageFragmentRoot>()
256 					.setBeforeSetValidator(new PFRootValidator()),
257 					UpdateValueStrategy.create(new PackageFragmentRootToStringConverter()));
258 
259 			final Button b = new Button(parent, SWT.PUSH);
260 			b.setText(Messages.AbstractNewClassPage_Browse);
261 			b.addSelectionListener(new SelectionAdapter() {
262 				@Override
263 				public void widgetSelected(SelectionEvent e) {
264 					final IPackageFragmentRoot root = choosePackageRoot();
265 					if (root != null) {
266 						froot = root;
267 						clazz.setFragmentRoot(root);
268 					}
269 					bd.updateModelToTarget();
270 				}
271 			});
272 		}
273 
274 		final Text tClassPackage;
275 		{
276 			final Label l = new Label(parent, SWT.NONE);
277 			l.setText(Messages.AbstractNewClassPage_Package);
278 			tClassPackage = new Text(parent, SWT.BORDER);
279 			tClassPackage.setEditable(true);
280 			tClassPackage.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
281 			final Binding bd = dbc.bindValue(
282 					WidgetProperties.text(SWT.Modify).observe(tClassPackage),
283 					BeanProperties.value(PACKAGE_FRAGMENT, IPackageFragment.class).observe(clazz),
284 					UpdateValueStrategy.create(new StringToPackageFragmentConverter(clazz)),
285 					UpdateValueStrategy.create(new PackageFragmentToStringConverter()));
286 
287 			final Button b = new Button(parent, SWT.PUSH);
288 			b.setText(Messages.AbstractNewClassPage_Browse);
289 			b.addSelectionListener(new SelectionAdapter() {
290 				@Override
291 				public void widgetSelected(SelectionEvent e) {
292 					final IPackageFragment fragment = choosePackage();
293 					if (fragment != null) {
294 						clazz.setPackageFragment(fragment);
295 					}
296 					bd.updateModelToTarget(); // TODO Find out why this is needed
297 				}
298 			});
299 		}
300 
301 		final Text tClassName;
302 		{
303 			final IWidgetValueProperty<Text, String> textProp = WidgetProperties.text(SWT.Modify);
304 
305 			final Label l = new Label(parent, SWT.NONE);
306 			l.setText(Messages.AbstractNewClassPage_Name);
307 
308 			tClassName = new Text(parent, SWT.BORDER);
309 			tClassName.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
310 			dbc.bindValue(textProp.observe(tClassName),
311 					BeanProperties.value(PROPERTY_NAME, String.class).observe(clazz),
312 					new UpdateValueStrategy<String, String>().setBeforeSetValidator(new ClassnameValidator()), null);
313 
314 			new Label(parent, SWT.NONE);
315 		}
316 
317 		{
318 			final Label l = new Label(parent, SWT.SEPARATOR | SWT.HORIZONTAL);
319 			l.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, false, false, 3, 1));
320 		}
321 
322 		final ISWTObservableValue<String> obsPackage = WidgetProperties.text(SWT.Modify).observe(tClassPackage);
323 		final ISWTObservableValue<String> obsClass = WidgetProperties.text(SWT.Modify).observe(tClassName);
324 		final ClassMultiValidator multiValidator = new ClassMultiValidator(clazz, obsPackage, obsClass);
325 		dbc.addValidationStatusProvider(multiValidator);
326 
327 		createFields(parent, dbc);
328 		setControl(parent);
329 	}
330 
parseInitialStringForPackage(String initialString2)331 	private String parseInitialStringForPackage(String initialString2) {
332 		if (initialString2 == null) {
333 			return null;
334 		}
335 		final int ioBC = initialString2.indexOf(BUNDLECLASS);
336 		final int iSecondSlash = initialString2.lastIndexOf('/');
337 		if (
338 
339 				initialString2.length() == 0 || // empty
340 				ioBC == -1 || // no bundle class
341 				iSecondSlash == -1 || // no package &| class name
342 				initialString2.indexOf('.') == -1// no package
343 				) {
344 			return null;
345 		}
346 
347 		final int lastDot = initialString2.lastIndexOf('.');
348 		final String packageString = initialString2.substring(iSecondSlash + 1, lastDot);
349 		return packageString;
350 	}
351 
parseInitialStringForClassName(String initialString)352 	private String parseInitialStringForClassName(String initialString) {
353 		if (initialString == null) {
354 			return null;
355 		}
356 		final int ioBC = initialString.indexOf(BUNDLECLASS);
357 		final int iSecondSlash = initialString.lastIndexOf('/');
358 		if (
359 
360 				initialString.length() == 0 || // empty
361 				ioBC == -1 || // no bundle class
362 				iSecondSlash == -1 || // no package &| class name
363 				initialString.indexOf('.') == -1// no package
364 				) {
365 			return null;
366 		}
367 		final int lastDot = initialString.lastIndexOf('.');
368 		if (lastDot != -1) {
369 			return initialString.substring(lastDot + 1);
370 		}
371 		return null;
372 	}
373 
choosePackageRoot()374 	private IPackageFragmentRoot choosePackageRoot() {
375 		final IJavaElement initElement = clazz.getFragmentRoot();
376 		Class<?>[] acceptedClasses = new Class[] { IPackageFragmentRoot.class, IJavaProject.class };
377 		final TypedElementSelectionValidator validator = new TypedElementSelectionValidator(acceptedClasses, false) {
378 			@Override
379 			public boolean isSelectedValid(Object element) {
380 				try {
381 					if (element instanceof IJavaProject) {
382 						final IJavaProject jproject = (IJavaProject) element;
383 						final IPath path = jproject.getProject().getFullPath();
384 						return jproject.findPackageFragmentRoot(path) != null;
385 					} else if (element instanceof IPackageFragmentRoot) {
386 						return ((IPackageFragmentRoot) element).getKind() == IPackageFragmentRoot.K_SOURCE;
387 					}
388 					return true;
389 				} catch (final JavaModelException e) {
390 					JavaPlugin.log(e.getStatus()); // just log, no UI in validation
391 				}
392 				return false;
393 			}
394 		};
395 
396 		acceptedClasses = new Class[] { IJavaModel.class, IPackageFragmentRoot.class, IJavaProject.class };
397 		final ViewerFilter filter = new TypedViewerFilter(acceptedClasses) {
398 			@Override
399 			public boolean select(Viewer viewer, Object parent, Object element) {
400 				if (element instanceof IPackageFragmentRoot) {
401 					try {
402 						return ((IPackageFragmentRoot) element).getKind() == IPackageFragmentRoot.K_SOURCE;
403 					} catch (final JavaModelException e) {
404 						JavaPlugin.log(e.getStatus()); // just log, no UI in validation
405 						return false;
406 					}
407 				}
408 				return super.select(viewer, parent, element);
409 			}
410 		};
411 
412 		final StandardJavaElementContentProvider provider = new StandardJavaElementContentProvider();
413 		final ILabelProvider labelProvider = new JavaElementLabelProvider(JavaElementLabelProvider.SHOW_DEFAULT);
414 		final ElementTreeSelectionDialog dialog = new ElementTreeSelectionDialog(getShell(), labelProvider, provider);
415 		dialog.setValidator(validator);
416 		dialog.setComparator(new JavaElementComparator());
417 		dialog.setTitle(NewWizardMessages.NewContainerWizardPage_ChooseSourceContainerDialog_title);
418 		dialog.setMessage(NewWizardMessages.NewContainerWizardPage_ChooseSourceContainerDialog_description);
419 		dialog.addFilter(filter);
420 		dialog.setInput(JavaCore.create(fWorkspaceRoot));
421 		dialog.setInitialSelection(initElement);
422 		dialog.setHelpAvailable(false);
423 
424 		if (dialog.open() == Window.OK) {
425 			final Object element = dialog.getFirstResult();
426 			if (element instanceof IJavaProject) {
427 				final IJavaProject jproject = (IJavaProject) element;
428 				return jproject.getPackageFragmentRoot(jproject.getProject());
429 			} else if (element instanceof IPackageFragmentRoot) {
430 				return (IPackageFragmentRoot) element;
431 			}
432 			return null;
433 		}
434 		return null;
435 	}
436 
choosePackage()437 	private IPackageFragment choosePackage() {
438 		IJavaElement[] packages = null;
439 		try {
440 			if (froot != null && froot.exists()) {
441 				packages = froot.getChildren();
442 			}
443 		} catch (final JavaModelException e) {
444 			e.printStackTrace();
445 		}
446 		if (packages == null) {
447 			packages = new IJavaElement[0];
448 		}
449 
450 		final ElementListSelectionDialog dialog = new ElementListSelectionDialog(getShell(),
451 				new JavaElementLabelProvider(JavaElementLabelProvider.SHOW_DEFAULT));
452 		dialog.setIgnoreCase(false);
453 		dialog.setTitle(Messages.AbstractNewClassPage_ChoosePackage);
454 		dialog.setMessage(Messages.AbstractNewClassPage_ChooseAPackage);
455 		dialog.setEmptyListMessage(Messages.AbstractNewClassPage_NeedToSelectAPackage);
456 		dialog.setElements(packages);
457 		dialog.setHelpAvailable(false);
458 		final IPackageFragment pack = clazz.getPackageFragment();
459 		if (pack != null) {
460 			dialog.setInitialSelections(pack);
461 		}
462 
463 		if (dialog.open() == Window.OK) {
464 			return (IPackageFragment) dialog.getFirstResult();
465 		}
466 		return null;
467 	}
468 
createFields(Composite parent, DataBindingContext dbc)469 	protected abstract void createFields(Composite parent, DataBindingContext dbc);
470 
createInstance()471 	protected abstract JavaClass createInstance();
472 
getClazz()473 	public JavaClass getClazz() {
474 		return clazz;
475 	}
476 
477 	/**
478 	 * Validate the specified class does not already exists
479 	 */
480 	static class ClassMultiValidator extends MultiValidator {
481 
482 		private final JavaClass javaClass;
483 		private final IObservableValue<String> observedPackage;
484 		private final IObservableValue<String> observedClass;
485 
ClassMultiValidator(JavaClass javaClass, final IObservableValue<String> observedPackage, final IObservableValue<String> observedClass)486 		public ClassMultiValidator(JavaClass javaClass, final IObservableValue<String> observedPackage,
487 				final IObservableValue<String> observedClass) {
488 			this.javaClass = javaClass;
489 			this.observedPackage = observedPackage;
490 			this.observedClass = observedClass;
491 		}
492 
493 		@Override
validate()494 		protected IStatus validate() {
495 			final String classPackage = observedPackage.getValue();
496 			final String className = observedClass.getValue();
497 
498 			final IPackageFragment packageFragment = javaClass.getFragmentRoot().getPackageFragment(classPackage);
499 
500 			if (JavaClass.exists(javaClass.getFragmentRoot(), packageFragment, className)) {
501 				return new Status(IStatus.ERROR, ToolsPlugin.PLUGIN_ID, Messages.AbstractNewClassPage_ClassExists);
502 			}
503 
504 			return ValidationStatus.ok();
505 		}
506 
507 	}
508 
509 	static class ClassnameValidator implements IValidator<String> {
510 
511 		@Override
validate(String name)512 		public IStatus validate(String name) {
513 			if (name.length() == 0) {
514 				return new Status(IStatus.ERROR, ToolsPlugin.PLUGIN_ID, Messages.AbstractNewClassPage_NameNotEmpty);
515 			}
516 			if (name.indexOf('.') != -1 || name.trim().indexOf(' ') != -1) {
517 				return new Status(IStatus.ERROR, ToolsPlugin.PLUGIN_ID,
518 						Messages.AbstractNewClassPage_NameMustBeQualified);
519 			}
520 
521 			return JavaConventions.validateJavaTypeName(name, JavaCore.VERSION_1_3, JavaCore.VERSION_1_3);
522 		}
523 	}
524 
525 	static class PFRootValidator implements IValidator<Object> {
526 
527 		@Override
validate(Object value)528 		public IStatus validate(Object value) {
529 			final String name = value.toString();
530 			if (name.length() == 0) {
531 				return new Status(IStatus.ERROR, ToolsPlugin.PLUGIN_ID,
532 						Messages.AbstractNewClassPage_SourceFolderNotEmpty);
533 			}
534 
535 			return new Status(IStatus.OK, ToolsPlugin.PLUGIN_ID, ""); //$NON-NLS-1$
536 		}
537 	}
538 
539 	static class PackageFragmentRootToStringConverter extends Converter<IPackageFragmentRoot, String> {
540 
PackageFragmentRootToStringConverter()541 		public PackageFragmentRootToStringConverter() {
542 			super(IPackageFragmentRoot.class, String.class);
543 		}
544 
545 		@Override
convert(IPackageFragmentRoot fromObject)546 		public String convert(IPackageFragmentRoot fromObject) {
547 			if (fromObject == null) {
548 				return ""; //$NON-NLS-1$
549 			}
550 			return fromObject.getPath().makeRelative().toString();
551 		}
552 	}
553 
554 	static class PackageFragmentToStringConverter extends Converter<IPackageFragment, String> {
555 
PackageFragmentToStringConverter()556 		public PackageFragmentToStringConverter() {
557 			super(IPackageFragment.class, String.class);
558 		}
559 
560 		@Override
convert(IPackageFragment fromObject)561 		public String convert(IPackageFragment fromObject) {
562 			if (fromObject == null) {
563 				return ""; //$NON-NLS-1$
564 			}
565 			return fromObject.getElementName();
566 		}
567 	}
568 
569 	static class StringToPackageFragmentConverter extends Converter<String, IPackageFragment> {
570 
571 		private final JavaClass clazz;
572 
StringToPackageFragmentConverter(JavaClass clazz)573 		public StringToPackageFragmentConverter(JavaClass clazz) {
574 			super(String.class, IPackageFragment.class);
575 			this.clazz = clazz;
576 		}
577 
578 		@Override
convert(String fromObject)579 		public IPackageFragment convert(String fromObject) {
580 			if (clazz.getFragmentRoot() == null) {
581 				return null;
582 			}
583 			if (fromObject == null) {
584 				return clazz.getFragmentRoot().getPackageFragment(""); //$NON-NLS-1$
585 			}
586 
587 			return clazz.getFragmentRoot().getPackageFragment(fromObject);
588 
589 		}
590 	}
591 }
592