/******************************************************************************* * Copyright (c) 2010 György Orosz. * 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: * György Orosz - initial API and implementation ******************************************************************************/ package org.erlide.wrangler.refactoring.util; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.eclipse.text.edits.DeleteEdit; import org.eclipse.text.edits.InsertEdit; import org.eclipse.text.edits.MultiTextEdit; import org.eclipse.text.edits.ReplaceEdit; import org.eclipse.text.edits.TextEdit; import org.incava.util.diff.Diff; import org.incava.util.diff.Difference; /** * Tool for comparing the refactor tool's output with the original file. * * @author Gyorgy Orosz * @version %I%, %G% */ public final class ChangesetMaker { static private File inFile; // static private File outFile; static Diff<Character> algorithm; static private List<Character> inFileCharArray; static private List<Character> outFileCharArray; static private List<Difference> differencesList; /** * Converts the given char array to list. * * @param charArray * @return list of chars */ @SuppressWarnings("boxing") private static List<Character> convertArrayToArrayList(final char[] charArray) { final List<Character> result = new ArrayList<>(); for (final char c : charArray) { result.add(c); } return result; } /** * Creates <code>Edit</code> object from a <code>Difference</code> object * * @param diff * @return */ private static TextEdit createEditFromDiff(final Difference diff) { TextEdit result = null; // delete if (diff.getAddedEnd() == -1 && diff.getDeletedEnd() != -1) { result = new DeleteEdit(diff.getDeletedStart(), diff.getDeletedEnd() - diff.getDeletedStart() + 1); } // replace else if (diff.getAddedEnd() != -1 && diff.getDeletedEnd() != -1) { result = createReplaceEdit(diff.getAddedStart(), diff.getAddedEnd(), diff.getDeletedStart(), diff.getDeletedEnd()); } // insert else if (diff.getAddedEnd() != -1 && diff.getDeletedEnd() == -1) { result = new InsertEdit(diff.getDeletedStart(), getString(diff.getAddedStart(), diff.getAddedEnd())); } return result; } // @SuppressWarnings("unchecked") // static public ArrayList<TextEdit> createEdits(File in, File out) // throws IOException { // inFile = in; // outFile = out; // // ArrayList<TextEdit> edits = new ArrayList<TextEdit>(); // inFileCharArray = null; // outFileCharArray = null; // // inFileCharArray = splitFile(inFile); // outFileCharArray = splitFile(outFile); // // algorithm = new Diff(inFileCharArray, outFileCharArray); // // differencesList = algorithm.diff(); // for (Difference d : differencesList) { // edits.add(createEditFromDiff(d)); // } // // return edits; // } /** * Reads the input file, compares with the given new string, then creates * Eclipse's <code>TextEdit</code>-s. * * @param in * original file * @param out * modified file content * @return list of edit objects * @throws IOException * if the file could not be read */ static public List<TextEdit> createEdits(final File in, final String out) throws IOException { inFile = in; final List<TextEdit> edits = new ArrayList<>(); inFileCharArray = null; outFileCharArray = null; inFileCharArray = readFile(inFile); outFileCharArray = new ArrayList<>(); outFileCharArray = convertArrayToArrayList(out.toCharArray()); algorithm = new Diff<>(inFileCharArray, outFileCharArray); differencesList = algorithm.diff(); for (final Difference d : differencesList) { edits.add(createEditFromDiff(d)); } return edits; } /** * Creates a <code>ReplaceEdit</code> object from the given parameters and * the stored input/output strings. * * @param addedStart * @param addedEnd * @param deletedStart * @param deletedEnd * @return */ private static TextEdit createReplaceEdit(final int addedStart, final int addedEnd, final int deletedStart, final int deletedEnd) { final TextEdit result = new MultiTextEdit(); final int addedLength = addedEnd - addedStart + 1; final int deletedLength = deletedEnd - deletedStart + 1; final int minLength = Math.min(addedLength, deletedLength); if (deletedLength < addedLength) { result.addChild(new InsertEdit(deletedStart + minLength, getString(addedStart + minLength, addedEnd))); } result.addChild(new ReplaceEdit(deletedStart, minLength, getString(addedStart, addedStart + minLength - 1))); if (addedLength < deletedLength) { result.addChild( new DeleteEdit(deletedStart + minLength, deletedLength - minLength)); } return result; } /** * Gets the string from the new source file, according to the given * parameters. * * @param from * string's starting position * @param to * string's ending position * @return */ private static String getString(final int from, final int to) { String s = ""; // from, to+1 for (final char c : outFileCharArray) { s += c; } return s.substring(from, to + 1); } /** * Read the given files into a list of <code>Character</code>-s. * * @param file * the file which is read * @return * @throws IOException * if any i/o error occurs this exception is raised. */ @SuppressWarnings("boxing") static private List<Character> readFile(final File file) throws IOException { final List<Character> result = new ArrayList<>(); try (final BufferedReader input = new BufferedReader(new FileReader(file))) { final char c[] = new char[1]; while (input.read(c) > 0) { /* * char[] chars = line.toCharArray(); for (int i = 0; i < * chars.length; ++i) { result.add(chars[i]); } * result.add('\n'); } input.close(); if (result.size() != 0) { * result.remove(result.size() - 1); */ result.add(c[0]); } } return result; } private ChangesetMaker() { } }