/******************************************************************************* * 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.model.util; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.List; import java.util.Objects; import org.apache.commons.io.FileUtils; import org.eclipse.core.resources.IResource; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.Document; import org.eclipse.jface.text.FindReplaceDocumentAdapter; import org.eclipse.jface.text.IRegion; import org.jboss.tools.windup.model.Activator; import com.google.common.collect.Lists; /** * Utility for editing document. */ public class DocumentUtils { /** * Returns the line of text from the specified resource at the specified line number. */ public static String getLine(IResource resource, int lineNumber) { try { String contents = FileUtils.readFileToString(resource.getLocation().toFile()); Document document = new Document(contents); IRegion region = document.getLineInformation(lineNumber); return document.get(region.getOffset(), region.getLength()); } catch (IOException | BadLocationException e) { Activator.log(e); } return ""; } public static int getLineNumbers(IResource resource) { try { String contents = FileUtils.readFileToString(resource.getLocation().toFile()); Document document = new Document(contents); return document.getNumberOfLines(); } catch (Exception e) { Activator.log(e); } return 0; } /** * Returns true if the line of text within the specified resource differs from that of * the specified line of text. */ public static boolean differs(IResource resource, int lineNumber, String text) { String line = DocumentUtils.getLine(resource, lineNumber); return !Objects.equals(line, text); } /** * Replaces the chunk of text represented as <code>searchString</code> with the specified <code>replacement</code> * text at the given line number in the specified resource. */ public static Document replace(IResource resource, int lineNumber, String searchString, String replacement) { try { String contents = FileUtils.readFileToString(resource.getLocation().toFile()); Document document = new Document(contents); IRegion info = document.getLineInformation(lineNumber); FindReplaceDocumentAdapter adapter = new FindReplaceDocumentAdapter(document); IRegion search = adapter.find(info.getOffset(), searchString, true, true, true, false); if (search != null) { document.replace(search.getOffset(), search.getLength(), replacement); } return document; } catch (IOException | BadLocationException e) { Activator.log(e); } return null; } /** * Deletes the line of text in the specified resource at the specified line number. */ public static Document deleteLine(IResource resource, int lineNumber) { try { String contents = FileUtils.readFileToString(resource.getLocation().toFile()); Document document = new Document(contents); IRegion info = document.getLineInformation(lineNumber); document.replace(info.getOffset(), info.getLength()+1, null); return document; } catch (IOException | BadLocationException e) { Activator.log(e); } return null; } /** * Inserts the provided chunk of text represented as <code>newLine</code> in the given * resource at the specified line. */ public static Document insertLine(IResource resource, int lineNumber, String newLine) { try { String contents = FileUtils.readFileToString(resource.getLocation().toFile()); Document document = new Document(contents); // TODO: This seems cumbersome. Find a cleaner way of performing insert. IRegion previousLine = document.getLineInformation(lineNumber); List<String> indentChars = DocumentUtils.getLeadingChars(document, previousLine); StringBuilder builder = new StringBuilder(); builder.append(System.lineSeparator()); for (String indentChar : indentChars) { builder.append(indentChar); } builder.append(newLine); int newLineOffset = previousLine.getOffset() + previousLine.getLength(); document.replace(newLineOffset, 0, builder.toString()); return document; } catch (IOException | BadLocationException e) { Activator.log(e); } return null; } /** * Returns a list of characters leading up to the first non-whitespace character. */ private static List<String> getLeadingChars(Document document, IRegion line) throws BadLocationException { List<String> result = Lists.newArrayList(); int pos= line.getOffset(); int max= pos + line.getLength(); while (pos < max) { char next = document.getChar(pos); if (!Character.isWhitespace(next)) break; result.add(String.valueOf(next)); pos++; } return result; } /** * Replace text of one resource <code>left</code> with the text of the other <code>right</code>. */ public static void replace(IResource left, IResource right) { File leftFile = left.getLocation().toFile(); File rightFile = right.getLocation().toFile(); try { FileOutputStream outputFile = new FileOutputStream(leftFile, false); FileInputStream inputFile = new FileInputStream(rightFile); byte[] buffer = new byte[1024]; int length; while((length = inputFile.read(buffer)) > 0) { outputFile.write(buffer, 0, length); } outputFile.close(); inputFile.close(); left.refreshLocal(IResource.DEPTH_INFINITE, null); } catch (Exception e) { Activator.log(e); } } }