package com.plectix.simulator.io.xml;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import javax.xml.stream.XMLStreamException;
import com.plectix.simulator.io.SimulationDataOutputUtil;
import com.plectix.simulator.simulator.KappaSystem;
import com.plectix.simulator.staticanalysis.Rule;
import com.plectix.simulator.staticanalysis.rulecompression.CompressionResults;
import com.plectix.simulator.staticanalysis.rulecompression.RuleCompressionType;
import com.plectix.simulator.staticanalysis.subviews.MainSubViews;
// it should stay public for a while, this is not good =(
public class RuleCompressionXMLWriter {
private static final class RuleMapping {
private Map<Integer, Integer> association = new TreeMap<Integer, Integer>();
private final Map<Integer, List<Integer>> inverseAssociation
= new LinkedHashMap<Integer, List<Integer>>();
public final int getData(int key) {
return association.get(key);
}
public final Map<Integer, Integer> getData() {
return association;
}
public final List<Integer> getInverseData(int key) {
return inverseAssociation.get(key);
}
public final void put(int key, int value) {
association.put(key, value);
List<Integer> list = inverseAssociation.get(value);
if (list == null) {
list = new LinkedList<Integer>();
inverseAssociation.put(value, list);
}
list.add(key);
}
}
private final Map<Integer, Rule> initialRulesMap = new LinkedHashMap<Integer, Rule>();
private final Map<RuleCompressionType, RuleMapping> associations
= new TreeMap<RuleCompressionType, RuleMapping>();
private final Map<RuleCompressionType, Set<Rule>> compressedRules
= new LinkedHashMap<RuleCompressionType, Set<Rule>>();
private final KappaSystem kappaSystem;
//TODO do adequate data structure for those results
private Map<CompressionResults, MainSubViews> compressionResults
= new HashMap<CompressionResults, MainSubViews>();
public RuleCompressionXMLWriter(KappaSystem ks) {
this.kappaSystem = ks;
}
public void addData(CompressionResults results, MainSubViews newSubViews) {
compressionResults.put(results, newSubViews);
for (Rule rule : kappaSystem.getRules()) {
this.initialRulesMap.put(rule.getRuleId(), rule);
}
Set<Rule> rulesAfterCompression = new LinkedHashSet<Rule>();
RuleMapping ruleMapping = new RuleMapping();
this.associations.put(results.getCompressionType(), ruleMapping);
for (Map.Entry<Rule, Rule> associationEntry : results.getAssociations()) {
int idRealRule = associationEntry.getKey().getRuleId();
int idCompressedRule = associationEntry.getValue().getRuleId();
ruleMapping.put(idRealRule, idCompressedRule);
rulesAfterCompression.add(associationEntry.getValue());
}
compressedRules.put(results.getCompressionType(), rulesAfterCompression);
}
public void writeToXML(OurXMLWriter xtw, boolean isOcamlStyleObsName)
throws XMLStreamException {
writeToXMLInitialRules(xtw,isOcamlStyleObsName);
for (Map.Entry<CompressionResults, MainSubViews> entry : this.compressionResults.entrySet()) {
RuleCompressionType currentCompressionType = entry.getKey().getCompressionType();
xtw.writeStartElement("RuleSet");
xtw.writeAttribute("Name", currentCompressionType + " compression");
writeToXMLQualitativeRules(xtw, isOcamlStyleObsName, entry.getValue(), currentCompressionType);
writeToXMLAssociationQualitativeMap(xtw, currentCompressionType);
xtw.writeEndElement();
}
}
private void writeToXMLInitialRules(OurXMLWriter xtw, boolean isOcamlStyleObsName) throws XMLStreamException{
xtw.writeStartElement("RuleSet");
xtw.writeAttribute("Name", "Original");
for(Rule rule : initialRulesMap.values()){
//<Rule Id="1" Name="Rule1" Data="R(l,r),E(r)->R(l!0,r),E(r!0)" ForwardRate="1"/>
xtw.writeStartElement("Rule");
xtw.writeAttribute("Id", Integer.valueOf(rule.getRuleId()+1).toString());
xtw.writeAttribute("ForwardRate", Double.valueOf(rule.getRate()).toString());
String name = rule.getName();
String data = SimulationDataOutputUtil.getData(rule,isOcamlStyleObsName);
if(name == null)
name = data;
xtw.writeAttribute("Name", name);
xtw.writeAttribute("Data", data);
xtw.writeEndElement();
}
xtw.writeEndElement();
}
private void writeToXMLAssociationQualitativeMap(OurXMLWriter xtw, RuleCompressionType compressionType)
throws XMLStreamException{
xtw.writeStartElement("Map");
xtw.writeAttribute("FromSet", "Original");
for(Map.Entry<Integer, Integer> entry : associations.get(compressionType).getData().entrySet()){
xtw.writeStartElement("Association");
xtw.writeAttribute("FromRule", Integer.toString(entry.getKey()+1));
xtw.writeAttribute("ToRule", entry.getValue().toString());
xtw.writeEndElement();
}
xtw.writeEndElement();
}
private void writeToXMLQualitativeRules(OurXMLWriter xtw, boolean isOcamlStyleObsName,
MainSubViews subViews, RuleCompressionType currentCompressionType)
throws XMLStreamException {
for (Rule rule : compressedRules.get(currentCompressionType)) {
xtw.writeStartElement("Rule");
Integer id = rule.getRuleId();
xtw.writeAttribute("Id", id.toString());
if(subViews.getDeadRules().contains(id))
xtw.writeAttribute("Data", "Cannot be applied");
else{
xtw.writeAttribute("ForwardRate", Double.valueOf(rule.getRate()).toString());
xtw.writeAttribute("Data", SimulationDataOutputUtil.getData(rule,isOcamlStyleObsName));
}
StringBuffer sb = new StringBuffer();
List<Integer> list = associations.get(currentCompressionType).getInverseData(id);
int size = list.size();
int counter = 1;
for (Integer key : list) {
Rule initRule = initialRulesMap.get(key);
String name = initRule.getName();
if (name != null)
sb.append(name);
else
sb.append(SimulationDataOutputUtil.getData(rule,isOcamlStyleObsName));
if(counter != size)
sb.append(",");
counter++;
}
xtw.writeAttribute("Name", sb.toString());
xtw.writeEndElement();
}
}
public CompressionResults getResults(RuleCompressionType type) {
for (CompressionResults results : compressionResults.keySet()) {
if (results.getCompressionType() == type) {
return results;
}
}
return null;
}
}