package com.plectix.simulator.simulationclasses.action;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.Set;
import com.plectix.simulator.interfaces.ConnectedComponentInterface;
import com.plectix.simulator.simulationclasses.injections.Injection;
import com.plectix.simulator.simulationclasses.solution.RuleApplicationPoolInterface;
import com.plectix.simulator.simulator.SimulationData;
import com.plectix.simulator.staticanalysis.Agent;
import com.plectix.simulator.staticanalysis.LinkStatus;
import com.plectix.simulator.staticanalysis.Rule;
import com.plectix.simulator.staticanalysis.Site;
import com.plectix.simulator.staticanalysis.stories.storage.StoryStorageException;
/**
* This class implements "atomic action".
*
* @see ActionType
*/
public abstract class Action {
private final Agent sourceAgent;
private final Agent targetAgent;
private final Rule rule;
private final ConnectedComponentInterface rightHandSideComponent;
private ConnectedComponentInterface leftHandSideComponent;
private ActionType type;
private Site targetSite = null;
private Site sourceSite = null;
/**
* Constructor. Creates atomic action, transforming chosen agent from left
* handside to the other one from right handside of the fixed rule
*
* @param rule
* fixed rule
* @param sourceAgent
* agent from left handSide of the rule
* @param targetAgent
* agent from right handSide of the rule
* @param leftHandSideComponent
* given connected component, containing <b>fromAgent</b>
* @param rightHandSideComponent
* given connected component, containing <b>toAgent</b>
*/
Action(Rule rule, Agent sourceAgent, Agent targetAgent,
ConnectedComponentInterface leftHandSideComponent,
ConnectedComponentInterface rightHandSideComponent) {
this.sourceAgent = sourceAgent;
this.targetAgent = targetAgent;
this.rightHandSideComponent = rightHandSideComponent;
this.leftHandSideComponent = leftHandSideComponent;
this.rule = rule;
}
/**
* This method apply current action in fixed rule application pool.
*
* @param pool
* rule application pool, storage where we get changeable
* substances from and where we put the result
* @param injection
* injection, pointing to agents which we should take for
* application.
* @param netNotation
* network notation ("null" if it not "STORY" simulation mode).
* @param simulationData
* simulation data
* @throws StoryStorageException
*/
public abstract void doAction(RuleApplicationPoolInterface pool,
Injection injection, ActionObserverInteface eventContainer,
SimulationData simulationData) throws StoryStorageException;
/**
* This method returns takes agent from left handside of the rule by it's
* image - agent from right handside, and then returns it's id in connected
* component
*
* @param toAgentRight
* given agent
* @return {@link Agent#getIdInConnectedComponent()}
*/
final int getAgentIdInCCBySideId(Agent toAgentRight) {
// TODO May be should optimize?
for (ConnectedComponentInterface cc : getRule().getLeftHandSide())
for (Agent leftHandSideComponentAgent : cc.getAgents())
if (leftHandSideComponentAgent.getIdInRuleHandside() == toAgentRight
.getIdInRuleHandside()) {
if (leftHandSideComponent == null)
leftHandSideComponent = cc;
return leftHandSideComponentAgent
.getIdInConnectedComponent();
}
return -1;
}
/**
* This method analyses current action and creates new actions, if possible.
*
* @return collection of new actions
*/
public final Collection<Action> createAtomicActions() {
Set<Action> atomicActions = new LinkedHashSet<Action>();
for (Site sourceSite : sourceAgent.getSites()) {
Site targetSite = targetAgent.getSiteByName(sourceSite.getName());
if (!sourceSite.getInternalState().hasSimilarName(targetSite.getInternalState())) {
atomicActions.add(new ModifyAction(getRule(), sourceSite, targetSite,
leftHandSideComponent,
rightHandSideComponent));
getRule().addInhibitedChangedSite(sourceSite, true, false);
}
if ((sourceSite.getLinkState().getStatusLink() == LinkStatus.FREE)
&& (targetSite.getLinkState().getStatusLink() == LinkStatus.FREE))
continue;
if ((sourceSite.getLinkState().getStatusLink() != LinkStatus.FREE)
&& (targetSite.getLinkState().getStatusLink() == LinkStatus.FREE)) {
atomicActions.add(new BreakAction(getRule(), sourceSite, targetSite,
leftHandSideComponent,
rightHandSideComponent));
getRule().addInhibitedChangedSite(sourceSite, false, true);
continue;
}
if ((sourceSite.getLinkState().getStatusLink() == LinkStatus.FREE)
&& (targetSite.getLinkState().getStatusLink() == LinkStatus.BOUND)) {
atomicActions.add(new BoundAction(getRule(), targetSite, targetSite.getLinkState()
.getConnectedSite(), leftHandSideComponent,
rightHandSideComponent));
getRule().addInhibitedChangedSite(sourceSite, false, true);
continue;
}
Site siteConnectedToSiteFrom = sourceSite.getLinkState().getConnectedSite();
Site siteConnectedToSiteTo = targetSite.getLinkState().getConnectedSite();
if (siteConnectedToSiteFrom == null || siteConnectedToSiteTo == null)
continue;
if ((siteConnectedToSiteFrom.getParentAgent().getIdInRuleHandside() == siteConnectedToSiteTo
.getParentAgent().getIdInRuleHandside())
&& (siteConnectedToSiteFrom.equalz(siteConnectedToSiteTo)))
continue;
atomicActions.add(new BreakAction(getRule(), sourceSite, targetSite,
leftHandSideComponent,
rightHandSideComponent));
atomicActions.add(new BoundAction(getRule(), targetSite, targetSite.getLinkState()
.getConnectedSite(), leftHandSideComponent,
rightHandSideComponent));
getRule().addInhibitedChangedSite(sourceSite, false, true);
}
return atomicActions;
}
// =======================GETTERS AND SETTERS========================
/**
* This method sets sites, which this action should be applied to.
*
* @param source
* site from the left handside of the rule
* @param target
* site from the right handside of the rule
*/
final void setActionApplicationSites(Site source, Site target) {
targetSite = target;
sourceSite = source;
}
/**
* This method sets type of current action.
*
* @param actionType
* type to be set
* @see ActionType
*/
final void setType(ActionType actionType) {
this.type = actionType;
}
/**
* This method returns site from the left handside of the rule, which this
* action should be applied to.
*/
public final Site getSourceSite() {
return sourceSite;
}
/**
* This method returns site from the right handside of the rule, which this
* action should be applied to.
*/
public final Site getTargetSite() {
return targetSite;
}
/**
* Util method, used for output only.
*/
public final Agent getSourceAgent() {
return sourceAgent;
}
/**
* Util method, used for output only.
*/
public final Agent getTargetAgent() {
return targetAgent;
}
/**
* This method returns connected component from right handSide rule, which
* this action should be applied to (may be "null").
*/
final ConnectedComponentInterface getRightCComponent() {
return rightHandSideComponent;
}
/**
* This method returns connected component from left handSide rule, which
* this action should be applied to (may be "null").
*/
public final ConnectedComponentInterface getLeftCComponent() {
return leftHandSideComponent;
}
Rule getRule() {
return rule;
}
public ActionType getType() {
return type;
}
}