package org.societies.context.user.refinement.impl.bayesianLibrary.bayesianLearner.impl;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.Vector;
import org.societies.context.user.refinement.impl.bayesianLibrary.bayesianLearner.exceptions.NodeValueIndexNotInNodeRangeException;
import org.societies.context.user.refinement.impl.bayesianLibrary.bayesianLearner.exceptions.NodeValueTextNotInNodeRangeException;
import org.societies.context.user.refinement.impl.bayesianLibrary.bayesianLearner.interfaces.RandomVariable;
public class SimpleRandomVariable implements RandomVariable,Serializable{
private int[] nodeRange;
private String name;
private Map<String,Integer> range;
private Map<IntegerContainer,String> rangeIntToText;
private Map<IntegerContainer,Integer> inverseRangeIntToRangePosition;
private IntegerContainer tmpIntegerContainer;
private int storedHash;
protected boolean doesNotAllowOutgoingArrows;
protected boolean allowsOnlyOutgoingArrows;
/**
* 0 means highest priority
*/
protected int hierarchy; // 0 means highest priority
/**
* Creates a new SimpleRandomVariable called name
* Range values must be zero or positive
* @param name the name of the SimpleRandomVariable
* @param range a Map<String,Integer> with the name of the range value mapped to the integer value
*/
public SimpleRandomVariable(String name, Map<String,Integer> range) {
this.doesNotAllowOutgoingArrows= false;
this.hierarchy = 0;
this.allowsOnlyOutgoingArrows=false;
this.name = name;
this.storedHash = this.name.hashCode();
this.range = new HashMap<String,Integer>();
this.inverseRangeIntToRangePosition = new HashMap<IntegerContainer,Integer>();
this.rangeIntToText = new HashMap<IntegerContainer,String>();
this.tmpIntegerContainer = new IntegerContainer(0);
if (range!=null) this.buildTables(range); // if needed for case when called with range=null from other constructor
}
/**
* Creates a new SimpleRandomVariable called name, with range values ordered according to
* the passed Vector "values". The range values as integers will be numbered from
* baseRangeValue ... values.size()+baseRangeValue-1 accordingly
* @param name the name of the SimpleRandomVariable
* @param baseRangeValue the starting value for the numbering of the range, must be >= 0
* @param values a Vector of Strings with the names of the range values
*/
public SimpleRandomVariable(String name, int baseRangeValue, Vector<String> values) {
this(name, baseRangeValue, (String[]) values.toArray(new String[0]));
}
/**
* Creates a new SimpleRandomVariable called name, with range values ordered according to
* the passed Vector "values". The range values as integers will be numbered from
* baseRangeValue ... values.size()+baseRangeValue-1 accordingly
* @param name the name of the SimpleRandomVariable
* @param baseRangeValue the starting value for the numbering of the range, must be >= 0
* @param values an array of Strings with the names of the range values
*/
public SimpleRandomVariable(String name, int baseRangeValue, String[] values) {
this(name, null);
Map<String,Integer> tmpMap = new HashMap<String,Integer>();
int counter = baseRangeValue;
for (int i=0;i<values.length;i++) {
tmpMap.put(values[i], new Integer(counter++));
}
this.buildTables(tmpMap);
}
private void buildTables(Map<String, Integer> range) {
// this.nodeRange = new int[range.size()+1];
// this.range.putAll(range);
// this.nodeRange[0] = -1;
// this.range.put("NOOP", new Integer(-1));
// this.rangeIntToText.put(new IntegerContainer(-1), "NOOP");
// this.inverseRangeIntToRangePosition.put(new IntegerContainer(-1), new Integer(0));
//
// String[] rangeTextArray = (String[]) range.keySet().toArray(new String[0]);
// for (int i=0;i<rangeTextArray.length;i++) {
// String rangeValueName = rangeTextArray[i];
// this.nodeRange[i+1] = ((Integer) range.get(rangeValueName)).intValue();
// // System.out.println("i: " + i + " " + rangeValueName + " " + range.get(rangeValueName).intValue());
//
// this.rangeIntToText.put(new IntegerContainer(this.nodeRange[i+1]), rangeValueName);
// this.inverseRangeIntToRangePosition.put(new IntegerContainer(this.nodeRange[i+1]), new Integer(i+1));
// }
this.nodeRange = new int[range.size()];
this.range.putAll(range);
String[] rangeTextArray = (String[]) range.keySet().toArray(new String[0]);
for (int i=0;i<rangeTextArray.length;i++) {
String rangeValueName = rangeTextArray[i];
this.nodeRange[i] = ((Integer) range.get(rangeValueName)).intValue();
this.rangeIntToText.put(new IntegerContainer(this.nodeRange[i]), rangeValueName);
this.inverseRangeIntToRangePosition.put(new IntegerContainer(this.nodeRange[i]), new Integer(i));
}
}
public int[] getNodeRange() {
return this.nodeRange;
}
public int getNodeRangePositionFromValue(int nodeValue) throws NodeValueIndexNotInNodeRangeException {
synchronized (this.tmpIntegerContainer) {
this.tmpIntegerContainer.setIntegerValue(nodeValue);
Integer ret = (Integer) this.inverseRangeIntToRangePosition.get(this.tmpIntegerContainer);
if (ret==null) throw new NodeValueIndexNotInNodeRangeException("\nValue: " + nodeValue+ " is not in this RV: "+ this.toString());
return ret.intValue();
}
}
public String getNodeValueText(int nodeValue) throws NodeValueIndexNotInNodeRangeException {
synchronized (this.tmpIntegerContainer) {
this.tmpIntegerContainer.setIntegerValue(nodeValue);
String ret = (String) this.rangeIntToText.get(this.tmpIntegerContainer);
if (ret==null) throw new NodeValueIndexNotInNodeRangeException(" Value: " + nodeValue+ " is not in this RV: "+ this.toString());
return ret;
}
}
public String getName() {
return this.name;
}
public int getNodeValueFromText(String nodeValueText) throws NodeValueTextNotInNodeRangeException {
Integer ret = (Integer) this.range.get(nodeValueText);
if (ret==null) throw new NodeValueTextNotInNodeRangeException("\n Value: " + nodeValueText+ " is not in this RV: "+ this.toString());
return ret.intValue();
}
public boolean equals (Object o) {
if (o instanceof RandomVariable) {
return ((RandomVariable) o).getName().equals(this.getName());
}
return false;
}
public int hashCode () {
return this.storedHash;
}
public int compareTo(RandomVariable arg0) {
return this.getName().compareTo(((RandomVariable) arg0).getName());
}
public String toString() {
return this.getName() + "/Rg:" + this.nodeRange.length;
}
public String toStringLong() {
return this.getName() + "/Rg:" + this.nodeRange.length + " Ranges: \n " + this.range;
}
public boolean doesNotAllowOutgoingArrows() {
return this.doesNotAllowOutgoingArrows;
}
public void setDoesNotAllowOutgoingArrows(boolean doesNotAllowOutgoingArrows) {
if (doesNotAllowOutgoingArrows) this.allowsOnlyOutgoingArrows = false;
this.doesNotAllowOutgoingArrows = doesNotAllowOutgoingArrows;
}
public int getHierarchy() {
return hierarchy;
}
public void setHierarchy(int hierarchy) {
this.hierarchy = hierarchy;
}
public boolean allowsOnlyOutgoingArrows() {
return allowsOnlyOutgoingArrows;
}
public void setAllowsOnlyOutgoingArrows(boolean allowsOnlyOutgoingArrows) {
if (allowsOnlyOutgoingArrows) this.doesNotAllowOutgoingArrows = false;
this.allowsOnlyOutgoingArrows = allowsOnlyOutgoingArrows;
}
private class IntegerContainer implements Serializable{
private long intValue;
/**
* @param i
*/
public IntegerContainer(int intValue) {
this.intValue = intValue;
}
/**
* @return Returns the intValue.
*/
public long getIntegerValue() {
return this.intValue;
}
/**
* @param intValue The intValue to set.
*/
public void setIntegerValue(int intValue) {
this.intValue = intValue;
}
public boolean equals (Object obj) {
if (obj instanceof IntegerContainer) {
return this.intValue == ((IntegerContainer) obj).getIntegerValue();
}
return false;
}
public int hashCode() {
return (int) this.intValue;
}
}
}