/**
   * Merges a collection of map data sets
   *
   * @param dataSets the data sets
   * @return the merged data set
   */
  protected MapDataSet mergeDataSets(
      List<MapDataSet> dataSets,
      MergingDataSetDefinition dataSetDefinition,
      EvaluationContext context) {
    MapDataSet ret = new MapDataSet(dataSetDefinition, context);

    List<DataSetColumn> columns = new ArrayList<DataSetColumn>();

    // Gather all columns from all contained data sets
    for (DataSet dataSet : dataSets) {
      for (DataSetColumn column : dataSet.getMetaData().getColumns()) {
        columns.add(column);
      }
    }

    // Sort the columns according to the merge order
    if (MergingDataSetDefinition.MergeOrder.NAME.equals(dataSetDefinition.getMergeOrder())) {
      Collections.sort(
          columns,
          new Comparator<DataSetColumn>() {
            @Override
            public int compare(DataSetColumn column1, DataSetColumn column2) {
              return OpenmrsUtil.compareWithNullAsGreatest(column1.getName(), column2.getName());
            }
          });
    } else if (MergingDataSetDefinition.MergeOrder.LABEL.equals(
        dataSetDefinition.getMergeOrder())) {
      Collections.sort(
          columns,
          new Comparator<DataSetColumn>() {
            @Override
            public int compare(DataSetColumn column1, DataSetColumn column2) {
              return OpenmrsUtil.compareWithNullAsGreatest(column1.getLabel(), column2.getLabel());
            }
          });
    }

    ret.getMetaData().setColumns(columns);

    // Gather column data values from all contained data sets
    for (MapDataSet dataSet : dataSets) {
      for (DataSetColumn column : dataSet.getMetaData().getColumns()) {
        ret.addData(column, getDataSetData(dataSet, column));
      }
    }

    return ret;
  }
  /**
   * @see
   *     DataSetEvaluator#evaluate(org.openmrs.module.reporting.dataset.definition.DataSetDefinition,
   *     org.openmrs.module.reporting.evaluation.EvaluationContext)
   */
  @Override
  public MapDataSet evaluate(DataSetDefinition dataSetDefinition, EvaluationContext context)
      throws EvaluationException {
    MergingDataSetDefinition dsd = (MergingDataSetDefinition) dataSetDefinition;

    List<MapDataSet> dataSets = new ArrayList<MapDataSet>();

    DataSetDefinitionService dss = Context.getService(DataSetDefinitionService.class);

    for (DataSetDefinition childDsd : dsd.getDataSetDefinitions()) {
      DataSet dataSet = dss.evaluate(childDsd, context);

      if (dataSet instanceof MapDataSet) {
        dataSets.add((MapDataSet) dataSet);
      } else {
        throw new EvaluationException("Can only merge single dimension data sets");
      }
    }

    return mergeDataSets(dataSets, dsd, context);
  }