package com.plectix.simulator.staticanalysis.subviews.storage;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import com.plectix.simulator.staticanalysis.Agent;
import com.plectix.simulator.staticanalysis.LinkStatus;
import com.plectix.simulator.staticanalysis.StaticAnalysisException;
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.SubViewClass;
import com.plectix.simulator.staticanalysis.subviews.base.AbstractAction;
import com.plectix.simulator.staticanalysis.subviews.base.AbstractActionType;
import com.plectix.simulator.util.NameDictionary;
public class SubViewsLinkedlist implements SubViewsInterface {
private final SubViewClass subViewClass;
private final List<AbstractAgent> storage;
public SubViewsLinkedlist(SubViewClass subViewClass) {
this.subViewClass = subViewClass;
this.storage = new LinkedList<AbstractAgent>();
}
public void fillingInitialState(
Map<String, AbstractAgent> agentNameToAgent,
Collection<Agent> agents) throws StaticAnalysisException {
AbstractAgent defAgent = agentNameToAgent.get(subViewClass
.getAgentType());
AbstractAgent needAgent = new AbstractAgent(defAgent);
for (AbstractSite defSite : defAgent.getSitesMap().values()) {
String siteName = defSite.getName();
if (!subViewClass.hasSite(siteName))
needAgent.getSitesMap().remove(siteName);
}
// storage.add(needAgent);
for (AbstractAgent agent : convertAgentsToAbstract(
getNeedAgentsBySolution(agents), needAgent)) {
addAbstractAgent(agent);
}
}
public boolean addAbstractAgent(AbstractAgent agent) throws StaticAnalysisException
{
if (agent.getSitesMap().size() < subViewClass.getSitesNames().size())
throw new StaticAnalysisException(subViewClass, agent);
if (test(agent))
return false;
storage.add(agent);
return true;
}
public boolean burnRule(AbstractAction action) throws StaticAnalysisException{
AbstractAgent oldViews = action.getLeftHandSideAgent();
AbstractAgent newViews = action.getRightHandSideAgent();
// if (oldViews == null)
// return addAbstractAgent(newViews);
List<AbstractAgent> agentsList;
if (testDeleteAction(action))
agentsList = storage;
else
agentsList = getAllSubViews(oldViews);
initBreakingSites(action, agentsList);
switch (action.getActionType()) {
case ADD:
return addAbstractAgent(newViews.clone());
case TEST_ONLY:
return false;
case DELETE:
return false;
}
boolean isAdd = false;
for (AbstractAgent storageAgent : agentsList) {
AbstractAgent newAgent = storageAgent.clone();
newAgent.addAllStates(newViews);
if (addAbstractAgent(newAgent))
isAdd = true;
}
return isAdd;
}
private boolean testDeleteAction(AbstractAction action) {
if (action.getActionType() != AbstractActionType.DELETE)
return false;
boolean isNotHave = true;
for (AbstractSite site : action.getLeftHandSideAgent().getSitesMap()
.values())
if (subViewClass.hasSite(site.getName()))
return false;
return isNotHave;
}
private void initBreakingSites(AbstractAction action,
List<AbstractAgent> agentsList) {
List<String> sideEffectId = action.getSideEffect();
Map<Integer, AbstractAgent> sideEfectMap = new LinkedHashMap<Integer, AbstractAgent>();
switch (action.getActionType()) {
case DELETE: {
for (AbstractAgent agent : agentsList)
for (AbstractSite site : agent.getSitesMap().values())
initSideEffectSite(site, agent, sideEfectMap, action);
break;
}
case TEST_AND_MODIFICATION: {
if (sideEffectId == null)
return;
for (AbstractAgent agent : agentsList)
for (String siteName : sideEffectId) {
AbstractSite site = agent.getSiteByName(siteName);
initSideEffectSite(site, agent, sideEfectMap, action);
}
break;
}
}
}
private void initSideEffectSite(AbstractSite site, AbstractAgent agent,
Map<Integer, AbstractAgent> sideEfectMap, AbstractAction action) {
AbstractLinkState linkState = site.getLinkState();
if (!NameDictionary.isDefaultAgentName(linkState.getAgentName())) {
String newAgentName = linkState.getAgentName();
String newSiteName = linkState.getConnectedSiteName();
int hashValue = generateHash(newAgentName, newSiteName, agent
.getName(), site.getName());
if (sideEfectMap.get(hashValue) == null) {
AbstractAgent newAgent = createSideEffectAgent(newAgentName,
newSiteName, agent.getName(), site.getName());
sideEfectMap.put(hashValue, newAgent);
action.addSiteSideEffect(newAgent.getSiteByName(newSiteName));
}
}
}
private static AbstractAgent createSideEffectAgent(String agentName,
String siteName, String linkAgentName, String linkSiteName) {
AbstractAgent newAgent = new AbstractAgent(agentName);
AbstractSite newSite = new AbstractSite(newAgent, siteName);
newSite.getLinkState().setAgentName(linkAgentName);
newSite.getLinkState().setLinkSiteName(linkSiteName);
newSite.getLinkState().setStatusLink(LinkStatus.BOUND);
newAgent.addSite(newSite);
return newAgent;
}
private static int generateHash(String agentName, String siteName,
String linkAgentName, String linkSiteName) {
int hashValue = 11;
hashValue = 31 * hashValue + agentName.hashCode();
hashValue = 31 * hashValue + siteName.hashCode();
hashValue = 31 * hashValue + linkAgentName.hashCode();
hashValue = 31 * hashValue + linkSiteName.hashCode();
return hashValue;
}
public boolean test(AbstractAction action) throws StaticAnalysisException {
AbstractAgent agent = action.getLeftHandSideAgent();
if (agent == null)
return true;
return test(agent);
}
public boolean test(AbstractAgent testView) throws StaticAnalysisException {
if (!testView.getName().equals(subViewClass.getAgentType()))
throw new StaticAnalysisException(subViewClass, testView);
boolean isHave = false;
if (testView.getSitesMap().isEmpty())
if (!storage.isEmpty()) {
return true;
} else
return false;
for (AbstractSite site : testView.getSitesMap().values())
if (subViewClass.hasSite(site.getName()))
isHave = true;
if (!isHave)
throw new StaticAnalysisException(subViewClass, testView);
for (AbstractAgent aAgent : storage) {
isHave = true;
for (AbstractSite site : testView.getSitesMap().values()) {
String siteName = site.getName();
// if (!aAgent.getSite(siteId).isFit(site)) {
if ((subViewClass.hasSite(siteName))
&& (!site.isFit(aAgent.getSiteByName(siteName)))) {
isHave = false;
break;
}
}
if (isHave)
return true;
}
return false;
}
public List<AbstractAgent> getAllSubViews() {
return storage;
}
public List<AbstractAgent> getAllSubViews(AbstractAgent view) {
List<AbstractAgent> outList = new LinkedList<AbstractAgent>();
if (view == null || !view.getName().equals(subViewClass.getAgentType()))
return outList;
if (view.getSitesMap().isEmpty())
return storage;
for (AbstractAgent aAgent : storage) {
boolean isHave = false;
for (AbstractSite site : view.getSitesMap().values()) {
// if (!aAgent.getSite(site.getName()).isFit(site)) {
String siteName = site.getName();
if (subViewClass.hasSite(siteName)) {
if (site.isFit(aAgent.getSiteByName(siteName)))
isHave = true;
else {
isHave = false;
break;
}
}
}
if (isHave)
outList.add(aAgent);
}
return outList;
}
// ==========================================================================
private List<AbstractAgent> convertAgentsToAbstract(List<Agent> agents,
AbstractAgent fillingAgent) {
List<AbstractAgent> outlist = new LinkedList<AbstractAgent>();
for (Agent agent : agents) {
AbstractAgent needAgent = fillingAgent.clone();
needAgent.addAllStates(agent);
// for (CAbstractSite aSite : needAgent.getSitesMap().values())
// aSite.addStates(agent.getSiteById(aSite.getName()));
outlist.add(needAgent);
}
return outlist;
}
private List<Agent> getNeedAgentsBySolution(Collection<Agent> agents) {
List<Agent> outList = new LinkedList<Agent>();
for (Agent a : agents)
if (a.getName().equals(subViewClass.getAgentType()))
outList.add(a);
return outList;
}
public boolean isAgentFit(AbstractAgent agent) {
for (AbstractSite site : agent.getSitesMap().values())
if (!subViewClass.hasSite(site.getName()))
return false;
return true;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof SubViewClass))
return false;
SubViewClass inClass = (SubViewClass) obj;
if (!subViewClass.equals(inClass))
return false;
return true;
}
@Override
public int hashCode() {
return subViewClass.hashCode();
}
@Override
public String toString() {
return subViewClass.toString();
}
public boolean burnBreakAllNeedLinkState(AbstractAction action) throws StaticAnalysisException {
List<AbstractSite> breakingSites = action.getSitesSideEffect();
List<AbstractAgent> addlist = new LinkedList<AbstractAgent>();
if (breakingSites == null)
return false;
for (AbstractSite site : breakingSites) {
if (!site.getParentAgent().getName().equals(subViewClass
.getAgentType()))
continue;
for (AbstractAgent storageAgent : storage) {
AbstractSite siteFromStorage = storageAgent.getSiteByName(site
.getName());
// if (site.equalz(siteFromStorage)) {
if (siteFromStorage != null && site.isFit(siteFromStorage)) {
AbstractAgent newAgent = new AbstractAgent(storageAgent);
newAgent.getSiteByName(site.getName()).getLinkState()
.setFreeLinkState();
addlist.add(newAgent);
}
}
}
boolean isAdd = false;
for (AbstractAgent agent : addlist) {
if (addAbstractAgent(agent))
isAdd = true;
}
return isAdd;
}
public SubViewClass getSubViewClass() {
return subViewClass;
}
public List<AbstractAgent> getAllSubViewsCoherent(AbstractAgent view) {
List<AbstractAgent> outList = new LinkedList<AbstractAgent>();
if (view == null || view.getSitesMap().isEmpty())
return storage;
for (AbstractAgent aAgent : storage) {
boolean isHave = true;
for (AbstractSite site : view.getSitesMap().values()) {
String siteName = site.getName();
if (subViewClass.hasSite(siteName)
&& !site.isFit(aAgent.getSiteByName(siteName))) {
isHave = false;
}
}
if (isHave)
outList.add(aAgent.summon(view));
}
return outList;
}
@Override
public boolean isEmpty() {
return storage.isEmpty();
}
}