Program: 50950
Project: 50950
Buggy source:
/** 
 * Finds rollup candidates among a list of headers with the same dimensionality. <p>For each column that is being aggregated away, we need to ensure that we have all values of that column. If the column is wildcarded, it's easy. For example, if we wish to roll up to create Segment1:</p> <pre>Segment1(Year=1997, MaritalStatus=*)</pre> <p>then clearly Segment2:</p> <pre>Segment2(Year=1997, MaritalStatus=*, Gender=*, Nation=*)</pre> <p>has all gender and Nation values. If the values are specified as a list:</p> <pre>Segment3(Year=1997, MaritalStatus=*, Gender={M, F}, Nation=*)</pre> <p>then we need to check the metadata. We see that Gender has two distinct values in the database, and we have two values, therefore we have all of them.</p> <p>What if we have multiple non-wildcard columns? Consider:</p> <pre> Segment4(Year=1997, MaritalStatus=*, Gender={M}, Nation={Mexico, USA}) Segment5(Year=1997, MaritalStatus=*, Gender={F}, Nation={USA}) Segment6(Year=1997, MaritalStatus=*, Gender={F, M}, Nation={Canada, Mexico, Honduras, Belize}) </pre> <p>The problem is similar to finding whether a collection of rectangular regions covers a rectangle (or, generalizing to n dimensions, an n-cube). Or better, find a minimal collection of regions.</p> <p>Our algorithm solves it by iterating over all combinations of values. Those combinations are exponential in theory, but tractible in practice, using the following trick. The algorithm reduces the number of combinations by looking for values that are always treated the same. In the above, Canada, Honduras and Belize are always treated the same, so to prove covering, it is sufficient to prove that all combinations involving Canada are covered.</p>
 * @param coordinates Coordinates
 * @param list List to write candidates to
 * @param headers Headers of candidate segments
 */
private void findRollupCandidatesAmong(Map<String,Comparable> coordinates,List<List<SegmentHeader>> list,List<SegmentHeader> headers){
  final List<Pair<SegmentHeader,List<SegmentColumn>>> matchingHeaders=new ArrayList<Pair<SegmentHeader,List<SegmentColumn>>>();
  headerLoop:   for (  SegmentHeader header : headers) {
    if (!header.getExcludedRegions().isEmpty()) {
      continue;
    }
    List<SegmentColumn> nonWildcards=new ArrayList<SegmentColumn>();
    for (    SegmentColumn column : header.getConstrainedColumns()) {
      final SegmentColumn constrainedColumn=header.getConstrainedColumn(column.columnExpression);
      if (coordinates.containsKey(column.columnExpression)) {
        Comparable value=coordinates.get(column.columnExpression);
        if (value == null) {
          value=RolapUtil.sqlNullValue;
        }
        if (constrainedColumn.values != null && !constrainedColumn.values.contains(value)) {
          continue headerLoop;
        }
      }
 else {
        if (constrainedColumn.values != null) {
          nonWildcards.add(constrainedColumn);
        }
      }
    }
    if (nonWildcards.isEmpty()) {
      list.add(Collections.singletonList(header));
    }
 else {
      matchingHeaders.add(Pair.of(header,nonWildcards));
    }
  }
  if (matchingHeaders.size() < 2) {
    return;
  }
  final List<SegmentColumn> columnList=new ArrayList<SegmentColumn>();
  final List<String> columnNameList=new ArrayList<String>();
  for (  Pair<SegmentHeader,List<SegmentColumn>> pair : matchingHeaders) {
    for (    SegmentColumn column : pair.right) {
      if (!columnNameList.contains(column.columnExpression)) {
        final int valueCount=column.getValueCount();
        if (valueCount <= 0) {
          return;
        }
        columnList.add(column);
        columnNameList.add(column.columnExpression);
      }
    }
  }
  final List<List<Comparable>> valueLists=new ArrayList<List<Comparable>>();
  for (  SegmentColumn column : columnList) {
    final SortedMap<Comparable,BitSet> valueMap=new TreeMap<Comparable,BitSet>();
    int h=-1;
    for (    SegmentHeader header : Pair.leftIter(matchingHeaders)) {
      ++h;
      final SegmentColumn column1=header.getConstrainedColumn(column.columnExpression);
      if (column1.getValues() == null) {
        for (        Entry<Comparable,BitSet> entry : valueMap.entrySet()) {
          for (int pos=0; pos < entry.getValue().cardinality(); pos++) {
            entry.getValue().set(pos);
          }
        }
      }
 else {
        for (        Comparable value : column1.getValues()) {
          BitSet bitSet=valueMap.get(value);
          if (bitSet == null) {
            bitSet=new BitSet();
            valueMap.put(value,bitSet);
          }
          bitSet.set(h);
        }
      }
    }
    if (valueMap.size() < column.valueCount) {
      return;
    }
    final Map<BitSet,Comparable> eqclassPrimaryValues=new HashMap<BitSet,Comparable>();
    for (    Map.Entry<Comparable,BitSet> entry : valueMap.entrySet()) {
      final BitSet bitSet=entry.getValue();
      if (!eqclassPrimaryValues.containsKey(bitSet)) {
        final Comparable value=entry.getKey();
        eqclassPrimaryValues.put(bitSet,value);
      }
    }
    valueLists.add(new ArrayList<Comparable>(eqclassPrimaryValues.values()));
  }
  final CartesianProductList<Comparable> tuples=new CartesianProductList<Comparable>(valueLists);
  final List<SegmentHeader> usedSegments=new ArrayList<SegmentHeader>();
  final List<SegmentHeader> unusedSegments=new ArrayList<SegmentHeader>(headers);
  tupleLoop:   for (  List<Comparable> tuple : tuples) {
    for (    SegmentHeader segment : usedSegments) {
      if (contains(segment,tuple,columnNameList)) {
        continue tupleLoop;
      }
    }
    for (    SegmentHeader segment : unusedSegments) {
      if (contains(segment,tuple,columnNameList)) {
        unusedSegments.remove(segment);
        usedSegments.add(segment);
        continue tupleLoop;
      }
    }
    return;
  }
  list.add(usedSegments);
}

Fixed version (ground truth):
/** 
 * Finds rollup candidates among a list of headers with the same dimensionality. <p>For each column that is being aggregated away, we need to ensure that we have all values of that column. If the column is wildcarded, it's easy. For example, if we wish to roll up to create Segment1:</p> <pre>Segment1(Year=1997, MaritalStatus=*)</pre> <p>then clearly Segment2:</p> <pre>Segment2(Year=1997, MaritalStatus=*, Gender=*, Nation=*)</pre> <p>has all gender and Nation values. If the values are specified as a list:</p> <pre>Segment3(Year=1997, MaritalStatus=*, Gender={M, F}, Nation=*)</pre> <p>then we need to check the metadata. We see that Gender has two distinct values in the database, and we have two values, therefore we have all of them.</p> <p>What if we have multiple non-wildcard columns? Consider:</p> <pre> Segment4(Year=1997, MaritalStatus=*, Gender={M}, Nation={Mexico, USA}) Segment5(Year=1997, MaritalStatus=*, Gender={F}, Nation={USA}) Segment6(Year=1997, MaritalStatus=*, Gender={F, M}, Nation={Canada, Mexico, Honduras, Belize}) </pre> <p>The problem is similar to finding whether a collection of rectangular regions covers a rectangle (or, generalizing to n dimensions, an n-cube). Or better, find a minimal collection of regions.</p> <p>Our algorithm solves it by iterating over all combinations of values. Those combinations are exponential in theory, but tractible in practice, using the following trick. The algorithm reduces the number of combinations by looking for values that are always treated the same. In the above, Canada, Honduras and Belize are always treated the same, so to prove covering, it is sufficient to prove that all combinations involving Canada are covered.</p>
 * @param coordinates Coordinates
 * @param list List to write candidates to
 * @param headers Headers of candidate segments
 */
private void findRollupCandidatesAmong(Map<String,Comparable> coordinates,List<List<SegmentHeader>> list,List<SegmentHeader> headers){
  final List<Pair<SegmentHeader,List<SegmentColumn>>> matchingHeaders=new ArrayList<Pair<SegmentHeader,List<SegmentColumn>>>();
  headerLoop:   for (  SegmentHeader header : headers) {
    if (!header.getExcludedRegions().isEmpty()) {
      continue;
    }
    List<SegmentColumn> nonWildcards=new ArrayList<SegmentColumn>();
    for (    SegmentColumn column : header.getConstrainedColumns()) {
      final SegmentColumn constrainedColumn=header.getConstrainedColumn(column.columnExpression);
      if (coordinates.containsKey(column.columnExpression)) {
        Comparable value=coordinates.get(column.columnExpression);
        if (value == null) {
          value=RolapUtil.sqlNullValue;
        }
        if (constrainedColumn.values != null && !constrainedColumn.values.contains(value)) {
          continue headerLoop;
        }
      }
 else {
        if (constrainedColumn.values != null) {
          nonWildcards.add(constrainedColumn);
        }
      }
    }
    if (nonWildcards.isEmpty()) {
      list.add(Collections.singletonList(header));
    }
 else {
      matchingHeaders.add(Pair.of(header,nonWildcards));
    }
  }
  if (matchingHeaders.size() < 2) {
    return;
  }
  final List<SegmentColumn> columnList=new ArrayList<SegmentColumn>();
  final List<String> columnNameList=new ArrayList<String>();
  for (  Pair<SegmentHeader,List<SegmentColumn>> pair : matchingHeaders) {
    for (    SegmentColumn column : pair.right) {
      if (!columnNameList.contains(column.columnExpression)) {
        final int valueCount=column.getValueCount();
        if (valueCount <= 0) {
          return;
        }
        columnList.add(column);
        columnNameList.add(column.columnExpression);
      }
    }
  }
  final List<List<Comparable>> valueLists=new ArrayList<List<Comparable>>();
  for (  SegmentColumn column : columnList) {
    final SortedMap<Comparable,BitSet> valueMap=new TreeMap<Comparable,BitSet>(RolapUtil.ROLAP_COMPARATOR);
    int h=-1;
    for (    SegmentHeader header : Pair.leftIter(matchingHeaders)) {
      ++h;
      final SegmentColumn column1=header.getConstrainedColumn(column.columnExpression);
      if (column1.getValues() == null) {
        for (        Entry<Comparable,BitSet> entry : valueMap.entrySet()) {
          for (int pos=0; pos < entry.getValue().cardinality(); pos++) {
            entry.getValue().set(pos);
          }
        }
      }
 else {
        for (        Comparable value : column1.getValues()) {
          BitSet bitSet=valueMap.get(value);
          if (bitSet == null) {
            bitSet=new BitSet();
            valueMap.put(value,bitSet);
          }
          bitSet.set(h);
        }
      }
    }
    if (valueMap.size() < column.valueCount) {
      return;
    }
    final Map<BitSet,Comparable> eqclassPrimaryValues=new HashMap<BitSet,Comparable>();
    for (    Map.Entry<Comparable,BitSet> entry : valueMap.entrySet()) {
      final BitSet bitSet=entry.getValue();
      if (!eqclassPrimaryValues.containsKey(bitSet)) {
        final Comparable value=entry.getKey();
        eqclassPrimaryValues.put(bitSet,value);
      }
    }
    valueLists.add(new ArrayList<Comparable>(eqclassPrimaryValues.values()));
  }
  final CartesianProductList<Comparable> tuples=new CartesianProductList<Comparable>(valueLists);
  final List<SegmentHeader> usedSegments=new ArrayList<SegmentHeader>();
  final List<SegmentHeader> unusedSegments=new ArrayList<SegmentHeader>(headers);
  tupleLoop:   for (  List<Comparable> tuple : tuples) {
    for (    SegmentHeader segment : usedSegments) {
      if (contains(segment,tuple,columnNameList)) {
        continue tupleLoop;
      }
    }
    for (    SegmentHeader segment : unusedSegments) {
      if (contains(segment,tuple,columnNameList)) {
        unusedSegments.remove(segment);
        usedSegments.add(segment);
        continue tupleLoop;
      }
    }
    return;
  }
  list.add(usedSegments);
}