package fr.inria.diversify.sosie;
import fr.inria.diversify.diversification.InputProgram;
import fr.inria.diversify.transformation.Transformation;
import fr.inria.diversify.transformation.TransformationJsonParser;
import fr.inria.diversify.transformation.TransformationParserException;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Collection;
import java.util.Properties;
/**
* A class to create a pool of sosies from a transformation directory
* <p/>
* Created by marodrig on 19/06/2014.
*/
public class SosiePoolCreator {
InputProgram inputProgram;
private Properties properties;
public Properties getProperties() {
return properties;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
public SosiePoolCreator(InputProgram inputProgram) {
this.inputProgram = inputProgram;
setProperties(new Properties());
//Collecto only sosies, this is for the parser and should not be
getProperties().setProperty("status", "0");
//Types fo transformations that we want by default
getProperties().setProperty("type", "adrStmt");
//Names of the transformations that we want by default
getProperties().setProperty("name", "replace replaceRandom replaceReaction replaceWittgenstein replaceSteroid delete");
}
/**
* Test if two transformations defined by their JSONObjects are equals
*
* @param a A transformation defined by a JSONObject
* @param b Another transformation defined by a JSONObject
* @return True if they are equals
*/
private boolean different(JSONObject a, JSONObject b) throws JSONException {
boolean result = a.get("position").equals(b.get("position")) &&
a.get("sourceCode").equals(b.get("sourceCode")) &&
a.get("type").equals(b.get("type"));
return !result;
}
/**
* Clean the sosies to avoid repreated sosies
*
* @param sosies
*/
private JSONArray cleanRepeated(JSONArray sosies) throws JSONException {
JSONArray nonRepeated = new JSONArray();
int index = 0;
for (int i = 0; i < sosies.length(); i++) {
boolean insert = true;
JSONObject a = sosies.getJSONObject(i);
JSONObject pa = a.getJSONObject("transplantationPoint");
JSONObject ta = a.has("transplant") ? a.getJSONObject("transplant") : null;
//Test that the Transplantation Point and the Transplantation are different
if (ta == null || different(pa, ta)) {
for (int j = 0; j < nonRepeated.length() && insert; j++) {
JSONObject b = nonRepeated.getJSONObject(j);
insert = different(
a.getJSONObject("transplantationPoint"),
b.getJSONObject("transplantationPoint"));
insert = insert || (a.has("transplant") != b.has("transplant"));
if (!insert && a.has("transplant")) {
insert = different(
a.getJSONObject("transplant"),
b.getJSONObject("transplant"));
}
}
}
if (insert) {
JSONObject obj = sosies.getJSONObject(i);
index++;
obj.put("tindex", index);
nonRepeated.put(sosies.get(i));
}
}
return nonRepeated;
}
/**
* Creates the pool of transformations
*/
public void create(String outputFile) throws TransformationParserException {
try {
//Check that all what we need is OK to fetch the transformations
if (inputProgram.getPreviousTransformationsPath() == null) {
throw new RuntimeException("Input program has no previous transformation information");
}
TransformationJsonParser parser = new TransformationJsonParser(false, inputProgram);
//Collecto only sosies, this is for the parser and should not be changed.
// Overwrite in case the user has changed this.
getProperties().setProperty("status", "0");
parser.setFilterProperties(properties);
Collection<Transformation> ts;
File f = new File(inputProgram.getPreviousTransformationsPath());
if (f.isDirectory()) {
ts = parser.parseDir(inputProgram.getPreviousTransformationsPath());
} else {
ts = parser.parseFile(f);
}
int index = 0;
JSONArray array = new JSONArray();
for (Transformation t : ts) {
//Allow only sosies
if (t.isSosie()) {
//Avoid repeated transformations
boolean unique = true;
JSONObject transJson = t.toJSONObject();
while (unique && array.length() > index) {
unique = !transJson.toString().equals(array.getJSONObject(index).toString());
index++;
}
String type = getProperties().getProperty("type", "");
String names = getProperties().getProperty("name", "");
if (unique &&
(type.equals("") || transJson.get("type").equals(type)) &&
(names.equals("") || names.contains((String) transJson.get("name")))) {
array.put(transJson);
transJson.put("tindex", index);
index++;
}
}
}
FileWriter fw = new FileWriter(outputFile);
JSONArray noRepeated = cleanRepeated(array);
noRepeated.write(fw);
fw.close();
} catch (JSONException | IOException e) {
throw new TransformationParserException(e);
}
}
}