package com.plectix.simulator.staticanalysis.speciesenumeration;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import com.plectix.simulator.staticanalysis.Agent;
import com.plectix.simulator.staticanalysis.ConnectedComponent;
import com.plectix.simulator.staticanalysis.InternalState;
import com.plectix.simulator.staticanalysis.Link;
import com.plectix.simulator.staticanalysis.LinkStatus;
import com.plectix.simulator.staticanalysis.Site;
import com.plectix.simulator.staticanalysis.abstracting.AbstractAgent;
import com.plectix.simulator.staticanalysis.abstracting.AbstractSite;
public class Species {
private static final int NOT_INITIALIZE = -1;
// all agents
// numberOfInitiateAgent
// all after numberOfInitiatedAgent with one site
private final List<Agent> instance;
// list of localViews by type of agent
private final Map<String, List<AbstractAgent>> availableListOfViews;
private final String hashCode;
private int numberOfInitiatedAgent;
public Species(Map<String, List<AbstractAgent>> availableListOfViews,
AbstractAgent origin) {
this.availableListOfViews = availableListOfViews;
instance = new ArrayList<Agent>();
numberOfInitiatedAgent = 0;
Agent first = new Agent(origin.getName(), NOT_INITIALIZE);
instance.add(first);
initiateAgent(first, origin);
hashCode = (new ConnectedComponent(instance)).getSmilesString();
}
private Species(ArrayList<Agent> cloneInstance,
Map<String, List<AbstractAgent>> availableListOfViews2,
int numberOfInitiatedAgent2, AbstractAgent mask) {
instance = cloneInstance;
this.availableListOfViews = availableListOfViews2;
numberOfInitiatedAgent = numberOfInitiatedAgent2;
initiateAgent(instance.get(numberOfInitiatedAgent), mask);
hashCode = (new ConnectedComponent(instance)).getSmilesString();
}
// add tentacles (almost empty agents)
private final void propagateTentacles(Agent rootOfPlague, AbstractAgent archetype) {
for (AbstractSite abstractSite : archetype.getSitesMap().values()) {
// agent has the same site
Site old = rootOfPlague.getSiteByName(abstractSite.getName());
if (old != null) {
old.setInternalState(abstractSite.getInternalState());
continue;
}
Site site = new Site(abstractSite.getName(), rootOfPlague);
// set internal state to site from abstract site
if (abstractSite.getInternalState() != InternalState.EMPTY_STATE) {
site.setInternalState(abstractSite.getInternalState());
}
rootOfPlague.addSite(site);
// set link state
if (abstractSite.getLinkState().getStatusLink() == LinkStatus.FREE) {
// site.getLinkState().setStatusLink(CLinkStatus.FREE);
site.getLinkState().setFree();
continue;
}
// if there is link....
Agent linkedAgent = new Agent(abstractSite.getLinkState()
.getAgentName(), NOT_INITIALIZE);
Site linkedSite = new Site(abstractSite.getLinkState()
.getConnectedSiteName(), linkedAgent);
linkedAgent.addSite(linkedSite);
site.getLinkState().connectSite(linkedSite);
linkedSite.getLinkState().connectSite(site);
instance.add(linkedAgent);
}
}
private final void initiateAgent(Agent agent, AbstractAgent archetype) {
if (agent.getId() != NOT_INITIALIZE) {
// TODO FAIL
}
agent.setId(numberOfInitiatedAgent);
numberOfInitiatedAgent++;
propagateTentacles(agent, archetype);
}
public final String getHashCode() {
return hashCode;
}
public final List<Species> propagate() {
if (instance.size() == numberOfInitiatedAgent) {
return null;
}
List<Species> answer = new LinkedList<Species>();
List<AbstractAgent> masks = getMasks(instance
.get(numberOfInitiatedAgent));
// for example this agent doesn't presence
if (masks == null || masks.isEmpty()) {
return null;
}
for (AbstractAgent mask : masks) {
answer.add(clone(this, mask));
}
return answer;
}
private final Species clone(Species species, AbstractAgent mask) {
return new Species(cloneInstance(), availableListOfViews,
numberOfInitiatedAgent, mask);
}
private final ArrayList<Agent> cloneInstance() {
ArrayList<Agent> newAgentsList = new ArrayList<Agent>();
for (Agent agent : instance) {
Agent newAgent = new Agent(agent.getName(), agent.getId());
for (Site site : agent.getSites()) {
Site newSite = new Site(site.getName(), newAgent);
newSite.setLinkIndex(site.getLinkIndex());
newSite.setInternalState(new InternalState(site
.getInternalState().getName()));
newAgent.addSite(newSite);
}
newAgentsList.add(newAgent);
}
for (int i = 0; i < newAgentsList.size(); i++) {
for (Site siteNew : newAgentsList.get(i).getSites()) {
Link lsNew = siteNew.getLinkState();
Link lsOld = instance.get(i).getSiteByName(
siteNew.getName()).getLinkState();
lsNew.setStatusLink(lsOld.getStatusLink());
if (lsOld.getConnectedSite() != null) {
Site siteOldLink = lsOld.getConnectedSite();
int j = 0;
for (; j < instance.size(); j++) {
if (instance.get(j) == siteOldLink.getParentAgent())
break;
}
int index = j;
lsNew.connectSite(newAgentsList.get(index).getSiteByName(
siteOldLink.getName()));
}
}
}
return newAgentsList;
}
private final List<AbstractAgent> getMasks(Agent agent) {
List<AbstractAgent> list = new LinkedList<AbstractAgent>();
AbstractAgent abstractAgent = new AbstractAgent(agent.getName());
abstractAgent.addSite(new AbstractSite(agent.getSites().iterator()
.next(), abstractAgent));
if (availableListOfViews.get(agent.getName()) == null) {
return null;
}
for (AbstractAgent view : availableListOfViews.get(agent.getName())) {
if (abstractAgent.isFit(view)) {
list.add(view);
}
}
return list;
}
public final boolean isComplete() {
return (instance.size() == numberOfInitiatedAgent);
}
}