/*******************************************************************************
* Copyright 2006 - 2012 Vienna University of Technology,
* Department of Software Technology and Interactive Systems, IFS
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This work originates from the Planets project, co-funded by the European Union under the Sixth Framework Programme.
******************************************************************************/
package eu.scape_project.planning.model.beans;
import java.io.Serializable;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import eu.scape_project.planning.model.Alternative;
import eu.scape_project.planning.model.aggregators.IAggregator;
import eu.scape_project.planning.model.sensitivity.ISensitivityAnalysisResult;
import eu.scape_project.planning.model.sensitivity.ISensitivityTest;
import eu.scape_project.planning.model.sensitivity.IWeightModifier;
import eu.scape_project.planning.model.tree.ITreeNode;
import eu.scape_project.planning.model.tree.ITreeWalker;
import eu.scape_project.planning.model.tree.TreeNode;
public class ResultNode implements ITreeNode, Serializable {
/**
*
*/
private static final long serialVersionUID = -8118525873048146001L;
private List<ResultNode> children = new ArrayList<ResultNode>();
private String name;
/**
* Aggregated results per alternative
*/
private HashMap<String, String> resultStrings = new HashMap<String, String>();
private HashMap<String, Double> results = new HashMap<String, Double>();
private static DecimalFormat format = new DecimalFormat("#0.00");
private ResultNode parent = null;
private int id;
private ISensitivityAnalysisResult sensitivityAnalysisResult;
private HashMap<TreeNode, Double> nodeWeights = new HashMap<TreeNode, Double>();
private TreeNode treeNode;
public String getStyle() {
return (isSensitive() ? "sensitiveNode" : (isAnyChildSensitive() ? "sensitiveNodeChildren" : ""));
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public void addChild(ResultNode n) {
children.add(n);
n.setParent(this);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<ResultNode> getChildren() {
return children;
}
public void setChildren(List<ResultNode> children) {
this.children = children;
}
public ResultNode() {
}
private boolean leaf;
public boolean isLeaf() {
return leaf;
}
public void setLeaf(boolean leaf) {
this.leaf = leaf;
}
/**
* Creates a result node for the given TreeNode, applying the given
* aggregator a. - applied to the root node of an objective tree this
* calculates the overall result for each alternative.
*
* @param n
* @param a
* @param alternatives
*/
public ResultNode(TreeNode n, IAggregator a, List<Alternative> alternatives) {
this.treeNode = n;
setName(n.getName());
setId(n.getId());
setLeaf(n.isLeaf());
for (Alternative alt : alternatives) {
double aggregated = a.getAggregatedValue(n, alt);
resultStrings.put(alt.getName(), format.format(aggregated));
results.put(alt.getName(), aggregated);
}
for (TreeNode node : n.getChildren()) {
addChild(new ResultNode(node, a, alternatives));
}
}
public ResultNode getParent() {
return parent;
}
public void setParent(ResultNode parent) {
this.parent = parent;
}
public HashMap<String, Double> getResults() {
return results;
}
public HashMap<String, String> getResultStrings() {
return resultStrings;
}
public void analyseSensitivity(IWeightModifier modificator, ISensitivityTest test) {
if (treeNode.isLeaf()) {
return;
}
saveNodeWeights(treeNode);
test.beforeNode(this);
while (true) {
test.beforeIteration(this);
boolean repeat = modificator.performModification(treeNode);
treeNode.normalizeWeights(false);
test.afterIteration(this);
restoreNodeWeights(treeNode);
if (!repeat) {
break;
}
}
test.afterNode(this);
for (ResultNode child : children) {
child.analyseSensitivity(modificator, test);
}
}
private void saveNodeWeights(TreeNode n) {
nodeWeights.clear();
for (TreeNode child : n.getChildren()) {
nodeWeights.put(child, child.getWeight());
}
}
private void restoreNodeWeights(TreeNode n) {
for (TreeNode child : n.getChildren()) {
child.setWeight(nodeWeights.get(child));
}
}
/**
* Equivalent to isSensitive(false).
*
* @return true if the importance factors (weights) of this node are
* unstable. This means that small changes can result in change in
* ordering of the alternatives. Otherwise false.
*/
public boolean isSensitive() {
return isSensitive(false);
}
/**
* @param recoursive
* if true the direct and indirect children are also inspected.
*
* @return true if the importance factors (weights) of this node are
* unstable. This means that small changes can result in change in
* ordering of the alternatives. Otherwise false.
*/
public boolean isSensitive(boolean recursive) {
if (sensitivityAnalysisResult != null) {
if (sensitivityAnalysisResult.isSensitive()) {
return true;
}
boolean result = false;
if (recursive) {
for (ResultNode child : children) {
result |= child.isAnyChildSensitive();
}
}
return result;
} else {
return false;
}
}
/**
* @return True if any of the children of this node is sensitive.
*/
public boolean isAnyChildSensitive() {
if (sensitivityAnalysisResult != null) {
boolean result = false;
for (ResultNode child : children) {
result |= child.isSensitive(true);
}
return result;
} else {
return false;
}
}
public void setSensitivityAnalysisResult(ISensitivityAnalysisResult analysisResult) {
this.sensitivityAnalysisResult = analysisResult;
}
public ISensitivityAnalysisResult getSensitivityAnalysisResult() {
return sensitivityAnalysisResult;
}
public TreeNode getTreeNode() {
return treeNode;
}
@Override
public void walkTree(ITreeWalker treeWalker) {
treeWalker.walk(this);
for (ResultNode node : children) {
node.walkTree(treeWalker);
}
}
}