package com.plectix.simulator.staticanalysis.rulecompression;
import java.util.ArrayList;
import java.util.HashSet;
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 com.plectix.simulator.interfaces.ConnectedComponentInterface;
import com.plectix.simulator.staticanalysis.Agent;
import com.plectix.simulator.staticanalysis.Rule;
import com.plectix.simulator.staticanalysis.Site;
import com.plectix.simulator.util.NameDictionary;
/**
* RuleMaster work with one rule. Find all possibilities for roots, find all
* rooted versions and create actionsString for them.
*
*/
public class RuleMaster {
private final Map<Integer, ShadowAgent> mapAfter;
private final Map<Integer, ShadowAgent> mapBefore;
private final Rule rule;
/**
* agent's ids from each of left component in rule
* needs for creating roots sets
*/
private final List<Set<Integer>> leftComponents;
/**
* RuleMaster work with one rule. Find all possibilities for roots, find all
* rooted versions and create actionsString for them.
*
* @param rule
*/
public RuleMaster(Rule rule) {
this.rule = rule;
mapAfter = new LinkedHashMap<Integer, ShadowAgent>();
mapBefore = new LinkedHashMap<Integer, ShadowAgent>();
leftComponents = new LinkedList<Set<Integer>>();
for (ConnectedComponentInterface cc : rule.getLeftHandSide()) {
Set<Integer> ids = new LinkedHashSet<Integer>();
for (ShadowAgent sa : RuleCompressionUtils
.shadowClone((ArrayList<Agent>) cc.getAgents())) {
if (NameDictionary.isDefaultAgentName(sa.getName()))
continue;
mapBefore.put(sa.getIdInRuleHandside(), sa);
ids.add(sa.getIdInRuleHandside());
}
if (!ids.isEmpty())
leftComponents.add(ids);
}
if (rule.getRightHandSide() != null) {
for (ConnectedComponentInterface cc : rule.getRightHandSide()) {
for (ShadowAgent sa : RuleCompressionUtils
.shadowClone((ArrayList<Agent>) cc.getAgents())) {
mapAfter.put(sa.getIdInRuleHandside(), sa);
}
}
}
findActionAgents();
}
/**
* find agents changed by this rule (in leftside or added agents in
* rigthside)
*/
private void findActionAgents() {
for (Integer i : mapAfter.keySet()) {
if (mapBefore.get(i) == null) {
mapAfter.get(i).setActionAgent();
}
}
for (Integer i : mapBefore.keySet()) {
ShadowAgent shadowAgentBefore = mapBefore.get(i);
ShadowAgent shadowAgentAfter = mapAfter.get(i);
if (shadowAgentAfter == null) {
shadowAgentBefore.setActionAgent();
continue;
}
for (Site s : shadowAgentBefore.getSites()) {
Site other = shadowAgentAfter.getSiteByName(s.getName());
if (!s.getInternalState().equalz(other.getInternalState())) {
shadowAgentBefore.setActionAgent();
}
if (!s.getLinkState().equalz(other.getLinkState())) {
shadowAgentBefore.setActionAgent();
}
}
}
}
/**
*
* @return all rooted versions of rule
*/
public List<RootedRule> getAllRootedVersions() {
List<RootedRule> rootedRules = new LinkedList<RootedRule>();
List<Set<Integer>> rootsOfComponents = getAllPossibleRoots();
for (Set<Integer> set : rootsOfComponents) {
rootedRules.add(cloneRootedRule(set));
}
return rootedRules;
}
/**
* set roots and create rooted rule
*
* @param set
* of root's ids
* @return
*/
private RootedRule cloneRootedRule(Set<Integer> set) {
RootedRule rr = new RootedRule(mapBefore, mapAfter);
rr.setRule(this.rule);
rr.setRootsAndFullActionInfo(set);
return rr;
}
// ================================================================
// generate roots
/**
* find all possible combination of roots actionAgent from each component,
* all added agents and any agents form tested component
*
* @return
*/
private List<Set<Integer>> getAllPossibleRoots() {
clearComponents();
List<Set<Integer>> answer = new LinkedList<Set<Integer>>();
Set<Integer> imperativeRoots = new LinkedHashSet<Integer>();
answer.add(imperativeRoots);
for (Integer i : mapAfter.keySet()) {
if (mapBefore.get(i) == null) {
imperativeRoots.add(i);
}
}
for (Set<Integer> set : leftComponents) {
answer = RuleCompressionUtils.addAllVariants(answer, set);
}
return answer;
}
/**
* clear leftComponent. If some components contains actionAgents then we
* delete tested agents from them
*/
private void clearComponents() {
for (Set<Integer> component : leftComponents) {
if (!isTest(component)) {
Set<Integer> deleted = new HashSet<Integer>();
for (Integer i : component) {
if (!mapBefore.get(i).isActionAgent()) {
deleted.add(i);
}
}
for (Integer i : deleted) {
component.remove(i);
}
}
}
}
/**
*
* @param component
* @return is this component only test by rule?
*/
private boolean isTest(Set<Integer> component) {
for (Integer i : component) {
if (mapBefore.get(i).isActionAgent()) {
return false;
}
}
return true;
}
// =================================================
// getters and setters
public Rule getRule() {
return rule;
}
public Map<Integer, ShadowAgent> getMapBefore() {
return mapBefore;
}
public Map<Integer, ShadowAgent> getMapAfter() {
return mapAfter;
}
}