package com.plectix.simulator.staticanalysis.contactmap;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import com.plectix.simulator.interfaces.ConnectedComponentInterface;
import com.plectix.simulator.interfaces.SolutionInterface;
import com.plectix.simulator.simulationclasses.solution.SuperSubstance;
import com.plectix.simulator.simulator.KappaSystem;
import com.plectix.simulator.staticanalysis.Agent;
import com.plectix.simulator.staticanalysis.Rule;
import com.plectix.simulator.staticanalysis.Site;
import com.plectix.simulator.staticanalysis.abstracting.AbstractAgent;
import com.plectix.simulator.staticanalysis.abstracting.AbstractLinkState;
import com.plectix.simulator.staticanalysis.abstracting.AbstractSite;
import com.plectix.simulator.staticanalysis.subviews.base.AbstractionRule;
import com.plectix.simulator.staticanalysis.subviews.storage.SubViewsInterface;
import com.plectix.simulator.util.NameDictionary;
public final class ContactMapAbstractSolution {
private final Map<String, AbstractAgent> agentNameToAgent;
private final Map<String, List<AbstractAgent>> agentNameToAgents;
private final Map<String, Boolean> agentsMap;
private final Map<String, Map<String, List<ContactMapAbstractEdge>>> edgesInContactMap;
private final Map<String, Map<String, ContactMapChangedSite>> agentsInContactMap;
private final KappaSystem kappaSystem;
public ContactMapAbstractSolution(KappaSystem kappaSystem) {
this.agentNameToAgent = new LinkedHashMap<String, AbstractAgent>();
this.agentNameToAgents = new LinkedHashMap<String, List<AbstractAgent>>();
this.agentsMap = new LinkedHashMap<String, Boolean>();
this.edgesInContactMap = new LinkedHashMap<String, Map<String, List<ContactMapAbstractEdge>>>();
this.agentsInContactMap = new LinkedHashMap<String, Map<String, ContactMapChangedSite>>();
this.kappaSystem = kappaSystem;
Collection<Agent> agents = getSolutionAgents();
fillModelMapOfAgents(agents);
fillAgentMap(agents);
}
private final Collection<Agent> getSolutionAgents() {
Collection<Agent> agents = new ArrayList<Agent>();
SolutionInterface solution = kappaSystem.getSolution();
if (solution.getStraightStorage() != null) {
agents.addAll(solution.getStraightStorage().getAgents());
}
if (solution.getSuperStorage() != null) {
for (SuperSubstance substance : solution.getSuperStorage()
.getComponents()) {
agents.addAll(substance.getComponent().getAgents());
}
}
return agents;
}
private final void addToEdgesAndAgentsMap(AbstractAgent agent) {
String agentKey = agent.getName();
Map<String, ContactMapChangedSite> sitesMap = this.agentsInContactMap
.get(agentKey);
fillMaps(null, agent, agentKey, sitesMap);
if (agent.getSitesMap().isEmpty()) {
if (sitesMap == null) {
sitesMap = new LinkedHashMap<String, ContactMapChangedSite>();
ContactMapChangedSite changedSite = new ContactMapChangedSite(
agent.getDefaultSite());
sitesMap.put(Site.DEFAULT_NAME, changedSite);
this.agentsInContactMap.put(agentKey, sitesMap);
}
}
}
private final void addToEdgesAndAgentsMap(Integer ruleId,
AbstractAgent agent) {
String agentKey = agent.getName();
Map<String, ContactMapChangedSite> sitesMap = this.agentsInContactMap
.get(agentKey);
fillMaps(ruleId, agent, agentKey, sitesMap);
}
private void fillMaps(Integer ruleId, AbstractAgent agent, String agentKey,
Map<String, ContactMapChangedSite> sitesMap) {
Map<String, List<ContactMapAbstractEdge>> edgesMap = this.edgesInContactMap
.get(agentKey);
for (AbstractSite site : agent.getSitesMap().values()) {
String targetSiteName = site.getLinkState().getConnectedSiteName();
String siteKey = site.getName();
if (!NameDictionary.isDefaultSiteName(targetSiteName)) {
edgesMap = putToEdgesInContactMap(ruleId, agentKey, edgesMap,
site, siteKey);
}
ContactMapChangedSite changedSite;
if (sitesMap == null) {
sitesMap = new LinkedHashMap<String, ContactMapChangedSite>();
changedSite = new ContactMapChangedSite(site);
sitesMap.put(siteKey, changedSite);
this.agentsInContactMap.put(agentKey, sitesMap);
} else {
changedSite = sitesMap.get(siteKey);
if (changedSite == null) {
changedSite = new ContactMapChangedSite(site);
sitesMap.put(siteKey, changedSite);
} else {
changedSite.setInternalState(site);
changedSite.setLinkState(site);
}
}
if (ruleId != null) {
changedSite.addRules(ruleId);
}
}
}
private Map<String, List<ContactMapAbstractEdge>> putToEdgesInContactMap(
Integer ruleId, String agentKey,
Map<String, List<ContactMapAbstractEdge>> edgesMap,
AbstractSite site, String siteKey) {
if (edgesMap == null) {
edgesMap = new LinkedHashMap<String, List<ContactMapAbstractEdge>>();
List<ContactMapAbstractEdge> edgeList = new ArrayList<ContactMapAbstractEdge>();
ContactMapAbstractEdge edge = new ContactMapAbstractEdge(site);
edgeList.add(edge);
edgesMap.put(siteKey, edgeList);
this.edgesInContactMap.put(agentKey, edgesMap);
if (ruleId != null) {
edge.addRules(ruleId);
}
} else {
List<ContactMapAbstractEdge> edgeList = edgesMap.get(siteKey);
if (edgeList == null) {
edgeList = new ArrayList<ContactMapAbstractEdge>();
edgesMap.put(siteKey, edgeList);
}
ContactMapAbstractEdge edge = new ContactMapAbstractEdge(site);
boolean wasInList = false;
for (ContactMapAbstractEdge checkedEdge : edgeList) {
if (edge.equalz(checkedEdge)) {
if (ruleId != null) {
checkedEdge.addRules(ruleId);
}
wasInList = true;
break;
}
}
if (!wasInList) {
edgeList.add(edge);
if (ruleId != null) {
edge.addRules(ruleId);
}
}
}
return edgesMap;
}
private final void fillModelMapOfAgents(Collection<Agent> agents) {
fillModelMapByAgentList(agents);
for (Rule rule : kappaSystem.getRules()) {
for (ConnectedComponentInterface cc : rule.getLeftHandSide())
fillModelMapByAgentList(cc.getAgents());
if (rule.getRightHandSide() != null)
for (ConnectedComponentInterface cc : rule.getRightHandSide())
fillModelMapByAgentList(cc.getAgents());
}
}
private final void fillModelMapByAgentList(Collection<Agent> agents) {
for (Agent agent : agents) {
AbstractAgent modelAgent = agentNameToAgent.get(agent.getName());
if (modelAgent == null) {
modelAgent = new AbstractAgent(agent.getName());
agentNameToAgent.put(agent.getName(), modelAgent);
}
for (Site s : agent.getSites()) {
AbstractSite as = new AbstractSite(s);
as.setParentAgent(modelAgent);
modelAgent.addModelSite(as);
}
}
}
private final void fillAgentMap(Collection<Agent> agents) {
for (Agent agent : agents) {
AbstractAgent abstractAgent = new AbstractAgent(agent,
this.agentNameToAgent.get(agent.getName()));
addAgentToAgentsMap(abstractAgent);
}
}
final boolean addAgentToAgentsMap(AbstractAgent abstractAgent) {
String key = abstractAgent.getKey();
if (agentsMap.get(key) == null) {
List<AbstractAgent> agentsFromSolution = agentNameToAgents
.get(abstractAgent.getName());
if (agentsFromSolution == null) {
agentsFromSolution = new ArrayList<AbstractAgent>();
agentNameToAgents.put(abstractAgent.getName(),
agentsFromSolution);
}
agentsFromSolution.add(abstractAgent);
agentsMap.put(key, true);
} else
return false;
addToEdgesAndAgentsMap(abstractAgent);
return true;
}
final void addAgentsBoundedWithFocusedAgent(AbstractAgent agent,
List<AbstractAgent> agentsFromRule) {
for (AbstractAgent ruleAgent : agentsFromRule) {
Map<String, AbstractSite> sitesMapFromRule = ruleAgent
.getSitesMap();
for (AbstractSite siteFromRule : sitesMapFromRule.values()) {
AbstractLinkState ls = siteFromRule.getLinkState();
if (ls.getAgentName().equals(agent.getName())
|| ruleAgent.getName().equals(agent.getName()))
addAgentToAgentsMap(ruleAgent);
}
}
}
public final void addData(List<SubViewsInterface> subViews) {
for (SubViewsInterface subView : subViews) {
List<AbstractAgent> list = subView.getAllSubViews();
LinkedHashSet<Integer> listOfRules = subView.getSubViewClass()
.getRulesId();
for (AbstractAgent a : list) {
if (addAgentToAgentsMap(a)) {
for (Integer ruleId : listOfRules) {
addToEdgesAndAgentsMap(ruleId, a);
}
}
}
}
}
/**
* Util method. Construct abstract contact map by given rules for guiven
* agents
*
* @param rules
* given rules
* @param addAgentList
* given agents
*/
final void constructAbstractCard(List<Rule> rules,
Collection<AbstractAgent> addAgentList) {
if (addAgentList == null) {
addAgentList = getAgentNameToAgent().values();
}
for (AbstractAgent agent : addAgentList)
addAgentToAgentsMap(agent);
for (Rule rule : rules) {
List<AbstractAgent> agentsFromRule = fillAgentsFromRule(rule);
for (AbstractAgent agent : addAgentList)
if (agent.includedInCollectionByName(agentsFromRule)) {
addAgentsBoundedWithFocusedAgent(agent, agentsFromRule);
}
}
}
/**
* Util method. Clears unnecessary information in contact map.
*
* @param agentNames
*/
public final void clearCard(Collection<String> agentNames) {
List<String> namesOfAgentsToDelete = new ArrayList<String>();
for (String key : agentNameToAgents.keySet()) {
if (!agentNames.contains(key)) {
namesOfAgentsToDelete.add(key);
edgesInContactMap.remove(key);
agentsInContactMap.remove(key);
}
}
for (String name : namesOfAgentsToDelete) {
agentNameToAgents.remove(name);
}
}
/**
* Util method. Fills given agents to given rule.
*
* @param rule
* given rule
* @param agents
* given agents
* @return
*/
private final List<AbstractAgent> fillAgentsFromRule(Rule rule) {
List<AbstractAgent> agents = new ArrayList<AbstractAgent>();
AbstractionRule abstractRule = new AbstractionRule(rule);
// TODO hren
if (!rule.getLeftHandSide().get(0).isEmpty()) {
for (AbstractAgent agent : abstractRule.getLeftHandSideAgents()) {
if (!agent.includedInCollection(agents)) {
agents.add(agent);
}
}
}
for (AbstractAgent agent : abstractRule.getRightHandSideAgents()) {
if (!agent.includedInCollection(agents)) {
agents.add(agent);
}
}
return agents;
}
public void addAllRules(List<Rule> rules) {
for (Rule r : rules) {
for (AbstractAgent agent : fillAgentsFromRule(r)) {
if (addAgentToAgentsMap(agent)) {
addToEdgesAndAgentsMap(r.getRuleId(), agent);
}
}
}
}
// =====================================
// getters and setters
public final Map<String, Map<String, List<ContactMapAbstractEdge>>> getEdgesInContactMap() {
return edgesInContactMap;
}
public final Map<String, AbstractAgent> getAgentNameToAgent() {
return agentNameToAgent;
}
public final Map<String, Map<String, ContactMapChangedSite>> getAgentsInContactMap() {
return agentsInContactMap;
}
public final Map<String, List<AbstractAgent>> getAgentNameToAgentsList() {
return agentNameToAgents;
}
}