package simulator;
import java.util.Map;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import models.algebra.Constant;
import models.algebra.Expression;
import models.dataConstraintModel.Selector;
import models.dataFlowModel.DataTransferChannel;
/**
* State of a channel, which represents the map from the values of the depended channel selectors to those of the depending channel selectors
*
* @author Nitta
*
*/
public class ChannelState implements Cloneable {
private DataTransferChannel channel;
private ReferenceStructure referenceStructure;
public ChannelState(DataTransferChannel channel) {
this.channel = channel;
}
public DataTransferChannel getChannel() {
return channel;
}
public Map<Expression, Expression> getDependingParamAndValues(List<Constant> channelValues) {
if (referenceStructure == null) {
return new HashMap<>();
}
return referenceStructure.getDependingParamAndValues(channelValues);
}
public List<List<Constant>> getDependedChannelSelectorValues(Expression dependingVariable, Expression itsValue) {
if (referenceStructure == null) {
return null;
}
Map<Expression, Expression> dependingVarToVal = new HashMap<>();
dependingVarToVal.put(dependingVariable, itsValue);
return referenceStructure.getDependedChannelSelectorValues(dependingVarToVal);
}
public List<List<Constant>> getDependedChannelSelectorValues(Map<Expression, Expression> dependingVarToVal) {
if (referenceStructure == null) {
return null;
}
return referenceStructure.getDependedChannelSelectorValues(dependingVarToVal);
}
/**
* Add a value of a depending channel selector
*
* @param channelValues the values of depended channel selectors
* @param dependingVariable a depending channel selector
* @param itsValue its new value
*/
public void addDependingParamAndValue(List<Constant> channelValues, Expression dependingVariable, Expression itsValue) {
if (referenceStructure == null) {
referenceStructure = new ReferenceStructure();
}
referenceStructure.addDependingParamAndValue(channelValues, dependingVariable, itsValue);
}
public Object clone() {
ChannelState newChannelState = new ChannelState(channel);
if (referenceStructure != null) newChannelState.referenceStructure = (ReferenceStructure) referenceStructure.clone();
return newChannelState;
}
private static class ReferenceStructure implements Cloneable {
private Map<Expression, Expression> dependingParamAndValues = null;
private Map<Constant, ReferenceStructure> referenceStructure;
public Map<Expression, Expression> getDependentParamAndValues() {
return dependingParamAndValues;
}
public Map<Expression, Expression> getDependingParamAndValues(List<Constant> channelValues) {
ReferenceStructure subStructure = this;
for (Constant chVal: channelValues) {
if (subStructure.getDependentParamAndValues() == null) {
subStructure = subStructure.getReferenceStructure(chVal);
} else {
return new HashMap<>();
}
}
return subStructure.getDependentParamAndValues();
}
public List<List<Constant>> getDependedChannelSelectorValues(Map<Expression, Expression> dependingVarToVal) {
List<List<Constant>> channelValuesList = new ArrayList<>();
if (dependingParamAndValues != null) {
boolean doesMatch = true;
for (Expression dependingVariable: dependingVarToVal.keySet()) {
if (dependingParamAndValues.keySet().contains(dependingVariable)) {
if (!dependingParamAndValues.get(dependingVariable).equals(dependingVarToVal.get(dependingVariable))) {
doesMatch = false;
}
}
}
if (doesMatch) {
List<List<Constant>> chValsList = new ArrayList<>();
chValsList.add(new ArrayList<>());
return chValsList;
} else {
return null;
}
} else {
for (Constant chVal: referenceStructure.keySet()) {
List<List<Constant>> chValsList = referenceStructure.get(chVal).getDependedChannelSelectorValues(dependingVarToVal);
if (chValsList != null) {
for (List<Constant> chVals: chValsList) {
chVals.add(0, chVal);
channelValuesList.add(chVals);
}
}
}
}
return channelValuesList;
}
public void addDependingParamAndValue(Expression dependingVariable, Expression itsValue) {
if (dependingParamAndValues == null) {
dependingParamAndValues = new HashMap<>();
}
dependingParamAndValues.put(dependingVariable, itsValue);
}
public void addDependingParamAndValue(List<Constant> channelValues, Expression dependingVariable, Expression itsValue) {
ReferenceStructure subStructure = this;
for (Constant chVal: channelValues) {
if (subStructure.referenceStructure == null) {
subStructure.referenceStructure = new HashMap<>();
}
ReferenceStructure nextStructure = subStructure.referenceStructure.get(chVal);
if (nextStructure == null) {
nextStructure = new ReferenceStructure();
subStructure.referenceStructure.put(chVal, nextStructure);
}
subStructure = nextStructure;
}
subStructure.addDependingParamAndValue(dependingVariable, itsValue);
}
public ReferenceStructure getReferenceStructure(Constant channelParam) {
return referenceStructure.get(channelParam);
}
public Object clone() {
ReferenceStructure newReferenceStructure = new ReferenceStructure();
if (dependingParamAndValues != null) {
newReferenceStructure.dependingParamAndValues = new HashMap<>(dependingParamAndValues);
}
if (referenceStructure != null) {
newReferenceStructure.referenceStructure = new HashMap<>();
for (Map.Entry<Constant, ReferenceStructure> refEnt: referenceStructure.entrySet()) {
newReferenceStructure.referenceStructure.put(refEnt.getKey(), (ReferenceStructure) refEnt.getValue().clone());
}
}
return newReferenceStructure;
}
}
}