package com.plectix.simulator.staticanalysis.stories.storage; import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Map.Entry; import com.plectix.simulator.staticanalysis.stories.ActionOfAEvent; import com.plectix.simulator.staticanalysis.stories.MarkOfEvent; import com.plectix.simulator.staticanalysis.stories.State; import com.plectix.simulator.staticanalysis.stories.TypeOfWire; public class Event implements EventInterface { public final static boolean BEFORE_STATE = true; public final static boolean AFTER_STATE = false; private MarkOfEvent mark = null; private final ArrayList<WireHashKey> filter = new ArrayList<WireHashKey>(); // map with all wires which touched by this event private final LinkedHashMap<WireHashKey, AtomicEvent<?>> eventsMap = new LinkedHashMap<WireHashKey, AtomicEvent<?>>(); private final long stepId; // event symbolize applying this rule private final int ruleId; public Event(long stepId, int ruleId) { this.ruleId = ruleId; this.stepId = stepId; } public Event(long stepId, int ruleId, MarkOfEvent initialMark) { this.ruleId = ruleId; this.stepId = stepId; this.mark = initialMark; } public AtomicEvent<?> addAtomicEvent(WireHashKey key, ActionOfAEvent type, TypeOfWire typeOfWire) { AtomicEvent<?> event = eventsMap.get(key); if (event == null) { addToFilter(key); switch (typeOfWire) { case AGENT : event = new AtomicEvent<State>(this, type); case BOUND_FREE : event = new AtomicEvent<State>(this, type); case INTERNAL_STATE : event = new AtomicEvent<String>(this, type); case LINK_STATE : event = new AtomicEvent<StateOfLink>(this, type); default :; } eventsMap.put(key, event); } else event.correctingType(type); return event; } public final long getStepId() { return stepId; } public final int getRuleId() { return ruleId; } public final LinkedHashMap<WireHashKey, AtomicEvent<?>> getAtomicEvents() { return eventsMap; } public final void setMark(MarkOfEvent newMark,MasterInformationAboutWires information) throws StoryStorageException { if (newMark == mark) throw new StoryStorageException("same mark"); // there is newMark != unresolved if (mark == MarkOfEvent.UNRESOLVED) { shiftNumberOfUnresolvedEventsOnWires(false,information); } else { if (newMark == MarkOfEvent.UNRESOLVED) { shiftNumberOfUnresolvedEventsOnWires(true, information); } } mark = newMark; } private final void shiftNumberOfUnresolvedEventsOnWires(boolean up, MasterInformationAboutWires information) throws StoryStorageException { for (WireHashKey w : eventsMap.keySet()) { if (eventsMap.get(w).getType() != ActionOfAEvent.TEST) { information.upNumberOfUnresolvedModifyEvent(w, up); } } } public final MarkOfEvent getMark() { return mark; } public final AtomicEvent<?> getAtomicEvent(int index) throws StoryStorageException { WireHashKey wk = filter.get(index); if (wk == null) throw new StoryStorageException("get atomic event =null", index); return eventsMap.get(wk); } public final int getAtomicEventCount() throws StoryStorageException { // TODO: refactor filter.clear(); for (WireHashKey wk : eventsMap.keySet()) { addToFilter(wk); } return filter.size(); } public final TypeOfWire getAtomicEventType(int index) throws StoryStorageException { WireHashKey wk = filter.get(index); if (wk == null) throw new StoryStorageException("get atomic event type", index); // TODO comment after good testing // if (eventsMap.get(wk).getType() == // EActionOfAEvent.TEST_AND_MODIFICATION // && eventsMap.get(wk).getState().getAfterState() == eventsMap // .get(wk).getState().getBeforeState()) { // throw new StoryStorageException( // "states after and before equals on testAndModify event"); // } // if (eventsMap.get(wk).getType() == EActionOfAEvent.TEST // && (eventsMap.get(wk).getState().getAfterState() != null || eventsMap // .get(wk).getState().getBeforeState() == null)) // throw new StoryStorageException( // "states after!=null or before=null on test event"); // // if (eventsMap.get(wk).getType() == EActionOfAEvent.MODIFICATION // && (eventsMap.get(wk).getState().getBeforeState() != null || // eventsMap // .get(wk).getState().getAfterState() == null)) // throw new StoryStorageException( // "states after=null or before!=null on onlyModify event " // + this.stepId); return wk.getTypeOfWire(); } public final WireHashKey getWireKey(int index) throws StoryStorageException { if (filter.isEmpty()) throw new StoryStorageException("filter in CEvent is empty"); WireHashKey wk = filter.get(index); if (wk == null) throw new StoryStorageException("get atomic event", index); return wk; } // optimize : LinkedList -> ArrayList public final Iterator<WireHashKey> wireEventIterator() { List<AtomicEvent<?>> list = new LinkedList<AtomicEvent<?>>(); for (int i = 0; i < filter.size(); i++) { list.add(eventsMap.get(filter.get(i))); } return new IteratorAtomicEventWithinEvent(eventsMap); } public final boolean containsWire(WireHashKey wireKey) { return eventsMap.containsKey(wireKey); } public final AtomicEvent<?> getAtomicEvent(WireHashKey wireKey) throws StoryStorageException { AtomicEvent<?> event = eventsMap.get(wireKey); if (event == null) { throw new StoryStorageException("getAtomicEvent", wireKey .hashCode()); } return event; } public final void removeWire(WireHashKey wKey) { eventsMap.remove(wKey); filter.remove(wKey); } /** * return null if all wire in this event doesn't contain unresolved modify * event * * @throws StoryStorageException * */ public final WireHashKey getWireWithMinimumUresolvedEvent( MasterInformationAboutWires information) throws StoryStorageException { WireHashKey wKey = filter.get(0); int n = filter.size(); int m = information.getUnresolvedModifyCount(wKey); int temp; for (int i = 1; i < n; i++) { temp = information.getUnresolvedModifyCount(filter.get(i)); if ((temp != 0 && temp < m) || (m == 0 && temp > 0)) { wKey = filter.get(i); m = temp; } } if (m > 0) { return wKey; } else { return null; } } public final void setMarkUnresolved(MasterInformationAboutWires information) throws StoryStorageException { mark = MarkOfEvent.UNRESOLVED; shiftNumberOfUnresolvedEventsOnWires(true, information); } public final void addToFilter(WireHashKey key) { if (key.getTypeOfWire() == TypeOfWire.AGENT) filter.add(0, key); else filter.add(key); } public final void onlySetMark(MarkOfEvent newMark) { mark = newMark; } // rebuild event and numberOfUnresolvedevents on wires public final List<PointRound> exchangeWires( Map<WireHashKey, WireHashKey> map, MasterInformationAboutWires information) throws StoryStorageException { List<PointRound> list = new LinkedList<PointRound>(); for (WireHashKey wk : map.keySet()) { WireHashKey wkTwo = map.get(wk); AtomicEvent<?> ae1 = eventsMap.remove(wk); AtomicEvent<?> ae2 = eventsMap.remove(wkTwo); if (ae1 == null && ae2 == null) { continue; } if (ae1 == null) { eventsMap.put(wk, ae2); } else { if (ae2 == null) { eventsMap.put(wkTwo, ae1); } else { eventsMap.put(wkTwo, ae1); eventsMap.put(wk, ae2); } } PointRound pr = new PointRound(); pr.number = stepId; pr.wk1 = wk; pr.wk2 = wkTwo; list.add(pr); int dif = 0; if (mark == MarkOfEvent.UNRESOLVED) { if (eventsMap.get(wk) != null && eventsMap.get(wk).getType() != ActionOfAEvent.TEST) { dif++; } if (eventsMap.get(wkTwo) != null && eventsMap.get(wkTwo).getType() != ActionOfAEvent.TEST) { dif--; } if (dif > 0) { information.upNumberOfUnresolvedModifyEvent(wk, true); information.upNumberOfUnresolvedModifyEvent(wkTwo, false); } if (dif < 0) { information.upNumberOfUnresolvedModifyEvent(wk, false); information.upNumberOfUnresolvedModifyEvent(wkTwo, true); } } } filter.clear(); for (WireHashKey wk : eventsMap.keySet()) { addToFilter(wk); } return list; } @Override public final String toString() { String string = new String("mark: " + mark + " stepId: " + stepId + " ruleId: " + ruleId); for (Entry<WireHashKey, AtomicEvent<?>> wk : eventsMap.entrySet()) { string += "wire : (" + wk.getKey() + ") + AtomicEvent " + wk.getValue(); } return string; } }