package fr.inria.diversify.persistence.json.input;
import fr.inria.diversify.diversification.InputProgram;
import fr.inria.diversify.persistence.Header;
import fr.inria.diversify.persistence.PersistenceException;
import fr.inria.diversify.transformation.Transformation;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
/**
* Created by marodrig on 09/01/2015.
*/
public class JsonSosiesInput {
public static final String ERROR = "ERROR :";
public static final String WARNING = "WARNING:";
public static final String INFO = "INFO :";
public static final String DEBUG = "DEBUG :";
private String jsonPath;
private InputStreamReader streamReader;
/**
* JSON Object loaded
*/
private JSONObject jsonObject;
/**
* Input program to obtain the code fragments for the transformations
*/
private InputProgram inputProgram;
/**
* Errors from the reader
*/
private List<String> loadMessages;
/**
* Header from the reader
*/
private Header header;
/**
* Visibles section for reading customization
*/
private HashMap<String, JsonSectionInput> sections;
public JsonSosiesInput() {
initSections();
}
public JsonSosiesInput(InputStreamReader r, InputProgram inputProgram) {
this("", inputProgram);
this.setStreamReader(r);
}
public JsonSosiesInput(String jsonPath, InputProgram inputProgram) {
this.setJsonPath(jsonPath);
this.inputProgram = inputProgram;
initSections();
}
/**
* Sets a section in the list of sections.
* There is only one section per class in the output object
* @param section Output Section to be set
*/
public void setSection(Class<? extends JsonSectionInput> aClass, JsonSectionInput section) {
sections.put(aClass.getName(), section);
}
/**
* Get the section from the list
* @param aClass
* @return
*/
public JsonSectionInput getSection(Class<? extends JsonSectionInput> aClass){
return sections.get(aClass.getName());
}
protected void open() {
BufferedReader br = null;
try {
if ( getStreamReader() == null ) setStreamReader(new FileReader(getJsonPath()));
br = new BufferedReader(getStreamReader());
StringBuilder sb = new StringBuilder();
String line = br.readLine();
while (line != null) {
sb.append(line);
line = br.readLine();
}
if (sb.length() == 0) throw new PersistenceException("Empty JSON. No lines to read");
jsonObject = null;
try {
jsonObject = new JSONObject(sb.toString());
} catch (JSONException e) {
throw new PersistenceException("Unable to parse text into JSON file", e);
}
} catch (IOException e) {
throw new PersistenceException("Unable to parse text file into JSON file", e);
} finally {
if (br != null) try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* Init all sections in the input
*/
private void initSections() {
sections = new HashMap<>();
setSection(JsonFailuresInput.class, new JsonFailuresInput(inputProgram, jsonObject));
setSection(JsonAstTransformationCollectionInput.class,
new JsonAstTransformationCollectionInput(inputProgram, jsonObject));
setSection(JsonHeaderInput.class, new JsonHeaderInput(inputProgram, jsonObject));
}
/**
* Read the transformations from the JSON file
* @return A collection the transformations
* @throws fr.inria.diversify.persistence.PersistenceException in case the read has to many errors
*/
public Collection<Transformation> read() {
open(); //Open the json file
HashMap<UUID, Transformation> result = new HashMap<>();
JsonHeaderInput headerInput = (JsonHeaderInput)getSection(JsonHeaderInput.class);
headerInput.setJsonObject(jsonObject);
headerInput.setInputProgram(inputProgram);
headerInput.setLoadMessages(getLoadMessages());
headerInput.read(result);
header = headerInput.getHeader();
JsonFailuresInput failures = (JsonFailuresInput) getSection(JsonFailuresInput.class);
failures.setJsonObject(jsonObject);
failures.setInputProgram(inputProgram);
failures.setLoadMessages(getLoadMessages());
failures.read(result);
JsonAstTransformationCollectionInput asts = (JsonAstTransformationCollectionInput)
getSection(JsonAstTransformationCollectionInput.class);
asts.setJsonObject(jsonObject);
asts.setInputProgram(inputProgram);
asts.setLoadMessages(getLoadMessages());
asts.setFailures(failures.getFailures());
asts.read(result);
for ( JsonSectionInput s : sections.values() ) {
if ( s.equals(headerInput) || s.equals(failures) || s.equals(asts) ) continue;
s.setInputProgram(inputProgram);
s.setJsonObject(jsonObject);
s.read(result);
}
return result.values();
}
public void setInputProgram(InputProgram inputProgram) {
this.inputProgram = inputProgram;
}
/**
* Input program to obtain the code fragments for the transformations
*/
public InputProgram getInputProgram() {
return inputProgram;
}
/**
* Errors during the loading process
* @return
*/
public List<String> getLoadMessages() {
if ( loadMessages == null ) loadMessages = new ArrayList<>();
return loadMessages;
}
public Header getHeader() {
if ( header == null ) throw new PersistenceException("Handler unset. Must call read method first");
return header;
}
/**
* Path of the json file
*/
public String getJsonPath() {
return jsonPath;
}
public void setJsonPath(String jsonPath) {
this.jsonPath = jsonPath;
}
/**
* Stream reader to obtain the JSON text from
*/
public InputStreamReader getStreamReader() {
return streamReader;
}
public void setStreamReader(InputStreamReader streamReader) {
this.streamReader = streamReader;
}
}