package ca.uwaterloo.ece.qhanam.jrsrepair.context;
import java.util.HashMap;
import java.util.Random;
import ca.uwaterloo.ece.qhanam.jrsrepair.DocumentASTRewrite;
import ca.uwaterloo.ece.qhanam.jrsrepair.SourceStatement;
import ca.uwaterloo.ece.qhanam.jrsrepair.Statements;
import ca.uwaterloo.ece.qhanam.jrsrepair.mutation.Mutation;
import ca.uwaterloo.ece.qhanam.jrsrepair.mutation.NullMutation;
import ca.uwaterloo.ece.qhanam.jrsrepair.mutation.AdditionMutation;
import ca.uwaterloo.ece.qhanam.jrsrepair.mutation.DeletionMutation;
import ca.uwaterloo.ece.qhanam.jrsrepair.mutation.ReplacementMutation;
/**
* MutationContext stores the context for mutation operations and
* provides services to enable mutations.
*
* The main operations are:
* getRandomMutation - Randomly selects and builds a mutation.
*
* @author qhanam
*/
public class MutationContext {
private HashMap<String, DocumentASTRewrite> sourceFileContents;
private Statements faultyStatements;
private Statements seedStatements;
private Random random;
/**
* Create a new MutationContext object.
* @param sourceFileContents The map of source file names to their DocumentASTRewriter.
* @param faultyStatements The list of faulty statements to mutate.
* @param seedStatements The list of seed statements to mutate with.
* @param random The random number generator (for random statement selection).
*/
public MutationContext(HashMap<String, DocumentASTRewrite> sourceFileContents,
Statements faultyStatements, Statements seedStatements,
Random random){
this.sourceFileContents = sourceFileContents;
this.faultyStatements = faultyStatements;
this.seedStatements = seedStatements;
this.random = random;
}
/**
* Returns a random mutation operation.
*
* @return A Mutation memento object for applying one mutation to a faulty statement.
*/
public Mutation getRandomMutation(MutationType type) throws Exception {
SourceStatement faultyStatement;
Mutation mutation;
switch(type){
case NULL: // Use for testing (e.g., to make sure the program compiles without mutations).
System.out.print("Applying null mutation...");
mutation = new NullMutation(sourceFileContents, faultyStatements.getRandomStatement(), null);
break;
case ADDITION:
System.out.print("Applying addition mutation...");
faultyStatement = faultyStatements.getRandomStatement();
mutation = new AdditionMutation(sourceFileContents, faultyStatement, seedStatements.getRandomStatement(faultyStatement));
break;
case REPLACEMENT:
System.out.print("Applying replacement mutation...");
faultyStatement = faultyStatements.getRandomStatement();
mutation = new ReplacementMutation(sourceFileContents, faultyStatement, seedStatements.getRandomStatement(faultyStatement));
break;
case DELETION:
System.out.print("Applying deletion mutation...");
mutation = new DeletionMutation(sourceFileContents, faultyStatements.getRandomStatement(), null);
break;
default:
throw new Exception("MutationContext: MutationType not recognised.");
}
return mutation;
}
/**
* Returns a random mutation type.
*
* NOTE: Will never return NULL mutation type.
*
* @return A MutationType that can be passed to getRandomMutation.
*/
public MutationType getRandomMutationType() throws Exception {
return MutationType.values()[(new Double(Math.ceil((this.random.nextDouble() * (MutationType.values().length - 1))))).intValue()];
}
public enum MutationType {
NULL, // Must be manually selected (won't be selected randomly in getRandomMutation)
ADDITION,
REPLACEMENT,
DELETION
}
}