/**
* This file is licensed under the University of Illinois/NCSA Open Source License. See LICENSE.TXT for details.
*/
package edu.illinois.codingtracker.tests.postprocessors;
import java.util.List;
import edu.illinois.codingtracker.helpers.Configuration;
import edu.illinois.codingtracker.operations.UserOperation;
import edu.illinois.codingtracker.operations.refactorings.FinishedRefactoringOperation;
import edu.illinois.codingtracker.operations.refactorings.NewStartedRefactoringOperation;
import edu.illinois.codingtracker.operations.refactorings.NewStartedRefactoringOperation.RefactoringMode;
import edu.illinois.codingtracker.operations.refactorings.PerformedRefactoringOperation;
import edu.illinois.codingtracker.operations.refactorings.RedoneRefactoringOperation;
import edu.illinois.codingtracker.operations.refactorings.RefactoringOperation;
import edu.illinois.codingtracker.operations.refactorings.UndoneRefactoringOperation;
import edu.illinois.codingtracker.operations.starts.StartedRefactoringOperation;
import edu.illinois.codingtracker.recording.TextRecorder;
/**
* This class upgrades an operation sequence from the old format to the new one by deserializing it
* in OLD_CODINGTRACKER_FORMAT mode and then serializing it in the new format. Also, it upgrades
* refactoring operations to the new API.
*
* Note that to use this functionality properly, the environment variable OLD_CODINGTRACKER_FORMAT
* has to be set.
*
* @author Stas Negara
*
*/
public class UpdateOperationSequenceFormatPostprocessor extends CodingTrackerPostprocessor {
private final static String FIRST_VERSION_WITH_NEW_FORMAT= "1.0.0.201105172309";
@Override
protected void checkPostprocessingPreconditions() {
if (!Configuration.isOldFormat) {
throw new RuntimeException("Set environment variable OLD_CODINGTRACKER_FORMAT to perform the format update correctly");
}
}
@Override
protected boolean shouldPostprocessVersionFolder(String folderName) {
return folderName.startsWith(VERSION_FOLDER_COMMON_PREFIX) && folderName.compareTo(FIRST_VERSION_WITH_NEW_FORMAT) < 0;
}
@Override
protected String getRecordFileName() {
return "codechanges_manual.txt";
}
@Override
protected void postprocess(List<UserOperation> userOperations) {
updateRefactoringOperations(userOperations);
for (UserOperation userOperation : userOperations) {
TextRecorder.record(userOperation);
}
}
private void updateRefactoringOperations(List<UserOperation> userOperations) {
int lastStartedRefactoringIndex= -1;
long lastStartedRefactoringTimestamp= -1;
for (int i= 0; i < userOperations.size(); i++) {
UserOperation userOperation= userOperations.get(i);
if (userOperation instanceof StartedRefactoringOperation) {
lastStartedRefactoringIndex= i;
lastStartedRefactoringTimestamp= userOperation.getTime();
continue;
}
if (userOperation instanceof RefactoringOperation) {
RefactoringOperation refactoringOperation= (RefactoringOperation)userOperation;
if (lastStartedRefactoringIndex == -1) {
throw new RuntimeException("Found RefactoringOperation without preceding StartedRefactoringOperation: " + refactoringOperation);
}
long newStartedRefactoringTimestamp= lastStartedRefactoringTimestamp;
long finishedRefactoringTimestamp= refactoringOperation.getTime();
if (newStartedRefactoringTimestamp > finishedRefactoringTimestamp) {
//This could happen when a refactoring is undone or redone. To keep consistent with the timestamps of the
//new refactoring operations for undo or redo, adjust timestamps accordingly.
newStartedRefactoringTimestamp= finishedRefactoringTimestamp; //this is timestamp of the originally performed refactoring
finishedRefactoringTimestamp= userOperations.get(i - 1).getTime();
}
NewStartedRefactoringOperation newStartedRefactoringOperation= new NewStartedRefactoringOperation(true, getRefactoringMode(refactoringOperation), refactoringOperation.getID(),
refactoringOperation.getProject(), refactoringOperation.getFlags(), refactoringOperation.getArguments(), newStartedRefactoringTimestamp);
FinishedRefactoringOperation finishedRefactoringOperation= new FinishedRefactoringOperation(true, finishedRefactoringTimestamp);
userOperations.set(lastStartedRefactoringIndex, newStartedRefactoringOperation);
userOperations.set(i, finishedRefactoringOperation);
lastStartedRefactoringIndex= -1;
}
}
}
private RefactoringMode getRefactoringMode(RefactoringOperation refactoringOperation) {
if (refactoringOperation instanceof PerformedRefactoringOperation) {
return RefactoringMode.PERFORM;
}
if (refactoringOperation instanceof UndoneRefactoringOperation) {
return RefactoringMode.UNDO;
}
if (refactoringOperation instanceof RedoneRefactoringOperation) {
return RefactoringMode.REDO;
}
throw new RuntimeException("Can not establish refactoring mode for refactoring operation: " + refactoringOperation);
}
}