/**
   * Create report title. Criteria that have a single value selected are put into the title. Format
   * and possible options are:
   *
   * <ul>
   *   <li>null (no change needed)
   *   <li>portlet
   *   <li>portlet (execution)
   *   <li>group
   *   <li>group (execution)
   *   <li>execution
   *   <li>portlet - group (also displayed if one of each criteria selected)
   * </ul>
   *
   * @param form the form
   * @return report title
   */
  @Override
  protected String getReportTitleAugmentation(PortletExecutionReportForm form) {
    int groupSize = form.getGroups().size();
    int portletSize = form.getPortlets().size();
    int executionTypeSize = form.getExecutionTypeNames().size();

    // Look up names in case we need them.  They should be in cache so no real performance hit.
    String firstPortletName =
        this.aggregatedPortletLookupDao
            .getMappedPortletForFname(form.getPortlets().iterator().next())
            .getFname();
    Long firstGroupId = form.getGroups().iterator().next().longValue();
    String firstGroupName =
        this.aggregatedGroupLookupDao.getGroupMapping(firstGroupId).getGroupName();
    String firstExecutionType = form.getExecutionTypeNames().iterator().next();

    TitleAndCount[] items =
        new TitleAndCount[] {
          new TitleAndCount(firstPortletName, portletSize),
          new TitleAndCount(firstExecutionType, executionTypeSize),
          new TitleAndCount(firstGroupName, groupSize)
        };

    return titleAndColumnDescriptionStrategy.getReportTitleAugmentation(items);
  }
  /** Select the first portlet name by default for the form */
  private void selectFormDefaultPortlet(final PortletExecutionReportForm report) {
    if (!report.getPortlets().isEmpty()) {
      // Portlets already selected, do nothin
      return;
    }

    final Set<AggregatedPortletMapping> portlets = this.getPortlets();
    if (!portlets.isEmpty()) {
      report.getPortlets().add(portlets.iterator().next().getFname());
    }
  }
  /**
   * Create column descriptions for the portlet report using the configured report labelling
   * strategy.
   *
   * @param reportColumnDiscriminator
   * @param form The original query form
   * @return
   */
  @Override
  protected List<ColumnDescription> getColumnDescriptions(
      PortletExecutionAggregationDiscriminator reportColumnDiscriminator,
      PortletExecutionReportForm form) {
    int groupSize = form.getGroups().size();
    int portletSize = form.getPortlets().size();
    int executionTypeSize = form.getExecutionTypeNames().size();

    String portletName = reportColumnDiscriminator.getPortletMapping().getFname();
    String groupName = reportColumnDiscriminator.getAggregatedGroup().getGroupName();
    String executionTypeName = reportColumnDiscriminator.getExecutionType().getName();

    TitleAndCount[] items =
        new TitleAndCount[] {
          new TitleAndCount(portletName, portletSize),
          new TitleAndCount(executionTypeName, executionTypeSize),
          new TitleAndCount(groupName, groupSize)
        };

    return titleAndColumnDescriptionStrategy.getColumnDescriptions(
        items, showFullColumnHeaderDescriptions(form), form);
  }
  protected Map<PortletExecutionAggregationDiscriminator, SortedSet<PortletExecutionAggregation>>
      createColumnDiscriminatorMap(PortletExecutionReportForm form) {
    // Collections used to track the queried groups and the results
    final Map<PortletExecutionAggregationDiscriminator, SortedSet<PortletExecutionAggregation>>
        groupedAggregations =
            new TreeMap<
                PortletExecutionAggregationDiscriminator, SortedSet<PortletExecutionAggregation>>(
                PortletExecutionAggregationDiscriminatorImpl.Comparator.INSTANCE);

    // Get concrete group mapping objects that are being queried for
    List<Long> groups = form.getGroups();
    Set<String> portletFNames = form.getPortlets();
    Set<String> executionTypes = form.getExecutionTypeNames();
    for (final Long queryGroupId : groups) {
      AggregatedGroupMapping groupMapping =
          this.aggregatedGroupLookupDao.getGroupMapping(queryGroupId);
      for (final String portletFName : portletFNames) {
        AggregatedPortletMapping tabMapping =
            this.aggregatedPortletLookupDao.getMappedPortletForFname(portletFName);
        for (String executionType : executionTypes) {
          final PortletExecutionAggregationDiscriminator mapping =
              new PortletExecutionAggregationDiscriminatorImpl(
                  groupMapping, tabMapping, ExecutionType.valueOf(executionType));
          // Create the set the aggregations for this report column will be stored in, sorted
          // chronologically
          final SortedSet<PortletExecutionAggregation> aggregations =
              new TreeSet<PortletExecutionAggregation>(BaseAggregationDateTimeComparator.INSTANCE);

          // Map the group to the set
          groupedAggregations.put(mapping, aggregations);
        }
      }
    }

    return groupedAggregations;
  }