package jcircus.environment;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.TreeMap;
import java.util.Vector;
import jcircus.exceptions.ChanUseUnificationException;
import jcircus.exceptions.MoreThanOneWriterException;
import jcircus.newutil.ChannelUtil;
import jcircus.util.ChanUse;
import net.sourceforge.czt.base.ast.ListTerm;
import net.sourceforge.czt.circus.ast.ProcessPara;
import net.sourceforge.czt.z.ast.Name;
import net.sourceforge.czt.z.ast.Spec;
import net.sourceforge.czt.z.ast.ZExprList;
import net.sourceforge.czt.z.ast.ZNameList;
/**
* ChanUseEnv.java
*
* @author Angela Freitas
*/
public class ChanUseEnv {
/**
* Needs to be String because the key in TreeMap has to implement Comparable.
* String (channelName) -> ChanUse
*/
private TreeMap<String, ChanUse> treeMap_;
/**
* Constructor
*/
public ChanUseEnv() {
this.treeMap_ = new TreeMap<String, ChanUse>();
}
/**
*
* @param channelName
* @param javaType
* @throws ChannelAlreadyDefinedException
*/
public void put(String channelName, ChanUse chanUse) {
if (chanUse == null)
throw new NullPointerException();
this.treeMap_.put(channelName.toString(), chanUse);
}
/**
*
* @param channelName
* @return
*/
public ChanUse get(String channelName) {
return treeMap_.get(channelName);
}
/**
*
* @param channelName
*/
public void remove(String channelName) {
this.treeMap_.remove(channelName);
}
/**
*
* @return
*/
public int size() {
return this.treeMap_.size();
}
/**
*
* @param channelName
* @return
*/
public boolean containsKey(String channelName) {
return this.treeMap_.containsKey(channelName);
}
/**
*
* @param channelUseEnvironment
* @throws ChannelAlreadyDefinedException
*/
private void putAll(ChanUseEnv channelUseEnvironment) {
Iterator<String> iterator = channelUseEnvironment.iteratorKeys();
String channelName;
ChanUse javaTypeChannel;
while(iterator.hasNext()) {
channelName = iterator.next();
javaTypeChannel = channelUseEnvironment.get(channelName);
this.put(channelName, javaTypeChannel);
}
}
/**
*
* @param channelUseEnvironment
*/
public void removeAll(ChanUseEnv channelUseEnvironment) {
Iterator<String> iterator = channelUseEnvironment.iteratorKeys();
String channelName;
while(iterator.hasNext()) {
channelName = iterator.next();
this.remove(channelName);
}
}
public ChanUseEnv merge(ChanUseEnv other, boolean isParallel)
/*throws ChanUseUnificationException, MoreThanOneWriterException*/ {
// Creates a new env, which will be returned
ChanUseEnv r = new ChanUseEnv();
// Inserts all the channels of this env
r.putAll(this);
// Iterates over the second env
Iterator<String> iterator = other.iteratorKeys();
while(iterator.hasNext()) {
String chanName = iterator.next();
ChanUse otherChanUse = other.get(chanName);
ChanUse newChanUse = otherChanUse;
// If the channel exists in both envs
if (r.containsKey(chanName)) {
ChanUse thisChanUse = r.get(chanName);
if (isParallel) {
// If this merge is a parallelism, permits if they are of
// complementary types
if (thisChanUse.equals(ChanUse.Input) && otherChanUse.equals(ChanUse.Output) ||
thisChanUse.equals(ChanUse.Output) && otherChanUse.equals(ChanUse.Input)) {
// In this case the resulting type is mixed, to indicate
// that it is used in a parallelism
newChanUse = ChanUse.Mixed;
// If they are equal
} else if (otherChanUse.equals(thisChanUse)) {
// The resulting remains the same
newChanUse = otherChanUse;
// If one is mixed and the other is input
} else if (thisChanUse.equals(ChanUse.Mixed) && otherChanUse.equals(ChanUse.Input) ||
thisChanUse.equals(ChanUse.Input) && otherChanUse.equals(ChanUse.Mixed)) {
// Remains mixed
newChanUse = ChanUse.Mixed;
// If one is mixed and the other is output
} /*else if (thisChanUse.equals(ChanUse.Mixed) && otherChanUse.equals(ChanUse.Output) ||
thisChanUse.equals(ChanUse.Output) && otherChanUse.equals(ChanUse.Mixed)) {
// Error because there is more than one writer in the
// parallelism
throw new MoreThanOneWriterException();
// If one is undefined and the other is input
}*/ else if (thisChanUse.equals(ChanUse.Undefined) && otherChanUse.equals(ChanUse.Input) ||
thisChanUse.equals(ChanUse.Input) && otherChanUse.equals(ChanUse.Undefined)) {
// Input
newChanUse = ChanUse.Input;
// If one is undefined and the other is output
} else if (thisChanUse.equals(ChanUse.Undefined) && otherChanUse.equals(ChanUse.Output) ||
thisChanUse.equals(ChanUse.Output) && otherChanUse.equals(ChanUse.Undefined)) {
// Output
newChanUse = ChanUse.Output;
// All other cases is a situation that I did not expected
} else {
// so throw an exception to find out what is happening!
/*throw new ChanUseUnificationException(
chanName, thisChanUse, otherChanUse);*/
}
} else {
// If this is not a composition of a parallelism, then we need
// to have the same types
if (otherChanUse.equals(thisChanUse)) {
newChanUse = otherChanUse;
} else {
// throw new ChanUseUnificationException(chanName, thisChanUse, otherChanUse);
}
}
}/*if (r.containsKey(chanName))*/
r.put(chanName, newChanUse);
}
return r;
}
/**
*
* @param newChannels
* @param oldChannels
* @return
* @throws ChannelAlreadyDefinedException
*/
public ChanUseEnv substitute(ZExprList/*ListTerm*/ newChannels, ZNameList/*ListTerm*/ oldChannels) {
ChanUseEnv r = new ChanUseEnv();
String channelName;
String newChannelName;
Name name;
ChanUse javaType;
int index;
r.putAll(this);
for (int i = 0; i < oldChannels.size(); i++) {
name = (Name) oldChannels.get(i);
newChannelName = ((Name) newChannels.get(i)).toString();
if (r.containsKey(name.toString())) {
javaType = r.get(name.toString());
r.remove(name.toString());
r.put(newChannelName, javaType);
}
}
return r;
}
/**
*
* @return
*/
public Iterator<String> iteratorKeys() {
return this.treeMap_.keySet().iterator();
}
public Set keysFromMainAction (ProcessPara processPara, Spec spec) {
Set keys = this.treeMap_.keySet();
Set <String> keysFromMainAction = new HashSet <String> ();
Vector <String> visibleChannelsFromMainAction = ChannelUtil.getVisibleChannelsFromMainAction(processPara, spec);
keysFromMainAction.addAll(visibleChannelsFromMainAction);
return keysFromMainAction;
}
public Iterator iteratorKeysFromMainAction (ProcessPara processPara, Spec spec) {
return keysFromMainAction (processPara, spec).iterator();
}
/**
*
*/
public void print() {
Iterator<String> it = this.iteratorKeys();
System.out.println("---------------------------");
while(it.hasNext()) {
String chanName = it.next();
ChanUse chanUse = this.get(chanName);
System.out.println(chanName + " " + chanUse);
}
}
}