/*
* This file is part of ADDIS (Aggregate Data Drug Information System).
* ADDIS is distributed from http://drugis.org/.
* Copyright © 2009 Gert van Valkenhoef, Tommi Tervonen.
* Copyright © 2010 Gert van Valkenhoef, Tommi Tervonen, Tijs Zwinkels,
* Maarten Jacobs, Hanno Koeslag, Florin Schimbinschi, Ahmad Kamal, Daniel
* Reid.
* Copyright © 2011 Gert van Valkenhoef, Ahmad Kamal, Daniel Reid, Florin
* Schimbinschi.
* Copyright © 2012 Gert van Valkenhoef, Daniel Reid, Joël Kuiper, Wouter
* Reckman.
* Copyright © 2013 Gert van Valkenhoef, Joël Kuiper.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.drugis.addis.presentation.wizard;
import static org.drugis.addis.presentation.wizard.TreatmentCategorizationWizardPresentation.findLeafNode;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.apache.commons.collections15.CollectionUtils;
import org.apache.commons.collections15.Predicate;
import org.drugis.addis.ExampleData;
import org.drugis.addis.entities.Domain;
import org.drugis.addis.entities.DomainImpl;
import org.drugis.addis.entities.DoseUnit;
import org.drugis.addis.entities.FixedDose;
import org.drugis.addis.entities.FlexibleDose;
import org.drugis.addis.entities.ScaleModifier;
import org.drugis.addis.entities.UnknownDose;
import org.drugis.addis.entities.treatment.Category;
import org.drugis.addis.entities.treatment.DecisionTreeEdge;
import org.drugis.addis.entities.treatment.DecisionTreeNode;
import org.drugis.addis.entities.treatment.DoseQuantityChoiceNode;
import org.drugis.addis.entities.treatment.LeafNode;
import org.drugis.addis.entities.treatment.RangeEdge;
import org.drugis.addis.entities.treatment.TreatmentCategorization;
import org.junit.Before;
import org.junit.Test;
import com.jgoodies.binding.list.ObservableList;
import edu.uci.ics.jung.graph.util.Pair;
public class TreatmentCategorizationWizardPresentationTest {
private TreatmentCategorization d_bean;
private TreatmentCategorizationWizardPresentation d_pm;
private Domain d_domain;
@Before
public void setUp() {
d_bean = TreatmentCategorization.createDefault("HD/LD", ExampleData.buildDrugCandesartan(), DoseUnit.createMilliGramsPerDay());
d_domain = new DomainImpl();
ExampleData.initDefaultData(d_domain);
d_pm = new TreatmentCategorizationWizardPresentation(d_bean, d_domain);
}
@Test
public void testInitialization() {
assertEquals(ExampleData.buildDrugCandesartan(), d_pm.getDrug().getValue());
assertEquals("HD/LD", d_pm.getName().getValue());
assertEquals(Collections.emptyList(), d_pm.getCategories());
assertTrue(d_pm.getOptionsForUnknownDose().contains(d_pm.getModelForUnknownDose().getValue()));
assertTrue(d_pm.getOptionsForKnownDose().contains(d_pm.getModelForKnownDose().getValue()));
assertTrue(d_pm.getOptionsForFixedDose().contains(d_pm.getModelForFixedDose().getValue()));
assertTrue(d_pm.getOptionsForFlexibleDose().contains(d_pm.getModelForFlexibleDose().getValue()));
}
@Test
public void testMessWithCategories() {
final Category catNode1 = new Category(d_bean, "foo");
final Category catNode2 = new Category(d_bean, "bar");
d_pm.getCategories().add(catNode1);
d_pm.getCategories().add(catNode2);
assertEquals(Arrays.asList(catNode1, catNode2), d_pm.getCategories());
d_pm.getCategories().remove(catNode1);
assertEquals(Arrays.asList(catNode2), d_pm.getCategories());
}
@Test
public void testSplitNodePreservesOptions() {
Category foo = new Category(d_bean, "foo");
d_pm.getCategories().add(foo);
d_pm.getModelForFixedDose().setValue(d_pm.getFixedRangeNode());
RangeEdge edge0 = RangeEdge.createDefault();
ObservableList<DecisionTreeNode> options0 = d_pm.getOptionsForEdge(edge0);
LeafNode child0 = findLeafNode(d_pm.getOptionsForEdge(edge0), foo);
d_pm.getBean().getDecisionTree().addChild(edge0, d_pm.getFixedRangeNode(), child0);
Pair<RangeEdge> splitRange = d_pm.splitRange(edge0, 20.0, false);
assertSame(child0, d_pm.getModelForEdge(splitRange.getFirst()).getValue());
assertSame(options0, d_pm.getOptionsForEdge(splitRange.getFirst()));
assertNotSame(options0, d_pm.getOptionsForEdge(splitRange.getSecond()));
assertTrue(d_pm.getOptionsForEdge(splitRange.getSecond()).contains(d_pm.getModelForEdge(splitRange.getSecond()).getValue()));
}
@Test
public void testUnknownDoseDirectlyToTree() {
Category foo = new Category(d_bean, "foo");
d_pm.getCategories().add(foo);
d_pm.getModelForUnknownDose().setValue(findLeafNode(d_pm.getOptionsForUnknownDose(), foo));
DecisionTreeNode edgeTarget = d_bean.getDecisionTree().getEdgeTarget(d_pm.findTypeEdge(UnknownDose.class));
assertNodeHasCategory(edgeTarget, foo);
}
@Test
public void testKnownDoseNotToTree() {
Category foo = new Category(d_bean, "foo");
d_pm.getCategories().add(foo);
DecisionTreeNode fixedExpected = d_bean.getDecisionTree().getEdgeTarget(d_pm.findTypeEdge(FixedDose.class));
DecisionTreeNode flexibleExpected = d_bean.getDecisionTree().getEdgeTarget(d_pm.findTypeEdge(FixedDose.class));
d_pm.getModelForKnownDose().setValue(findLeafNode(d_pm.getOptionsForKnownDose(), foo));
DecisionTreeNode fixedTarget = d_bean.getDecisionTree().getEdgeTarget(d_pm.findTypeEdge(FixedDose.class));
assertEquals(fixedExpected, fixedTarget);
DecisionTreeNode flexibleTarget = d_bean.getDecisionTree().getEdgeTarget(d_pm.findTypeEdge(FixedDose.class));
assertEquals(flexibleExpected, flexibleTarget);
}
@Test
public void testRewriteWithLeaf() {
Category foo = new Category(d_bean, "foo");
d_pm.getCategories().add(foo);
Category bar = new Category(d_bean, "bar");
d_pm.getCategories().add(bar);
d_pm.getModelForUnknownDose().setValue(findLeafNode(d_pm.getOptionsForUnknownDose(), foo));
d_pm.getModelForKnownDose().setValue(findLeafNode(d_pm.getOptionsForKnownDose(), bar));
d_pm.transformTree();
assertNodeHasCategory(d_bean.getDecisionTree().getEdgeTarget(d_pm.findTypeEdge(UnknownDose.class)), foo);
DecisionTreeNode fixedNode = d_bean.getDecisionTree().getEdgeTarget(d_pm.findTypeEdge(FixedDose.class));
assertNodeHasCategory(fixedNode, bar);
assertTrue(d_pm.getOptionsForFixedDose().contains(fixedNode));
DecisionTreeNode flexibleNode = d_bean.getDecisionTree().getEdgeTarget(d_pm.findTypeEdge(FlexibleDose.class));
assertNodeHasCategory(flexibleNode, bar);
assertTrue(d_pm.getOptionsForFlexibleDose().contains(flexibleNode));
d_pm.getModelForKnownDose().setValue(findLeafNode(d_pm.getOptionsForKnownDose(), null));
d_pm.transformTree();
fixedNode = d_bean.getDecisionTree().getEdgeTarget(d_pm.findTypeEdge(FixedDose.class));
flexibleNode = d_bean.getDecisionTree().getEdgeTarget(d_pm.findTypeEdge(FlexibleDose.class));
assertNodeHasCategory(fixedNode, null);
assertNodeHasCategory(flexibleNode, null);
}
@Test
public void testRewriteDoNotConsiderDoseType() {
Category foo = new Category(d_bean, "foo");
d_pm.getCategories().add(foo);
Category bar = new Category(d_bean, "bar");
d_pm.getCategories().add(bar);
d_pm.getModelForKnownDose().setValue(TreatmentCategorizationWizardPresentation.CategorySpecifiers.DO_NOT_CONSIDER);
d_pm.getModelForFixedDose().setValue(d_pm.getFixedRangeNode());
// Add ranges to tree (normally handled by RangeInputPresentation).
RangeEdge edge0 = RangeEdge.createDefault();
d_pm.getBean().getDecisionTree().addChild(edge0, d_pm.getFixedRangeNode(), findLeafNode(d_pm.getOptionsForEdge(edge0), bar));
Pair<RangeEdge> splitRange = d_pm.splitRange(edge0, 20.0, false);
d_pm.getModelForEdge(splitRange.getSecond()).setValue(findLeafNode(d_pm.getOptionsForEdge(splitRange.getSecond()), foo));
d_pm.transformTree();
// The transformed tree should consider MIN_DOSE first.
assertEquals(d_pm.getFlexibleLowerRangeNode(), d_pm.getModelForFlexibleDose().getValue());
// The ranges for MIN_DOSE should be identical to those for FixedDose
List<DecisionTreeEdge> lowerEdges = d_pm.getFlexibleLowerRanges();
ObservableList<DecisionTreeEdge> fixedEdges = d_pm.getOutEdges(d_pm.getFixedRangeNode());
assertEquals(2, lowerEdges.size());
assertEquals(fixedEdges.get(0).toString(), lowerEdges.get(0).toString());
assertEquals(fixedEdges.get(1).toString(), lowerEdges.get(1).toString());
for (int i = 0; i < lowerEdges.size(); i++) {
RangeEdge fixedRange = (RangeEdge) fixedEdges.get(i);
RangeEdge lowerRange = (RangeEdge) lowerEdges.get(i);
DoseQuantityChoiceNode upper = (DoseQuantityChoiceNode) d_pm.getModelForEdge(lowerRange).getValue();
// FIXME: test that the node is in the options list.
// For each MIN_DOSE range, the MAX_DOSE should subsequently be considered
assertEquals(FlexibleDose.class, upper.getBeanClass());
assertEquals(FlexibleDose.PROPERTY_MAX_DOSE, upper.getPropertyName());
assertSame(d_bean.getDoseUnit(), upper.getDoseUnit());
// There should be two out-edges, unless the upper bound is +infinity
List<DecisionTreeEdge> upperEdges = d_pm.getOutEdges(upper);
assertEquals(lowerRange.toString(), upperEdges.get(0).toString());
assertNodeHasCategory(
(DecisionTreeNode) d_pm.getModelForEdge(upperEdges.get(0)).getValue(),
((LeafNode)d_pm.getModelForEdge(fixedRange).getValue()).getCategory());
if (!Double.isInfinite(lowerRange.getUpperBound())) {
assertEquals(2, upperEdges.size());
RangeEdge expected = new RangeEdge(lowerRange.getUpperBound(), !lowerRange.isUpperBoundOpen(), Double.POSITIVE_INFINITY, true);
assertEquals(expected.toString(), upperEdges.get(1).toString());
assertNodeHasCategory(
(DecisionTreeNode) d_pm.getModelForEdge(upperEdges.get(1)).getValue(),
null);
} else {
assertEquals(1, upperEdges.size());
}
}
}
@Test
public void testRewriteDoNotConsiderDoseTypeWithExclusion() {
Category bar = new Category(d_bean, "bar");
d_pm.getCategories().add(bar);
d_pm.getModelForKnownDose().setValue(TreatmentCategorizationWizardPresentation.CategorySpecifiers.DO_NOT_CONSIDER);
d_pm.getModelForFixedDose().setValue(d_pm.getFixedRangeNode());
// Add ranges to tree (normally handled by RangeInputPresentation).
RangeEdge edge0 = RangeEdge.createDefault();
d_pm.getBean().getDecisionTree().addChild(edge0, d_pm.getFixedRangeNode(), findLeafNode(d_pm.getOptionsForEdge(edge0), null));
Pair<RangeEdge> splitRange = d_pm.splitRange(edge0, 20.0, false);
d_pm.getModelForEdge(splitRange.getSecond()).setValue(findLeafNode(d_pm.getOptionsForEdge(splitRange.getSecond()), bar));
d_pm.transformTree();
// The lower range is excluded anyway, so don't split on MAX_DOSE.
DoseQuantityChoiceNode upper = (DoseQuantityChoiceNode) d_pm.getModelForEdge(d_pm.getFlexibleLowerRanges().get(0)).getValue();
ObservableList<DecisionTreeEdge> edges = d_pm.getOutEdges(upper);
assertEquals(1, edges.size());
RangeEdge edge = (RangeEdge) edges.get(0);
RangeEdge expected = new RangeEdge(0.0, false, Double.POSITIVE_INFINITY, true);
assertEquals(expected.toString(), edge.toString());
assertNodeHasCategory((DecisionTreeNode) d_pm.getModelForEdge(edge).getValue(), null);
}
@Test
public void testFlexibleDoseNodeChaining() {
// If MIN_DOSE is considered first, allow MAX_DOSE next
d_pm.getModelForFlexibleDose().setValue(d_pm.getFlexibleLowerRangeNode());
RangeEdge edge1 = d_pm.addDefaultRangeEdge(d_pm.getFlexibleLowerRangeNode());
assertNull(findDoseQuantityNode(d_pm.getOptionsForEdge(edge1), FlexibleDose.PROPERTY_MIN_DOSE));
assertNotNull(findDoseQuantityNode(d_pm.getOptionsForEdge(edge1), FlexibleDose.PROPERTY_MAX_DOSE));
assertTrue(d_pm.getOptionsForEdge(edge1).contains(d_pm.getModelForEdge(edge1).getValue()));
// If MAX_DOSE is considered first, allow MIN_DOSE next
d_pm.getModelForFlexibleDose().setValue(d_pm.getFlexibleUpperRangeNode());
RangeEdge edge2 = d_pm.addDefaultRangeEdge(d_pm.getFlexibleUpperRangeNode());
assertNotNull(findDoseQuantityNode(d_pm.getOptionsForEdge(edge2), FlexibleDose.PROPERTY_MIN_DOSE));
assertNull(findDoseQuantityNode(d_pm.getOptionsForEdge(edge2), FlexibleDose.PROPERTY_MAX_DOSE));
assertTrue(d_pm.getOptionsForEdge(edge2).contains(d_pm.getModelForEdge(edge2).getValue()));
// No MIN_DOSE / MAX_DOSE for fixed dose nodes
d_pm.getModelForFixedDose().setValue(d_pm.getFixedRangeNode());
RangeEdge edge3 = d_pm.addDefaultRangeEdge(d_pm.getFixedRangeNode());
assertNull(findDoseQuantityNode(d_pm.getOptionsForEdge(edge3), FlexibleDose.PROPERTY_MIN_DOSE));
assertNull(findDoseQuantityNode(d_pm.getOptionsForEdge(edge3), FlexibleDose.PROPERTY_MAX_DOSE));
assertTrue(d_pm.getOptionsForEdge(edge3).contains(d_pm.getModelForEdge(edge3).getValue()));
// If MAX_DOSE is considered first, and MIN_DOSE is considered second, no further extra options
DoseQuantityChoiceNode lower2 = findDoseQuantityNode(d_pm.getOptionsForEdge(edge2), FlexibleDose.PROPERTY_MIN_DOSE);
d_pm.getModelForEdge(edge2).setValue(lower2);
RangeEdge edge4 = d_pm.addDefaultRangeEdge(lower2);
assertNull(findDoseQuantityNode(d_pm.getOptionsForEdge(edge4), FlexibleDose.PROPERTY_MIN_DOSE));
assertNull(findDoseQuantityNode(d_pm.getOptionsForEdge(edge4), FlexibleDose.PROPERTY_MAX_DOSE));
assertTrue(d_pm.getOptionsForEdge(edge4).contains(d_pm.getModelForEdge(edge4).getValue()));
}
@Test
public void testFlexibleDoseNodeChainingOnSplit() {
// If MIN_DOSE is considered first, allow MAX_DOSE next
d_pm.getModelForFlexibleDose().setValue(d_pm.getFlexibleLowerRangeNode());
RangeEdge edge0 = d_pm.addDefaultRangeEdge(d_pm.getFlexibleLowerRangeNode());
Pair<RangeEdge> splitRange = d_pm.splitRange(edge0, 20.0, false);
RangeEdge edge1 = splitRange.getFirst();
RangeEdge edge2 = splitRange.getSecond();
assertNull(findDoseQuantityNode(d_pm.getOptionsForEdge(edge1), FlexibleDose.PROPERTY_MIN_DOSE));
assertNotNull(findDoseQuantityNode(d_pm.getOptionsForEdge(edge1), FlexibleDose.PROPERTY_MAX_DOSE));
assertTrue(d_pm.getOptionsForEdge(edge1).contains(d_pm.getModelForEdge(edge1).getValue()));
assertNull(findDoseQuantityNode(d_pm.getOptionsForEdge(edge2), FlexibleDose.PROPERTY_MIN_DOSE));
assertNotNull(findDoseQuantityNode(d_pm.getOptionsForEdge(edge2), FlexibleDose.PROPERTY_MAX_DOSE));
assertTrue(d_pm.getOptionsForEdge(edge2).contains(d_pm.getModelForEdge(edge2).getValue()));
}
private static DoseQuantityChoiceNode findDoseQuantityNode(ObservableList<DecisionTreeNode> options, final String propertyName) {
return (DoseQuantityChoiceNode) CollectionUtils.find(options, new Predicate<DecisionTreeNode>() {
public boolean evaluate(DecisionTreeNode object) {
if (object instanceof DoseQuantityChoiceNode) {
DoseQuantityChoiceNode node = (DoseQuantityChoiceNode) object;
return propertyName.equals(node.getPropertyName());
}
return false;
}
});
}
private static void assertNodeHasCategory(DecisionTreeNode node, Category category) {
assertTrue(node instanceof LeafNode);
assertEquals(category, ((LeafNode)node).getCategory());
}
/*
* Regression test for bug #566
*/
@Test
public void testDoNotReuseDefaultDose() {
TreatmentCategorizationWizardPresentation pm1 = new TreatmentCategorizationWizardPresentation(TreatmentCategorization.createDefault(), d_domain);
TreatmentCategorizationWizardPresentation pm2 = new TreatmentCategorizationWizardPresentation(TreatmentCategorization.createDefault(), d_domain);
pm1.getDoseUnit().setScaleModifier(ScaleModifier.MEGA);
assertFalse(pm2.getDoseUnit().equals(pm1.getDoseUnit()));
}
}