package com.plectix.simulator.staticanalysis.subviews.base; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import com.plectix.simulator.interfaces.ConnectedComponentInterface; import com.plectix.simulator.interfaces.ObservableConnectedComponentInterface; import com.plectix.simulator.staticanalysis.Agent; import com.plectix.simulator.staticanalysis.Rule; import com.plectix.simulator.staticanalysis.StaticAnalysisException; import com.plectix.simulator.staticanalysis.abstracting.AbstractAgent; import com.plectix.simulator.staticanalysis.abstracting.AbstractSite; import com.plectix.simulator.staticanalysis.subviews.WrapperTwoSet; import com.plectix.simulator.staticanalysis.subviews.storage.SubViewsInterface; public final class AbstractionRule { private final List<AbstractAction> actions; private final int ruleId; // TODO please correct me if I set the wrong name to this one private boolean wasApplied = false; private final ObservableConnectedComponentInterface observableComponent; private final List<AbstractAgent> leftHandSideAgents; private final List<AbstractAgent> rightHandSideAgents; public AbstractionRule(Rule rule) { actions = new LinkedList<AbstractAction>(); this.ruleId = rule.getRuleId(); this.leftHandSideAgents = initListAgents(rule.getLeftHandSide()); this.rightHandSideAgents = initListAgents(rule.getRightHandSide()); List<AbstractAgent> left = initListAgents(rule.getLeftHandSide()); List<AbstractAgent> right = initListAgents(rule.getRightHandSide()); initAtomicActions(left, right); observableComponent = null; } public AbstractionRule(ObservableConnectedComponentInterface observableComponent) { actions = new LinkedList<AbstractAction>(); this.observableComponent = observableComponent; this.ruleId = observableComponent.getId(); List<ConnectedComponentInterface> leftList = new LinkedList<ConnectedComponentInterface>(); leftList.add(observableComponent); List<AbstractAgent> left = initListAgents(leftList); List<AbstractAgent> right = initListAgents(null); initAtomicActions(left, right); this.leftHandSideAgents = null; this.rightHandSideAgents = null; } public final void initActionsToSubViews( Map<String, List<SubViewsInterface>> subViews) { for (AbstractAction action : actions) action.initSubViews(subViews); } public final WrapperTwoSet apply(Map<String, AbstractAgent> agentNameToAgent, Map<String, List<SubViewsInterface>> subViewsMap) throws StaticAnalysisException { if (!wasApplied) { for (AbstractAction action : actions) { boolean isEnd = true; if (action.canApply()) continue; for (SubViewsInterface subViews : action.getSubViews()) try { if (subViews.test(action)) { isEnd = false; } else if (action.getActionType() == AbstractActionType.TEST_ONLY || action.getActionType() == AbstractActionType.DELETE) return null; } catch (StaticAnalysisException e) { if (action.getActionType() != AbstractActionType.DELETE) throw e; } if (isEnd) return null; action.setApplicable(); } } WrapperTwoSet activatedRules = new WrapperTwoSet(); wasApplied = true; for (AbstractAction action : actions) { if (action.getActionType() != AbstractActionType.TEST_ONLY) { action.clearSitesSideEffect(); for (SubViewsInterface subViews : action.getSubViews()) { if (subViews.burnRule(action)) activatedRules.firstSetAddAll( subViews.getSubViewClass().getRulesId()); } for (List<SubViewsInterface> subViewsList : subViewsMap .values()) for (SubViewsInterface subViews : subViewsList) if (subViews.burnBreakAllNeedLinkState(action)) activatedRules.secondSetAddAll( subViews.getSubViewClass().getRulesId()); } } if (!activatedRules.isEmpty()) { return activatedRules; } else { return null; } } /** * Util method. Uses for sort and creates list of abstract agent by given * connected components. * * @param components * given connected components * @return list of abstract agent */ private final List<AbstractAgent> initListAgents( List<ConnectedComponentInterface> components) { List<AbstractAgent> listOut = new LinkedList<AbstractAgent>(); Map<Integer, AbstractAgent> map = new LinkedHashMap<Integer, AbstractAgent>(); if (components == null) return listOut; for (ConnectedComponentInterface component : components) for (Agent agent : component.getAgents()) { AbstractAgent newAgent = new AbstractAgent(agent); map.put(agent.getIdInRuleHandside(), newAgent); } List<Integer> indexList = new ArrayList<Integer>(); indexList.addAll(map.keySet()); Collections.sort(indexList); for (int i : indexList) listOut.add(map.get(i)); return listOut; } /** * This method initializes abstract atomic actions. */ private final void initAtomicActions(List<AbstractAgent> leftHandSide, List<AbstractAgent> rightHandSide) { if (leftHandSide.get(0).hasDefaultName()) { addAgentsToAdd(rightHandSide); return; } if (rightHandSide.isEmpty()) { for (AbstractAgent a : leftHandSide) { addAgentToDelete(a); } return; } int i = 0; for (AbstractAgent lhsAgent : leftHandSide) { if (i >= rightHandSide.size()) { addAgentToDelete(lhsAgent); continue; } AbstractAgent rhsAgent = rightHandSide.get(i++); if (isFit(lhsAgent, rhsAgent)) { actions.add(new AbstractAction(lhsAgent, rhsAgent)); } else { addAgentToDelete(lhsAgent); addAgentToAdd(rhsAgent); } } for (int j = i; j < rightHandSide.size(); j++) { AbstractAgent rhsAgent = rightHandSide.get(j); addAgentToAdd(rhsAgent); } } /** * Util method. Uses only in {@link #initAtomicActions()}. Creates "ADD" * action. * * @param agents * given list of agents */ private final void addAgentsToAdd(List<AbstractAgent> agents) { for (AbstractAgent a : agents) addAgentToAdd(a); } /** * Util method. Uses only in {@link #initAtomicActions()}. Creates "ADD" * action. * * @param agentIn * given agent */ private final void addAgentToAdd(AbstractAgent agentIn) { actions.add(new AbstractAction(null, agentIn)); } /** * Util method. Uses only in {@link #initAtomicActions()}. Creates "DELETE" * action. * * @param agentIn * given agent */ private final void addAgentToDelete(AbstractAgent agentIn) { actions.add(new AbstractAction(agentIn, null)); } /** * Util method. Compares given agents. Uses only in * {@link #initAtomicActions()} * * @param a1 * given agent * @param a2 * given agent * @return <tt>true</tt> if given agents are similar, otherwise * <tt>false</tt> */ private static final boolean isFit(AbstractAgent a1, AbstractAgent a2) { if (!a1.hasSimilarName(a2)) return false; if (a1.getSitesMap().size() != a2.getSitesMap().size()) return false; for (Map.Entry<String, AbstractSite> entry : a1.getSitesMap() .entrySet()) { AbstractSite s1 = entry.getValue(); AbstractSite s2 = a2.getSitesMap().get(entry.getKey()); if ((s2 == null) || (!s1.hasSimilarName(s2))) return false; } return true; } public final List<AbstractAction> getActions() { return actions; } public final int getRuleId() { return ruleId; } public final boolean isApply() { return wasApplied; } public final ObservableConnectedComponentInterface getObservableComponent() { return observableComponent; } public final List<AbstractAction> getLeftHandSideActions() { List<AbstractAction> outList = new LinkedList<AbstractAction>(); for (AbstractAction action : actions) if (action.getActionType() != AbstractActionType.ADD) outList.add(action); return outList; } /** * This method returns agents, necessary for "focus rule". * * @return necessary agents. */ public final Collection<AbstractAgent> getFocusedAgents() { Collection<AbstractAgent> agentsList = new LinkedHashSet<AbstractAgent>(); for (AbstractAction action : actions) { if (action.getActionType() == AbstractActionType.ADD) { AbstractAgent agent = action.getLeftHandSideAgent(); if (!agent.includedInCollection(agentsList)) { agentsList.add(agent); } } if (action.getActionType() == AbstractActionType.DELETE) { AbstractAgent agent = action.getRightHandSideAgent(); if (!agent.includedInCollection(agentsList)) { agentsList.add(agent); } } if (action.getActionType() == AbstractActionType.TEST_AND_MODIFICATION) { AbstractAgent agent = action.getLeftHandSideAgent(); if (!agent.includedInCollection(agentsList)) { agentsList.add(agent); } AbstractAgent agent2 = action.getRightHandSideAgent(); if (!agent2.includedInCollection(agentsList)) { agentsList.add(agent2); } } } return agentsList; } /** * This method returns agents from left handSide current rule. * * @return agents from left handSide current rule. */ public final List<AbstractAgent> getLeftHandSideAgents() { return leftHandSideAgents; } /** * This method returns agents from right handSide current rule. * * @return agents from right handSide current rule. */ public final List<AbstractAgent> getRightHandSideAgents() { return rightHandSideAgents; } }