/**
* Copyright (c) 2013 committers of YAKINDU 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:
* committers of YAKINDU - initial API and implementation
*
*/
package org.yakindu.sct.refactoring.handlers.impl;
import java.util.List;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.jface.dialogs.IInputValidator;
import org.eclipse.jface.dialogs.InputDialog;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.window.Window;
import org.eclipse.ui.IWorkbenchPartSite;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.xtext.EcoreUtil2;
import org.eclipse.xtext.linking.lazy.LazyLinkingResource;
import org.yakindu.base.base.NamedElement;
import org.yakindu.base.expressions.expressions.ElementReferenceExpression;
import org.yakindu.base.expressions.expressions.FeatureCall;
import org.yakindu.base.types.Declaration;
import org.yakindu.sct.model.sgraph.Scope;
import org.yakindu.sct.model.sgraph.Statechart;
import org.yakindu.sct.model.sgraph.util.ContextElementAdapter;
import org.yakindu.sct.refactoring.handlers.AbstractRefactoringHandler;
import org.yakindu.sct.refactoring.refactor.AbstractRefactoring;
import org.yakindu.sct.refactoring.refactor.impl.RenameRefactoring;
import com.google.common.collect.Lists;
/**
* Handler for {@link RenameRefactoring}.
*
* @author thomas kutz - Initial contribution and API
*
*/
public class RenameElementHandler extends AbstractRefactoringHandler<NamedElement> {
@Override
public Object execute(ExecutionEvent event) throws ExecutionException {
NamedElement element = refactoring.getContextObject();
if (element != null) {
IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
InputDialog dialog = new InputDialog(window.getShell(), "Rename..", "Please enter new name:", element.getName(), new NameUniquenessValidator(element));
if (dialog.open() == Window.OK) {
String newName = dialog.getValue();
if (newName != null) {
((RenameRefactoring)refactoring).setNewName(newName);
refactoring.execute();
}
}
}
return null;
}
/**
* Unwraps the given selection into a state sgraph element
*
* @param selection the current selection
* @return the state sgraph element for the given selection
*/
public NamedElement unwrap(ISelection selection) {
IStructuredSelection structuredSelection = (IStructuredSelection) selection;
EObject selectedElement = (EObject) structuredSelection.getFirstElement();
// The provided element is the one from the fake resource of styled text adapter.
// We need to find the actual element in our statechart for this fake element
if (selectedElement instanceof FeatureCall) {
return findElementForFakeInStatechart((NamedElement)((FeatureCall)selectedElement).getFeature());
}
else if (selectedElement instanceof ElementReferenceExpression) {
return findElementForFakeInStatechart((NamedElement)((ElementReferenceExpression)selectedElement).getReference());
}
if (selectedElement instanceof NamedElement)
return findElementForFakeInStatechart((NamedElement)selectedElement);
return null;
}
private NamedElement findElementForFakeInStatechart(NamedElement fakeElement) {
Resource resource = fakeElement.eResource();
// only do something if element is really from fake resource
if (resource instanceof LazyLinkingResource) {
Statechart sct = getStatechartFromFakeResource((LazyLinkingResource)resource);
EList<Scope> scopes = sct.getScopes();
for (Scope scope : scopes) {
// check all declarations
EList<Declaration> declarations = scope.getDeclarations();
for (Declaration decl : declarations) {
if (decl.eClass().getName().equals(fakeElement.eClass().getName())
&& decl.getName().equals(fakeElement.getName())) {
return decl;
}
}
// check scope itself it is a named one
if (scope instanceof NamedElement) {
NamedElement namedScope = (NamedElement) scope;
if (namedScope.eClass().getName().equals(fakeElement.eClass().getName())
&& namedScope.getName().equals(fakeElement.getName())) {
return namedScope;
}
}
}
}
return fakeElement;
}
protected Statechart getStatechartFromFakeResource(LazyLinkingResource resource) {
for (Adapter adapter : resource.eAdapters()) {
if (adapter instanceof ContextElementAdapter) {
EObject elem = ((ContextElementAdapter)adapter).getElement();
if (elem instanceof Statechart) {
return (Statechart) elem;
}
}
}
return null;
}
@Override
public boolean isEnabled() {
IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
if (window == null) {
return false;
}
IWorkbenchPartSite site = window.getActivePage().getActiveEditor().getSite();
if (site == null) {
return false;
}
ISelectionProvider selectionProvider = site.getSelectionProvider();
if (selectionProvider == null) {
return false;
}
ISelection currentSelection = selectionProvider.getSelection();
setContext(refactoring, currentSelection);
return refactoring.isExecutable();
}
@Override
public AbstractRefactoring<NamedElement> createRefactoring() {
return new RenameRefactoring();
}
@Override
public void setContext(AbstractRefactoring<NamedElement> refactoring,
ISelection selection) {
NamedElement element = unwrap(selection);
refactoring.setContextObjects(Lists.newArrayList(element));
}
private class NameUniquenessValidator implements IInputValidator {
protected List<String> existingNames;
public NameUniquenessValidator(NamedElement element) {
existingNames = Lists.newArrayList();
Scope scope = EcoreUtil2.getContainerOfType(element, Scope.class);
List<? extends NamedElement> allOfSameType = EcoreUtil2.getAllContentsOfType(scope, NamedElement.class);
allOfSameType.remove(element);
for (NamedElement namedElement : allOfSameType) {
existingNames.add(namedElement.getName());
}
}
public String isValid(String newText) {
return existingNames.contains(newText)? "Name already exists!": null;
}
}
}