package com.plectix.simulator.staticanalysis.stories.graphs;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.Map.Entry;
import com.plectix.simulator.staticanalysis.stories.ActionOfAEvent;
import com.plectix.simulator.staticanalysis.stories.TypeOfWire;
import com.plectix.simulator.staticanalysis.stories.compressions.CompressionPassport;
import com.plectix.simulator.staticanalysis.stories.storage.AtomicEvent;
import com.plectix.simulator.staticanalysis.stories.storage.EventInterface;
import com.plectix.simulator.staticanalysis.stories.storage.EventIteratorInterface;
import com.plectix.simulator.staticanalysis.stories.storage.StateOfLink;
import com.plectix.simulator.staticanalysis.stories.storage.StoryStorageException;
import com.plectix.simulator.staticanalysis.stories.storage.WireHashKey;
public final class StoriesGraphs {
private final TreeMap<Long, Long> introAgentsToComponents = new TreeMap<Long, Long>();
private final TreeMap<Long, String> introComponentIdsData = new TreeMap<Long, String>();
private TreeMap<Long, Long> nodeIdToEventId = new TreeMap<Long, Long>();
private TreeMap<Long, Long> nodeEventIdToNodeId = new TreeMap<Long, Long>();
private TreeMap<Long, Integer> depths = new TreeMap<Long, Integer>();
private final Connections connections;
private final CompressionPassport passport;
public StoriesGraphs(CompressionPassport passport) {
this.passport = passport;
this.connections = new Connections();
}
public final int getEventDepth(long eventId) throws StoryStorageException {
if (depths.isEmpty()) {
nodeEventIdToNodeId = new TreeMap<Long, Long>();
}
return depths.get(nodeEventIdToNodeId.get(eventId));
}
public final Connections getConnections2() {
return connections;
}
public final int getIntroDepth(long introId) throws StoryStorageException {
if (depths.isEmpty()) {
nodeEventIdToNodeId = new TreeMap<Long, Long>();
}
if (!depths.containsKey(introId)) {
return -1;
}
return depths.get(introId);
}
public final void buildGraph() throws StoryStorageException {
EventInterface intro = getEventByStepId(-1);
fillNodeIdMap(initializeIntroIdMap(intro));
fillConnections();
fillDepths();
// filterNodes();
}
private final void fillDepths() {
TreeMap<Long, Set<Long>> myconnections = connections.getAdjacentEdges();
Long tmpNode = myconnections.lastKey();
depths.put(tmpNode, 0);
do {
for (Long leaf : myconnections.get(tmpNode)) {
if (depths.containsKey(leaf)) {
if (depths.get(leaf) < depths.get(tmpNode) + 1) {
depths.put(leaf, depths.get(tmpNode) + 1);
}
} else {
depths.put(leaf, depths.get(tmpNode) + 1);
}
}
tmpNode = myconnections.lowerKey(tmpNode);
} while (tmpNode != null);
inverseDepths();
}
private final void inverseDepths() {
TreeMap<Long, Integer> inverseDepths = new TreeMap<Long, Integer>();
int graphDepth = depths.size() - 1;
for (Long key : depths.keySet()) {
inverseDepths.put(key, graphDepth - depths.get(key));
}
depths = null;
depths = inverseDepths;
}
private final long initializeIntroIdMap(EventInterface introEvent)
throws StoryStorageException {
TreeMap<Long, LinkedHashSet<BoundedCouple>> agentsMap = new TreeMap<Long, LinkedHashSet<BoundedCouple>>();
if (introEvent != null) {
long counter = 0;
for (Iterator<WireHashKey> wireIt = introEvent.wireEventIterator(); wireIt
.hasNext();) {
WireHashKey wKey = (WireHashKey) wireIt.next();
if (wKey.getTypeOfWire().equals(TypeOfWire.AGENT)) {
if (!agentsMap.containsKey(wKey.getAgentId())) {
agentsMap.put(wKey.getAgentId(),
new LinkedHashSet<BoundedCouple>());
}
}
if (wKey.getTypeOfWire().equals(TypeOfWire.LINK_STATE)) {
StateOfLink link = (StateOfLink) introEvent.getAtomicEvent(
wKey).getState().getAfterState();
if (link != null) {
if (!agentsMap.containsKey(wKey.getAgentId())) {
agentsMap.put(wKey.getAgentId(),
new LinkedHashSet<BoundedCouple>());
}
agentsMap.get(wKey.getAgentId()).add(
new BoundedCouple(wKey.getAgentId(), wKey
.getSiteName(), link.getAgentId(), link
.getSiteName()));
}
}
}
initializeInternalStates(introEvent, agentsMap);
counter = initializeComponentsData(agentsMap);
return counter;
}
return Long.valueOf(0);
}
private final void initializeInternalStates(EventInterface introEvent,
TreeMap<Long, LinkedHashSet<BoundedCouple>> agentsMap)
throws StoryStorageException {
for (Iterator<WireHashKey> wireIt = introEvent.wireEventIterator(); wireIt
.hasNext();) {
WireHashKey wKey = (WireHashKey) wireIt.next();
if (wKey.getTypeOfWire().equals(TypeOfWire.INTERNAL_STATE)) {
String internal = (String) introEvent.getAtomicEvent(wKey)
.getState().getAfterState();
if (internal != null) {
for (BoundedCouple couple : agentsMap
.get(wKey.getAgentId())) {
if (couple.getFirstAgentId() == wKey.getAgentId()
&& couple.getFirstSite() == wKey.getSiteName()) {
couple.setFirstInternalState(internal);
}
if (couple.getSecondAgentId() != Long.MIN_VALUE)
if (couple.getSecondAgentId() == wKey.getAgentId()
&& couple.getSecondSite().equals(wKey.getSiteName())) {
couple.setSecondInternalState(internal);
}
}
}
}
}
}
private final long initializeComponentsData(
TreeMap<Long, LinkedHashSet<BoundedCouple>> agentsMap) {
long counter = 0;
Map<Long, Set<BoundedCouple>> mapCC = new TreeMap<Long, Set<BoundedCouple>>();
for (Entry<Long, LinkedHashSet<BoundedCouple>> entry : agentsMap
.entrySet()) {
Set<BoundedCouple> set = new LinkedHashSet<BoundedCouple>();
if (!introAgentsToComponents.containsKey(entry.getKey())) {
set = buildComponents(entry.getKey(), agentsMap, set);
mapCC.put(counter, set);
for (BoundedCouple couple : set) {
introAgentsToComponents.put(couple.getFirstAgentId(), counter);
nodeIdToEventId.put(counter, counter);
if (couple.getSecondAgentId() != Long.MIN_VALUE) {
introAgentsToComponents.put(couple.getSecondAgentId(), counter);
nodeIdToEventId.put(counter, counter);
}
}
counter++;
}
}
for (Long id : mapCC.keySet()) {
if (mapCC.get(id).size() > 0) {
introComponentIdsData.put(id, getText(mapCC.get(id)));
}
}
return counter;
}
private final String getText(Set<BoundedCouple> set) {
StringBuffer text = new StringBuffer();
Map<Long, Set<Site>> agentWithSites = new LinkedHashMap<Long, Set<Site>>();
int counter = 0;
for (BoundedCouple boundedCouple : set) {
if (boundedCouple.getSecondAgentId() != Long.MIN_VALUE) {
boundedCouple.setLink(counter++);
if (agentWithSites.containsKey(boundedCouple.getFirstAgentId())) {
agentWithSites.get(boundedCouple.getFirstAgentId()).add(
new Site(boundedCouple.getFirstSite(), boundedCouple
.getLink(), boundedCouple
.getFirstInternalState()));
} else {
agentWithSites.put(boundedCouple.getFirstAgentId(),
new LinkedHashSet<Site>());
agentWithSites.get(boundedCouple.getFirstAgentId()).add(
new Site(boundedCouple.getFirstSite(), boundedCouple
.getLink(), boundedCouple
.getFirstInternalState()));
}
if (agentWithSites.containsKey(boundedCouple.getSecondAgentId())) {
agentWithSites.get(boundedCouple.getSecondAgentId()).add(
new Site(boundedCouple.getSecondSite(), boundedCouple
.getLink(), boundedCouple
.getSecondInternalState()));
} else {
agentWithSites.put(boundedCouple.getSecondAgentId(),
new LinkedHashSet<Site>());
agentWithSites.get(boundedCouple.getSecondAgentId()).add(
new Site(boundedCouple.getSecondSite(), boundedCouple
.getLink(), boundedCouple
.getSecondInternalState()));
}
} else {
if (!agentWithSites.containsKey(boundedCouple.getFirstAgentId())) {
agentWithSites.put(boundedCouple.getFirstAgentId(),
new LinkedHashSet<Site>());
}
agentWithSites.get(boundedCouple.getFirstAgentId()).add(
new Site(boundedCouple.getFirstSite(), boundedCouple
.getFirstInternalState()));
}
}
boolean agentFirst = true;
for (Long agentId : agentWithSites.keySet()) {
if (agentId == null)
continue;
if (agentFirst) {
agentFirst = false;
} else {
text.append(", ");
}
String type = passport.getStorage().getStoriesAgentTypesStorage()
.getType(passport.getStorage().getIteration(), agentId);
text.append("" + type + "(");
boolean siteFirst = true;
if (agentWithSites.get(agentId) != null) { // is it neccessary???
for (Site site : agentWithSites.get(agentId)) {
if (siteFirst) {
siteFirst = false;
} else {
text.append(", ");
}
text.append(site.toString());
}
}
text.append(")");
}
return text.toString();
}
private final Set<BoundedCouple> buildComponents(Long key,
TreeMap<Long, LinkedHashSet<BoundedCouple>> agentsMap,
Set<BoundedCouple> set) {
boolean flag = false;
// if (agentsMap.get(key).isEmpty()) {
// set.add(new BoundedCouple(key));
// return set;
// }
for (BoundedCouple couple : agentsMap.get(key)) {
for (BoundedCouple boundedCouple : set) {
if (boundedCouple.isSame(couple)
|| boundedCouple.equals(couple)) {
flag = true;
}
}
if (!flag) {
set.add(couple);
if (couple.getSecondAgentId() != Long.MIN_VALUE)
buildComponents(couple.getSecondAgentId(), agentsMap, set);
}
}
return set;
}
private void fillNodeIdMap(long id) throws StoryStorageException {
for (EventIteratorInterface iterator = passport.eventIterator(false); iterator
.hasNext();) {
long eventId = (long) iterator.next();
if (eventId != -1) {
nodeEventIdToNodeId.put(eventId, id);
nodeIdToEventId.put(id, eventId);
id++;
}
}
}
private final void fillConnections() throws StoryStorageException {
for (EventIteratorInterface iterator = passport.eventIterator(false); iterator
.hasNext();) {
long eventId = (long) iterator.next();
if (eventId != -1) {
fillConnectionsForOneEvent(getEventByStepId(eventId));
}
}
}
private final void fillConnectionsForOneEvent(EventInterface event) {
Long upperNode;
// Set<Long> connectionSet = new LinkedHashSet<Long>();
TreeMap<Long, Long> map = new TreeMap<Long, Long>();
for (Iterator<WireHashKey> iterator = event.wireEventIterator(); iterator
.hasNext();) {
WireHashKey wkey = (WireHashKey) iterator.next();
TreeMap<Long, AtomicEvent<?>> wire = passport.getStorage()
.getStorageWires().get(wkey);
if (!wire.get(event.getStepId()).getType().equals(
ActionOfAEvent.MODIFICATION)) {
upperNode = getUpperNode(wire, wkey, event.getStepId());
if (upperNode != null) {
map.put(upperNode, upperNode);
}
}
}
if (!map.isEmpty()) {
upperNode = map.lastKey();
do {
connections.addConnection(nodeEventIdToNodeId.get(event
.getStepId()), upperNode);
upperNode = map.lowerKey(upperNode);
} while (upperNode != null);
}
}
private final Long getUpperNode(TreeMap<Long, AtomicEvent<?>> wire,
WireHashKey key, long eventId) {
Long tmp = eventId;
tmp = wire.lowerKey(tmp);
if (tmp != null) {
while (wire.lowerEntry(tmp) != null
&& wire.get(tmp).getType().equals(ActionOfAEvent.TEST)) {
tmp = wire.lowerKey(tmp);
}
// }
if (wire.get(tmp) != null) {
// if (wire.get(tmp).getType().equals(EActionOfAEvent.TEST))
// return null;
if (tmp != -1)
return nodeEventIdToNodeId.get(tmp);
else
return introAgentsToComponents.get(key.getAgentId());
}
}
return null;
}
public final EventInterface getEventByStepId(long stepId) {
if (!passport.getAllEventsByNumber().containsKey(stepId))
return null;
return passport.getAllEventsByNumber().get(stepId).getContainer();
}
public final long getNodeIdByEventId(long eventId) {
if (!nodeEventIdToNodeId.containsKey(eventId))
return -1;
return nodeEventIdToNodeId.get(eventId);
}
public final TreeMap<Long, String> getIntroComponentIdtoData() {
return introComponentIdsData;
}
public final CompressionPassport getPassport() {
return passport;
}
public final long getEventIdByNodeId(long id) {
return nodeIdToEventId.get(id);
}
}