/* * 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 java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.TreeSet; import javax.swing.event.ListDataEvent; import javax.swing.event.ListDataListener; import org.apache.commons.collections15.Predicate; import org.drugis.addis.entities.Indication; import org.drugis.addis.entities.OutcomeMeasure; import org.drugis.addis.entities.analysis.BenefitRiskAnalysis; import org.drugis.addis.entities.analysis.BenefitRiskAnalysis.AnalysisType; import org.drugis.addis.entities.analysis.DecisionContext; import org.drugis.addis.entities.analysis.MetaAnalysis; import org.drugis.addis.entities.analysis.MetaBenefitRiskAnalysis; import org.drugis.addis.entities.treatment.TreatmentDefinition; import org.drugis.addis.presentation.ModifiableHolder; import org.drugis.addis.presentation.ValueHolder; import org.drugis.common.beans.AbstractObservable; import org.drugis.common.beans.ContentAwareListModel; import org.drugis.common.beans.FilteredObservableList; import org.drugis.common.beans.SortedSetModel; import org.drugis.common.beans.TransformedObservableList; import org.drugis.common.beans.TransformedObservableList.Transform; import org.drugis.common.validation.BooleanAndModel; import com.jgoodies.binding.list.ArrayListModel; import com.jgoodies.binding.list.ObservableList; import com.jgoodies.binding.value.AbstractValueModel; import com.jgoodies.binding.value.ValueModel; public class MetaCriteriaAndAlternativesPresentation extends CriteriaAndAlternativesPresentation<TreatmentDefinition> { private final class AutoSelectMetaAnalysisListener implements ListDataListener { public void intervalRemoved(ListDataEvent e) { } public void intervalAdded(ListDataEvent e) { autoSelectInterval(e.getIndex0(), e.getIndex1()); } public void contentsChanged(ListDataEvent e) { autoSelectInterval(e.getIndex0(), e.getIndex1()); } private void autoSelectInterval(int index0, int index1) { for (int i = index0; i <= index1; ++i) { OutcomeMeasure crit = getSelectedCriteria().get(i); CriterionAnalysisPair pair = findCriterionAnalysisPair(crit); if (pair.getAnalysis() == null) { pair.setAnalysis(getDefaultMetaAnalysis(crit)); } } } } private static class CriterionAnalysisPair extends AbstractObservable { public static final String PROPERTY_ANALYSIS = "analysis"; private final OutcomeMeasure d_criterion; private ModifiableHolder<MetaAnalysis> d_analysis; public CriterionAnalysisPair(OutcomeMeasure criterion, MetaAnalysis analysis) { d_criterion = criterion; d_analysis = new ModifiableHolder<MetaAnalysis>(analysis); d_analysis.addPropertyChangeListener(new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { firePropertyChange(PROPERTY_ANALYSIS, evt.getOldValue(), evt.getNewValue()); } }); } public OutcomeMeasure getCriterion() { return d_criterion; } public MetaAnalysis getAnalysis() { return d_analysis.getValue(); } public ValueHolder<MetaAnalysis> getAnalysisModel() { return d_analysis; } public void setAnalysis(MetaAnalysis ma) { d_analysis.setValue(ma); } } private class CriteriaHaveAnalysisModel extends AbstractValueModel implements ValueModel { private static final long serialVersionUID = 5940166304699871730L; private boolean d_value; public CriteriaHaveAnalysisModel() { ListDataListener myListener = new ListDataListener() { public void intervalRemoved(ListDataEvent e) { update(); } public void intervalAdded(ListDataEvent e) { update(); } public void contentsChanged(ListDataEvent e) { update(); } }; getSelectedCriteria().addListDataListener(myListener); d_selectedMetaAnalysesPairs.addListDataListener(myListener); } private void update() { boolean newValue = calculate(); if (d_value != newValue) { boolean oldValue = d_value; d_value = newValue; fireValueChange(oldValue, newValue); } } private boolean calculate() { for (OutcomeMeasure crit : getSelectedCriteria()) { if (getMetaAnalysesSelectedModel(crit).getValue() == null) { return false; } } return true; } public Object getValue() { return d_value; } public void setValue(Object newValue) { } } private class OutcomeMeasureFilter implements Predicate<MetaAnalysis> { private final OutcomeMeasure d_om; public OutcomeMeasureFilter(OutcomeMeasure om) { d_om = om; } public boolean evaluate(MetaAnalysis ma) { return ma.getOutcomeMeasure().equals(d_om); } } public static class IndicationFilter implements Predicate<MetaAnalysis> { private final Indication d_indication; public IndicationFilter(Indication i) { d_indication = i; } public boolean evaluate(MetaAnalysis ma) { return ma.getIndication().equals(d_indication); } } private final ObservableList<OutcomeMeasure> d_availableCriteria; private final ObservableList<OutcomeMeasure> d_metaAnalysesCriteria; private final FilteredObservableList<MetaAnalysis> d_metaAnalyses; private final ObservableList<CriterionAnalysisPair> d_selectedMetaAnalysesPairs; private final ValueModel d_metaCompleteModel; private ObservableList<MetaAnalysis> d_selectedMetaAnalyses; public MetaCriteriaAndAlternativesPresentation(ValueHolder<Indication> indication, ModifiableHolder<AnalysisType> analysisType, SortedSetModel<MetaAnalysis> metaAnalyses) { super(indication, analysisType); d_metaAnalyses = new FilteredObservableList<MetaAnalysis>(metaAnalyses, new IndicationFilter(d_indicationModel.getValue())); d_metaAnalysesCriteria = new TransformedObservableList<MetaAnalysis, OutcomeMeasure>(d_metaAnalyses, new Transform<MetaAnalysis, OutcomeMeasure>() { public OutcomeMeasure transform(MetaAnalysis a) { return a.getOutcomeMeasure(); } }); d_availableCriteria = new SortedSetModel<OutcomeMeasure>(); d_metaAnalysesCriteria.addListDataListener(new ListDataListener() { public void intervalRemoved(ListDataEvent e) { updateCriteria(); } public void intervalAdded(ListDataEvent e) { updateCriteria(); } public void contentsChanged(ListDataEvent e) { updateCriteria(); } }); d_selectedMetaAnalysesPairs = new ContentAwareListModel<CriterionAnalysisPair>(new ArrayListModel<CriterionAnalysisPair>(), new String[] {CriterionAnalysisPair.PROPERTY_ANALYSIS}); // Filter the CriterionAnalysisPair list to include only selected criteria. final Predicate<CriterionAnalysisPair> criterionSelectedFilter = new Predicate<CriterionAnalysisPair>() { public boolean evaluate(CriterionAnalysisPair obj) { return getSelectedCriteria().contains(obj.getCriterion()); } }; final FilteredObservableList<CriterionAnalysisPair> pairsWithIncludedCriterion = new FilteredObservableList<CriterionAnalysisPair>(d_selectedMetaAnalysesPairs, criterionSelectedFilter); // Re-calculate the filtered list when the selected criteria change. getSelectedCriteria().addListDataListener(new ListDataListener() { public void intervalRemoved(ListDataEvent e) { update(); } public void intervalAdded(ListDataEvent e) { update(); } public void contentsChanged(ListDataEvent e) { update(); } private void update() { pairsWithIncludedCriterion.setFilter(criterionSelectedFilter); } }); d_selectedMetaAnalyses = new TransformedObservableList<CriterionAnalysisPair, MetaAnalysis>(pairsWithIncludedCriterion, new Transform<CriterionAnalysisPair, MetaAnalysis>() { public MetaAnalysis transform(CriterionAnalysisPair pair) { return pair.getAnalysis(); } }); d_selectedMetaAnalysesPairs.addListDataListener(d_resetAlternativeEnabledModelsListener); ValueModel criteriaHaveAnalysisModel = new CriteriaHaveAnalysisModel(); d_metaCompleteModel = new BooleanAndModel(d_completeModel, criteriaHaveAnalysisModel); getSelectedCriteria().addListDataListener(new AutoSelectMetaAnalysisListener()); } public ObservableList<MetaAnalysis> getSelectedMetaAnalyses() { return d_selectedMetaAnalyses; } protected void updateCriteria() { d_availableCriteria.clear(); d_availableCriteria.addAll(d_metaAnalysesCriteria); } @Override public BenefitRiskAnalysis<TreatmentDefinition> createAnalysis(String id, DecisionContext context) { TreatmentDefinition baseline = d_baselineModel.getValue(); List<TreatmentDefinition> alternatives = new ArrayList<TreatmentDefinition>(getSelectedAlternatives()); alternatives.remove(baseline); return new MetaBenefitRiskAnalysis( id, d_indicationModel.getValue(), getSelectedMetaAnalyses(), baseline, alternatives, d_analysisTypeHolder.getValue(), context); } @Override public ValueModel getCompleteModel() { return d_metaCompleteModel; } @Override public ObservableList<OutcomeMeasure> getCriteriaListModel() { return d_availableCriteria; } @Override protected void reset() { // selected criteria have to be cleared before availableCriteria and selectedMetaAnalyses d_selectedCriteria.clear(); d_selectedAlternatives.clear(); d_selectedMetaAnalysesPairs.clear(); d_baselineModel.setValue(null); d_availableCriteria.clear(); d_availableAlternatives.clear(); if (d_indicationModel.getValue() != null) { initializeValues(); } } private void initializeValues() { d_metaAnalyses.setFilter(new IndicationFilter(d_indicationModel.getValue())); initCriteria(); initAlternatives(getAlternatives()); for (OutcomeMeasure om : getCriteriaListModel()) { d_selectedMetaAnalysesPairs.add(new CriterionAnalysisPair(om, null)); } } private MetaAnalysis getDefaultMetaAnalysis(OutcomeMeasure om) { ObservableList<MetaAnalysis> metaAnalyses = getMetaAnalyses(om); return metaAnalyses.size() == 1 ? metaAnalyses.get(0) : null; } private Set<TreatmentDefinition> getAlternatives() { Set<TreatmentDefinition> alternatives = new TreeSet<TreatmentDefinition>(); for(MetaAnalysis ma : d_metaAnalyses) { if(ma.getIndication() == d_indicationModel.getValue()) alternatives.addAll(ma.getAlternatives()); } return alternatives; } public ObservableList<MetaAnalysis> getMetaAnalyses(OutcomeMeasure om) { return new FilteredObservableList<MetaAnalysis>(d_metaAnalyses, new OutcomeMeasureFilter(om)); } public ValueHolder<MetaAnalysis> getMetaAnalysesSelectedModel(OutcomeMeasure om) { return findCriterionAnalysisPair(om).getAnalysisModel(); } private CriterionAnalysisPair findCriterionAnalysisPair(OutcomeMeasure om) { for (CriterionAnalysisPair pair : d_selectedMetaAnalysesPairs) { if (pair.getCriterion().equals(om)) { return pair; } } return null; } @Override protected boolean getAlternativeShouldBeEnabled(TreatmentDefinition alternative) { if (!super.getAlternativeShouldBeEnabled(alternative)) { return false; } return getAlternativeIncludedInAllSelectedAnalyses((TreatmentDefinition) alternative); } private boolean getAlternativeIncludedInAllSelectedAnalyses(TreatmentDefinition alternative) { boolean noAnalysesSelected = true; List<OutcomeMeasure> selectedCriteria = getSelectedCriteria(); for (CriterionAnalysisPair pair : d_selectedMetaAnalysesPairs) { if (selectedCriteria.contains(pair.getCriterion()) && pair.getAnalysis() != null) { noAnalysesSelected = false; if (!pair.getAnalysis().getAlternatives().contains(alternative)) { return false; } } } return !noAnalysesSelected; } }