/******************************************************************************* * Copyright (c) 2016 Red Hat, Inc. * Distributed under license by Red Hat, Inc. All rights reserved. * This program is 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: * Red Hat, Inc. - initial API and implementation ******************************************************************************/ package org.jboss.tools.windup.ui.internal.explorer; import java.io.File; import java.rmi.RemoteException; import javax.inject.Inject; import javax.inject.Singleton; import org.apache.commons.io.FileUtils; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IResource; import org.eclipse.e4.core.di.annotations.Creatable; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.internal.ui.text.java.JavaFormattingStrategy; import org.eclipse.jface.text.Document; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.Region; import org.eclipse.jface.text.formatter.MultiPassContentFormatter; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.eclipse.wst.sse.core.StructuredModelManager; import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel; import org.eclipse.wst.xml.core.internal.formatter.XMLFormatterFormatProcessor; import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel; import org.jboss.tools.windup.model.domain.WorkspaceResourceUtils; import org.jboss.tools.windup.model.util.DocumentUtils; import org.jboss.tools.windup.runtime.WindupRmiClient; import org.jboss.tools.windup.ui.WindupUIPlugin; import org.jboss.tools.windup.ui.internal.rules.xml.XMLRulesetModelUtil; import org.jboss.tools.windup.ui.internal.services.MarkerService; import org.jboss.tools.windup.windup.ConfigurationElement; import org.jboss.tools.windup.windup.Hint; import org.jboss.tools.windup.windup.Input; import org.jboss.tools.windup.windup.Issue; import org.jboss.tools.windup.windup.QuickFix; import org.jboss.windup.tooling.ExecutionBuilder; import org.jboss.windup.tooling.data.QuickfixType; import org.jboss.windup.tooling.quickfix.QuickfixLocationDTO; import com.google.common.base.Objects; /** * Service for interacting with quick fixes. */ @SuppressWarnings("restriction") @Creatable @Singleton public class QuickfixService { @Inject private MarkerService markerService; @Inject private WindupRmiClient windupClient; public void applyQuickFix(QuickFix quickfix) { IMarker quickfixMarker =(IMarker)quickfix.getMarker(); IResource newResource = getQuickFixedResource(quickfix, quickfixMarker); DocumentUtils.replace(quickfixMarker.getResource(), newResource); markerService.delete(quickfixMarker, quickfix); IResource quickfixResource = quickfixMarker.getResource(); Hint hint = (Hint)quickfix.eContainer(); IMarker hintMarker = (IMarker)hint.getMarker(); if (hintMarker.exists()) { /* * This is temporary. We're deleting all Windup markers associated with a resource that has been * transformed by the quickfix. Ideally, we should only delete the ones that have become stale, * but because the MarkerSync service hasn't yet been notified, we're clearing all of them for now. */ IResource hintResource = hintMarker.getResource(); if (!Objects.equal(hintResource, quickfixResource)) { markerService.clear(quickfixResource); } if (!hint.isFixed()) { if (hintMarker != null && hintMarker.exists()) { markerService.setFixed(hint); } } } else { markerService.clear(quickfixResource); } } public IResource getQuickFixedResource(QuickFix quickFix, IMarker marker) { Hint hint = (Hint)quickFix.eContainer(); IResource original = marker.getResource(); TempProject project = new TempProject(); if (QuickfixType.REPLACE.toString().equals(quickFix.getQuickFixType())) { int lineNumber = hint.getLineNumber()-1; String searchString = quickFix.getSearchString(); String replacement = quickFix.getReplacementString(); Document document = DocumentUtils.replace(original, lineNumber, searchString, replacement); return project.createResource(document.get()); } else if (QuickfixType.DELETE_LINE.toString().equals(quickFix.getQuickFixType())) { int lineNumber = hint.getLineNumber()-1; Document document = DocumentUtils.deleteLine(original, lineNumber); return project.createResource(document.get()); } else if (QuickfixType.INSERT_LINE.toString().equals(quickFix.getQuickFixType())) { int lineNumber = hint.getLineNumber(); lineNumber = lineNumber > 1 ? lineNumber - 2 : lineNumber-1; String newLine = quickFix.getReplacementString(); Document document = DocumentUtils.insertLine(original, lineNumber, newLine); return project.createResource(document.get()); } else if (QuickfixType.TRANSFORMATION.toString().equals(quickFix.getQuickFixType())) { // TODO: Quickfixes need their own location info. int lineNumber = hint.getLineNumber(); // marker.getAttribute(IMarker.LINE_NUMBER, hint.getLineNumber()); int column = hint.getColumn(); // marker.getAttribute(IMarker.CHAR_START, hint.getColumn()); int length = hint.getLength(); //marker.getAttribute(IMarker.CHAR_END, hint.getLength()); Input input = (Input)hint.eContainer().eContainer(); ConfigurationElement configuration = (ConfigurationElement)input.eContainer(); String reportBaseLocation = configuration.getReportDirectory(); File reportDirectory = new File(reportBaseLocation); QuickfixLocationDTO locationDTO = new QuickfixLocationDTO( reportDirectory, original.getLocation().toFile(), lineNumber, column, length); try { if (windupClient.isWindupServerRunning()) { ExecutionBuilder builder = windupClient.getExecutionBuilder(); String preview = builder.transform(quickFix.getTransformationId(), locationDTO); preview = format(marker.getResource(), preview); return project.createResource(preview); } } catch (RemoteException e) { WindupUIPlugin.log(e); } } return null; } public void previewQuickFix(Hint hint, IMarker marker) { Shell shell = Display.getCurrent().getActiveShell(); QuickFixDiffDialog dialog = new QuickFixDiffDialog(shell, hint, this); if (dialog.open() == IssueConstants.APPLY_FIX) { for (QuickFix quickfix : dialog.getQuickfixes()) { applyQuickFix(quickfix); } } } private String format(IResource resource, String contents) { /* * Java Formatting */ if (JavaCore.create(resource) != null) { MultiPassContentFormatter formatter= new MultiPassContentFormatter(/*IJavaPartitions.JAVA_PARTITIONING*/"__dftl_partitioning", IDocument.DEFAULT_CONTENT_TYPE); formatter.setMasterStrategy(new JavaFormattingStrategy()); Document document = new Document(contents); formatter.format(document, new Region(0, document.getLength())); return document.get(); } /* * XML Formatting */ IDOMModel xmlModel = XMLRulesetModelUtil.getModel(WorkspaceResourceUtils.getFile(resource.getLocation().toString()), true); if (xmlModel != null) { XMLFormatterFormatProcessor formatProcessor = new XMLFormatterFormatProcessor(); try { TempProject project = new TempProject(); IFile file = (IFile)project.createResource(contents); IStructuredModel model = StructuredModelManager.getModelManager().createUnManagedStructuredModelFor(file); formatProcessor.formatModel(model); StructuredModelManager.getModelManager().saveStructuredDocument(model.getStructuredDocument(), file); return FileUtils.readFileToString(file.getLocation().toFile()); } catch (Exception e) { WindupUIPlugin.log(e); } } return contents; } public static boolean isIssueFixable(Issue issue) { return !issue.isStale() && !issue.isFixed() && !issue.getQuickFixes().isEmpty(); } }