/**
* Copyright 2004-2016 Riccardo Solmi. All rights reserved.
* This file is part of the Whole Platform.
*
* The Whole Platform is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* The Whole Platform is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the Whole Platform. If not, see <http://www.gnu.org/licenses/>.
*/
package org.whole.lang.ui.actions;
import java.io.File;
import java.net.URL;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.e4.ui.services.IServiceConstants;
import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
import org.eclipse.gef.commands.CommandStack;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.dialogs.ElementTreeSelectionDialog;
import org.eclipse.ui.model.WorkbenchContentProvider;
import org.eclipse.ui.model.WorkbenchLabelProvider;
import org.whole.lang.bindings.BindingManagerFactory;
import org.whole.lang.bindings.IBindingManager;
import org.whole.lang.e4.ui.actions.AbstractE4Action;
import org.whole.lang.e4.ui.handler.HandlersBehavior;
import org.whole.lang.factories.GenericEntityFactory;
import org.whole.lang.model.IEntity;
import org.whole.lang.reflect.EntityDescriptor;
import org.whole.lang.ui.commands.ModelTransactionCommand;
import org.whole.lang.ui.dialogs.SelectResourceAsDialog;
import org.whole.lang.ui.util.ResourceUtils;
import org.whole.lang.ui.util.UIUtils;
import org.whole.lang.ui.viewers.IEntityPartViewer;
import org.whole.lang.util.StringUtils;
/**
* @author Enrico Persiani, Riccardo Solmi
*/
public abstract class ReplaceWithResourceAction extends AbstractE4Action {
protected static final String SELECT_RESOURCE_MSG = "Select a resource";
protected static final ImageDescriptor SELECT_RESOURCE_ICON = UIUtils.getImageDescriptor("icons/actions/select_persistence.gif");
public static enum ResourceKind {
WORKSPACE, FILE_SYSTEM, CLASSPATH, URL
}
protected EntityDescriptor<?> ed;
protected String path;
public ReplaceWithResourceAction(IEclipseContext context, EntityDescriptor<?> ed, String path, String text) {
super(context, text, SELECT_RESOURCE_ICON);
this.ed = ed;
this.path = path;
}
@Override
public void update() {
ESelectionService selectionService = getContext().get(ESelectionService.class);
if (selectionService.getSelection() instanceof IBindingManager) {
IBindingManager bm = (IBindingManager) selectionService.getSelection();
setEnabled(HandlersBehavior.isValidFocusEntityPart(bm));
} else
setEnabled(false);
}
protected abstract boolean isLoading(IEntity selectedEntity);
protected abstract ResourceKind getResourceKind(IEntity selectedEntity);
@Override
public void run() {
ESelectionService selectionService = getContext().get(ESelectionService.class);
IBindingManager bm = (IBindingManager) selectionService.getSelection();
IEntity focusEntity = bm.wGet("focusEntity");
ResourceKind resourceKind = getResourceKind(focusEntity);
Shell shell = (Shell) getContext().get(IServiceConstants.ACTIVE_SHELL);
boolean selectionPerformed = false;
switch (resourceKind) {
case WORKSPACE:
selectionPerformed = performWorkspaceResourceSelection(shell, focusEntity);
break;
case CLASSPATH:
selectionPerformed = performClasspathResourceSelection(shell, focusEntity);
break;
case FILE_SYSTEM:
case URL:
selectionPerformed = performFilesystemSelection(shell, focusEntity, resourceKind == ResourceKind.URL);
break;
}
if (!selectionPerformed)
return;
IEntity replacement = GenericEntityFactory.instance.create(ed, path);
ModelTransactionCommand mtc = new ModelTransactionCommand(focusEntity);
try {
mtc.setLabel("replace with class name");
mtc.begin();
performReplace(focusEntity, replacement);
mtc.commit();
if (mtc.canUndo()) {
IEntityPartViewer viewer = (IEntityPartViewer) bm.wGetValue("viewer");
CommandStack commandStack = viewer.getEditDomain().getCommandStack();
commandStack.execute(mtc);
}
} catch (RuntimeException e) {
mtc.rollbackIfNeeded();
throw e;
}
}
protected void performReplace(IEntity primarySelectedEntity, IEntity replacement) {
primarySelectedEntity.wGetParent().wSet(primarySelectedEntity, replacement);
}
protected boolean performFilesystemSelection(Shell shell, IEntity entity, boolean isURL) {
int style = isLoading(entity) ? SWT.OPEN : SWT.SAVE;
FileDialog dialog = new FileDialog(shell, style);
dialog.setText(SELECT_RESOURCE_MSG);
File file = isURL ? URLToFile(path) : new File(path);
if (file.exists() && file.isFile()) {
dialog.setFilterPath(file.getParent());
dialog.setFileName(file.getName());
}
if ((path = dialog.open()) == null)
return false;
if (isURL)
path = FileToURL(new File(path));
return true;
}
protected boolean performWorkspaceResourceSelection(Shell shell, IEntity entity) {
IPath filePath = Path.fromPortableString(path);
IResource resource = filePath.isAbsolute() ?
ResourcesPlugin.getWorkspace().getRoot().findMember(filePath) : null;
ElementTreeSelectionDialog dialog = new ElementTreeSelectionDialog(shell, new WorkbenchLabelProvider(), new WorkbenchContentProvider());
dialog.setInput(ResourcesPlugin.getWorkspace());
dialog.setTitle(SELECT_RESOURCE_MSG);
dialog.setMessage("Choose a resource");
dialog.setInitialSelection(resource);
if (dialog.open() != IDialogConstants.OK_ID)
return false;
Object[] selection = dialog.getResult();
path = selection.length == 0 ? "/" : ((IResource) selection[0]).getFullPath().toPortableString();
return true;
}
protected boolean performClasspathResourceSelection(Shell shell, IEntity entity) {
String fileName = Path.fromPortableString(path).lastSegment();
if (fileName != null && StringUtils.getFileExtension(fileName)
.equals(StringUtils.CLASS_FILE_EXTENSION))
fileName = StringUtils.appendFileExtension(
StringUtils.stripFileExtension(fileName),
StringUtils.JAVA_FILE_EXTENSION);
IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
SelectResourceAsDialog dialog = new SelectResourceAsDialog(shell, workspaceRoot, IResource.FILE);
if (fileName != null)
dialog.setInitialPattern(fileName);
if (dialog.open() != IDialogConstants.OK_ID)
return false;
Object[] selection = dialog.getResult();
IBindingManager bm = BindingManagerFactory.instance.createBindingManager();
IFile file = workspaceRoot.getFile(((IResource) selection[0]).getFullPath());
ResourceUtils.defineResourceBindings(bm, file);
if (bm.wStringValue("fileExtension").equals(StringUtils.JAVA_FILE_EXTENSION))
path = StringUtils.toResourceClasspath(bm.wStringValue("compilationUnitName"));
else
path = StringUtils.packagePath(bm.wStringValue("packageName"))+File.separator+
bm.wStringValue("fileNameWithExtension");
return true;
}
public static File URLToFile(String url) {
try {
return new File(new URL(url).toURI().getPath());
} catch (Exception e) {
return new File(url);
}
}
public static String FileToURL(File file) {
try {
return file.toURI().toURL().toExternalForm();
} catch (Exception e) {
return file.getAbsolutePath();
}
}
public void transform(IEntity oldEntity, IEntity newEntity) {
newEntity.wSetValue(path);
}
}