/*******************************************************************************
* 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.
******************************************************************************/
package eu.scape_project.planning.criteria.bean;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import eu.scape_project.planning.model.TargetValueObject;
import eu.scape_project.planning.model.kbrowser.CriteriaLeaf;
import eu.scape_project.planning.model.kbrowser.VPlanLeaf;
import eu.scape_project.planning.model.measurement.Attribute;
import eu.scape_project.planning.model.measurement.CriterionCategory;
import eu.scape_project.planning.model.measurement.Measure;
import eu.scape_project.planning.model.transform.NumericTransformer;
import eu.scape_project.planning.model.transform.OrdinalTransformer;
import eu.scape_project.planning.model.transform.TransformationMode;
import eu.scape_project.planning.model.transform.Transformer;
import eu.scape_project.planning.model.values.INumericValue;
import eu.scape_project.planning.model.values.IOrdinalValue;
import eu.scape_project.planning.model.values.Value;
/**
* Class responsible for calculating statistics for KBrowser.
*
* @author Markus Hamm
*/
public class KBrowserCalculator implements Serializable {
private static final long serialVersionUID = 3798396219762966856L;
/**
* List of all plan leaves.
*/
private List<VPlanLeaf> planLeaves;
/**
* List of plan leaves which are mapped to measures.
*/
private List<VPlanLeaf> mappedPlanLeaves;
/**
* List of plan leaves for a specified measure.
*/
private List<VPlanLeaf> measurePlanLeaves;
/**
* variable responsible for calculating aggregated criteria impact factors.
*/
private CriteriaLeaf criteriaAggregator;
public KBrowserCalculator(List<VPlanLeaf> planLeaves, Long nrRelevantPlans) {
this.planLeaves = planLeaves;
// will be updated as soon as a criterion is selected
this.measurePlanLeaves = new ArrayList<VPlanLeaf>();
this.criteriaAggregator = new CriteriaLeaf(nrRelevantPlans);
filterMappedLeaves();
}
/**
* Updates the mapped plan leaf list from all plan leaves filtering all
* unmapped leaves.
*/
private void filterMappedLeaves() {
// filter mapped PlanLeaves
mappedPlanLeaves = new ArrayList<VPlanLeaf>(planLeaves.size());
for (VPlanLeaf pl : planLeaves) {
if (pl.isMapped()) {
mappedPlanLeaves.add(pl);
}
}
}
/**
* Method responsible for filtering all leaves which match the given
* criterion.
*/
public void filterMeasure(Measure m) {
// Reset criterion lists
measurePlanLeaves.clear();
// Filter PlanLeaves
for (VPlanLeaf l : mappedPlanLeaves) {
if (l.getMeasure().getUri().equals(m.getUri())) {
measurePlanLeaves.add(l);
}
}
criteriaAggregator.setPlanLeaves(measurePlanLeaves);
}
/**
* Returns the number of plan leaves.
*
* @return the number of plan leaves
*/
public int getNrPlanLeaves() {
return planLeaves.size();
}
/**
* Returns the number of mapped plan leaves.
*
* @return the number of mapped plan leaves.
*/
public int getNrMappedPlanLeaves() {
return mappedPlanLeaves.size();
}
/**
* Returns the number of measures that are used in at least on plan leaf.
*
* @return number of used measures
*/
public int getNrCriteriaUsedAtLeastOnce() {
HashMap<String, String> mappedMeasures = new HashMap<String, String>();
for (VPlanLeaf l : mappedPlanLeaves) {
mappedMeasures.put(l.getMeasure().getUri(), l.getMeasure().getUri());
}
return mappedMeasures.size();
}
/**
* Returns the number of plan leaves that are mapped to a measure in the
* provided category.
*
* @param category
* category to filter for or null for any category.
* @return the number of plan leaves having the given category assigned.
*/
public int getNrPlanLeavesInCategory(CriterionCategory category) {
if (category == null) {
return mappedPlanLeaves.size();
}
int count = 0;
for (VPlanLeaf l : mappedPlanLeaves) {
if (l.getMeasure().getAttribute().getCategory().getUri().equals(category.getUri())) {
count++;
}
}
return count;
}
/**
* Method responsible for counting the plan leaves having the given property
* assigned, giving no respect to the fact if the property is measurable or
* not or if a metric is assigned or not.
*
* @param attribute
* property to filter for or null for all properties
*/
public int getNrPlanLeavesUsingProperty(Attribute attribute) {
if (attribute == null) {
return mappedPlanLeaves.size();
}
int count = 0;
for (VPlanLeaf l : mappedPlanLeaves) {
if (l.getMeasure().getAttribute().getUri().equals(attribute.getUri())) {
count++;
}
}
return count;
}
/**
* Returns the number of plan leaves that are mapped to the set measure.
*
* @return the number of plan leaves
*/
public int getNrCriterionPlanLeaves() {
return measurePlanLeaves.size();
}
/**
* Returns the average weight of the plan leaves that are mapped to the set
* measure.
*
* @return the average weight
*/
public double getCPLAverageWeight() {
double sum = 0;
int count = 0;
for (VPlanLeaf l : measurePlanLeaves) {
sum = sum + l.getWeight();
count++;
}
if (count > 0) {
return sum / count;
} else {
return 0;
}
}
/**
* Returns the number of measurements of the set measure.
*
* @return the number of measurements
*/
public int getNrCPLMeasurementsObtained() {
int count = 0;
for (VPlanLeaf l : measurePlanLeaves) {
count = count + l.getMeasuredValues().size();
}
return count;
}
/**
* Method responsible for returning the minimum numeric measurement of
* criterion plan leaves.
*
* @return 0 if no numeric measurements are found. Otherwise minimum numeric
* measurment of criterion plan leaves is returned.
*/
public double getCPLNumericMeasurementsMin() {
Boolean atLeastOneMeasuredValue = false;
double min = Double.MAX_VALUE;
for (VPlanLeaf l : measurePlanLeaves) {
for (Value val : l.getMeasuredValues()) {
if (val instanceof INumericValue) {
atLeastOneMeasuredValue = true;
INumericValue numVal = (INumericValue) val;
if (numVal.value() < min) {
min = numVal.value();
}
}
}
}
if (atLeastOneMeasuredValue) {
return min;
} else {
return 0;
}
}
/**
* Method responsible for returning the maximum numeric measurment of
* criterion plan leaves.
*
* @return 0 if no numeric measurements are found. Otherwise maximum numeric
* measurment of criterion plan leaves is returned.
*/
public double getCPLNumericMeasurementsMax() {
Boolean atLeastOneMeasuredValue = false;
double max = -Double.MAX_VALUE;
for (VPlanLeaf l : measurePlanLeaves) {
for (Value val : l.getMeasuredValues()) {
if (val instanceof INumericValue) {
atLeastOneMeasuredValue = true;
INumericValue numVal = (INumericValue) val;
if (numVal.value() > max) {
max = numVal.value();
}
}
}
}
if (atLeastOneMeasuredValue) {
return max;
} else {
return 0;
}
}
/**
* Method responsible for returning the avarage numeric measurment of
* criterion plan leaves.
*
* @return 0 if no numeric measurements are found. Otherwise average numeric
* measurment of criterion plan leaves is returned.
*/
public double getCPLNumericMeasurementsAvg() {
int count = 0;
double sum = 0d;
for (VPlanLeaf l : measurePlanLeaves) {
for (Value val : l.getMeasuredValues()) {
if (val instanceof INumericValue) {
count++;
INumericValue numVal = (INumericValue) val;
sum = sum + numVal.value();
}
}
}
if (count > 0) {
return sum / count;
} else {
return 0;
}
}
/**
* Method responsible for returning all ordinal MeasuredValues + the number
* of occurrence.
*
* @return A list of Strings in the form "MeasuredValue : #occurrence".
*/
public Map<String, Integer> getCPLOrdinalMeasurements() {
Map<String, Integer> measuredOrdinalValues = new HashMap<String, Integer>();
// List<String> ordinalMeasurements = new ArrayList<String>();
// collect ordinal values
// We have to lower-case values here to get reasonable results (in plans
// upper- and lower-case strings are used)
for (VPlanLeaf l : measurePlanLeaves) {
for (Value val : l.getMeasuredValues()) {
if (val instanceof IOrdinalValue) {
IOrdinalValue valOrd = (IOrdinalValue) val;
String ordinalString = new String(valOrd.getValue().toLowerCase());
if (measuredOrdinalValues.containsKey(ordinalString)) {
Integer oldV = measuredOrdinalValues.get(ordinalString);
measuredOrdinalValues.put(ordinalString, oldV + 1);
} else {
measuredOrdinalValues.put(ordinalString, 1);
}
}
}
}
// // Convert Map<String, Integer> into List<String> with all
// information encoded.
// // This is done for output in UI - because in JSF it is hard to
// output a Map.
// for (String key : measuredOrdinalValues.keySet()) {
// ordinalMeasurements.add(key + " : " +
// measuredOrdinalValues.get(key));
// }
//
// return ordinalMeasurements;
return measuredOrdinalValues;
}
/**
* Method responsible for creating a table including all
* transformer-mappings.
*
* @return table including all transformer-mappings.
*/
public KBrowserTransformerTable getCPSTransformerTable() {
KBrowserTransformerTable table = new KBrowserTransformerTable();
for (VPlanLeaf l : measurePlanLeaves) {
Transformer trans = l.getTransformer();
if (trans == null) {
continue;
}
// OrdinalTransformer
if (trans instanceof OrdinalTransformer) {
table.setOrdinal(true);
OrdinalTransformer oTrans = (OrdinalTransformer) trans;
Map<String, TargetValueObject> oTransMapping = oTrans.getMapping();
Map<Double, String> tableMapping = new HashMap<Double, String>();
for (String str : oTransMapping.keySet()) {
Double tv = oTransMapping.get(str).getValue();
table.addTargetValue(tv);
if (tableMapping.containsKey(tv)) {
String oldValue = tableMapping.get(tv);
String newValue = oldValue + ", " + str;
tableMapping.put(tv, newValue);
} else {
tableMapping.put(tv, str);
}
}
table.addTransformerMapping(tableMapping, "mappings");
}
// NumericTransformer
if (trans instanceof NumericTransformer) {
table.setOrdinal(false);
// numeric transformer always have the same thresholds - fixed
// set
table.addTargetValue(1.0);
table.addTargetValue(2.0);
table.addTargetValue(3.0);
table.addTargetValue(4.0);
table.addTargetValue(5.0);
NumericTransformer nTrans = (NumericTransformer) trans;
Map<Double, String> tableMapping = new HashMap<Double, String>();
tableMapping.put(1.0, nTrans.getThreshold1().toString());
tableMapping.put(2.0, nTrans.getThreshold2().toString());
tableMapping.put(3.0, nTrans.getThreshold3().toString());
tableMapping.put(4.0, nTrans.getThreshold4().toString());
tableMapping.put(5.0, nTrans.getThreshold5().toString());
TransformationMode tMode = nTrans.getMode();
table.addTransformerMapping(tableMapping, "thresholds (" + tMode.getName().toLowerCase() + ")");
}
}
return table;
}
/**
* Method responsible for returning all criterion plan leaves - evaluations.
*
* @return all criterion plan leaves - evaluations.
*/
public List<Double> getCPLEvaluations() {
List<Double> evaluations = new ArrayList<Double>();
// for each leaf transform its measured values into transformed values
for (VPlanLeaf l : measurePlanLeaves) {
evaluations.addAll(l.getAlternativeResults());
}
return evaluations;
}
// ---------- Impact Factors ----------
public double getCPL_IF1() {
return criteriaAggregator.getImportanceFactorIF1();
}
public double getCPL_IF2() {
return criteriaAggregator.getImportanceFactorIF2();
}
public double getCPL_IF3() {
return criteriaAggregator.getImportanceFactorIF3();
}
public double getCPL_IF4() {
return criteriaAggregator.getImportanceFactorIF4();
}
public double getCPL_IF5() {
return criteriaAggregator.getImportanceFactorIF5();
}
public double getCPL_IF6() {
return criteriaAggregator.getImportanceFactorIF6();
}
public double getCPL_IF7() {
return criteriaAggregator.getImportanceFactorIF7();
}
public double getCPL_IF8() {
return criteriaAggregator.getImportanceFactorIF8();
}
public double getCPL_IF9() {
return criteriaAggregator.getImportanceFactorIF9();
}
public double getCPL_IF10() {
return criteriaAggregator.getImportanceFactorIF10();
}
public double getCPL_IF11() {
return criteriaAggregator.getImportanceFactorIF11();
}
public double getCPL_IF12() {
return criteriaAggregator.getImportanceFactorIF12();
}
public double getCPL_IF13() {
return criteriaAggregator.getImportanceFactorIF13();
}
public double getCPL_IF14() {
return criteriaAggregator.getImportanceFactorIF14();
}
public double getCPL_IF15() {
return criteriaAggregator.getImportanceFactorIF15();
}
public double getCPL_IF16() {
return criteriaAggregator.getImportanceFactorIF16();
}
public double getCPL_IF17() {
return criteriaAggregator.getImportanceFactorIF17();
}
public double getCPL_IF18() {
return criteriaAggregator.getImportanceFactorIF18();
}
}