blob: b007b42972b93a53e1016e4975157e981eecc803 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2013 BSI Business Systems Integration AG.
* 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:
* BSI Business Systems Integration AG - initial API and implementation
******************************************************************************/
package org.eclipse.scout.sdk.ui.internal.extensions.codecompletion;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jface.text.DocumentEvent;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.scout.commons.holders.Holder;
import org.eclipse.scout.commons.holders.IHolder;
import org.eclipse.scout.sdk.operation.IOperation;
import org.eclipse.scout.sdk.ui.action.AbstractScoutHandler;
import org.eclipse.scout.sdk.ui.executor.AbstractWizardExecutor;
import org.eclipse.scout.sdk.ui.executor.selection.ScoutStructuredSelection;
import org.eclipse.scout.sdk.ui.extensions.executor.IExecutor;
import org.eclipse.scout.sdk.ui.fields.proposal.SiblingProposal;
import org.eclipse.scout.sdk.ui.internal.ScoutSdkUi;
import org.eclipse.scout.sdk.util.NamingUtility;
import org.eclipse.scout.sdk.util.log.ScoutStatus;
import org.eclipse.scout.sdk.util.type.ITypeFilter;
import org.eclipse.scout.sdk.util.type.TypeFilters;
import org.eclipse.scout.sdk.util.type.TypeUtility;
import org.eclipse.scout.sdk.util.typecache.IWorkingCopyManager;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.text.edits.DeleteEdit;
/**
* <h3>{@link AbstractSdkWizardProposal}</h3>
*
* @author Matthias Villiger
* @since 4.1.0 11.07.2014
*/
public abstract class AbstractSdkWizardProposal extends AbstractSdkProposal {
private final IType m_declaringType;
private final IType m_siblingSubTypeFilter;
private final int m_startOffset;
protected AbstractSdkWizardProposal(IType declaringType, IType siblingSubTypeFilter, int startOffset) {
m_declaringType = declaringType;
m_siblingSubTypeFilter = siblingSubTypeFilter;
m_startOffset = startOffset;
}
public IType getDeclaringType() {
return m_declaringType;
}
protected abstract IExecutor createExecutor();
protected IJavaElement findSibling(int sourceRangeOffset) {
IJavaElement sibling = null;
try {
ITypeFilter filter = null;
if (m_siblingSubTypeFilter != null) {
// do not use the filter using the TypeUtility.getLocalTypeHierarchy(getDeclaringType()) because in dirty compilation units, this hierarchy may be empty!
filter = TypeFilters.getSubtypeFilter(m_siblingSubTypeFilter);
}
sibling = findSibling(getDeclaringType(), sourceRangeOffset, filter);
}
catch (JavaModelException e) {
ScoutSdkUi.logWarning("could not find sibling in type '" + getDeclaringType().getFullyQualifiedName() + "'.", e);
}
return sibling;
}
@Override
public void apply(ITextViewer viewer, char trigger, int stateMask, int offset) {
SiblingProposal proposal = null;
IJavaElement sibling = findSibling(offset);
if (TypeUtility.exists(sibling)) {
proposal = new SiblingProposal(sibling);
}
String name = null;
IOperation removePrefixOp = null;
if (m_startOffset >= 0) {
ICompilationUnit icu = getDeclaringType().getCompilationUnit();
IDocument document = viewer.getDocument();
String source = document.get();
if (source != null && source.length() >= offset && offset >= m_startOffset) {
name = NamingUtility.ensureStartWithUpperCase(source.substring(m_startOffset, offset));
removePrefixOp = new P_RemovePrefixOperation(icu, document, viewer.getTextWidget().getDisplay(), m_startOffset, offset);
}
}
ScoutStructuredSelection selection = new ScoutStructuredSelection(new Object[]{getDeclaringType()});
selection.setSibling(proposal);
selection.setTypeName(name);
IExecutor executor = createExecutor();
if (removePrefixOp != null && executor instanceof AbstractWizardExecutor) {
AbstractWizardExecutor wizEx = (AbstractWizardExecutor) executor;
wizEx.addAdditionalPerformFinishOperation(removePrefixOp, -10.0d); // execute before wizard finish
}
Shell shell = ScoutSdkUi.getShell();
ExecutionEvent event = AbstractScoutHandler.createEvent(shell, selection);
executor.run(shell, selection, event);
}
@Override
public void selected(ITextViewer viewer, boolean smartToggle) {
}
@Override
public boolean validate(IDocument document, int offset, DocumentEvent event) {
return true;
}
private static final class P_RemovePrefixOperation implements IOperation {
private final IDocument m_document;
private final int m_start, m_end;
private final ICompilationUnit m_icu;
private final Display m_display;
private P_RemovePrefixOperation(ICompilationUnit icu, IDocument doc, Display display, int start, int end) {
m_document = doc;
m_display = display;
m_start = start;
m_end = end;
m_icu = icu;
}
@Override
public String getOperationName() {
return "Remove Prefix";
}
@Override
public void validate() {
}
@Override
public void run(final IProgressMonitor monitor, final IWorkingCopyManager workingCopyManager) throws CoreException {
final DeleteEdit removePrefix = new DeleteEdit(m_start, m_end - m_start);
final IHolder<Exception> exHolder = new Holder<Exception>(Exception.class, null);
m_display.syncExec(new Runnable() {
@Override
public void run() {
try {
workingCopyManager.register(m_icu, monitor);
removePrefix.apply(m_document);
}
catch (Exception e) {
exHolder.setValue(e);
}
}
});
Exception e = exHolder.getValue();
if (e != null) {
throw new CoreException(new ScoutStatus("Unable to delete prefix.", e));
}
m_icu.getBuffer().setContents(m_document.get());
workingCopyManager.reconcile(m_icu, monitor);
}
}
}