cvsuser     02/04/09 13:00:35

  Modified:    P5EEx/Blue/P5EEx/Blue Repository.pm
  Log:
  added core sorting and grouping support for physical repositories which don't 
support it natively
  
  Revision  Changes    Path
  1.12      +211 -1    p5ee/P5EEx/Blue/P5EEx/Blue/Repository.pm
  
  Index: Repository.pm
  ===================================================================
  RCS file: /cvs/public/p5ee/P5EEx/Blue/P5EEx/Blue/Repository.pm,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -w -r1.11 -r1.12
  --- Repository.pm     5 Apr 2002 22:00:12 -0000       1.11
  +++ Repository.pm     9 Apr 2002 20:00:34 -0000       1.12
  @@ -1,6 +1,6 @@
   
   #############################################################################
  -## $Id: Repository.pm,v 1.11 2002/04/05 22:00:12 spadkins Exp $
  +## $Id: Repository.pm,v 1.12 2002/04/09 20:00:34 spadkins Exp $
   #############################################################################
   
   package P5EEx::Blue::Repository;
  @@ -2133,6 +2133,162 @@
   =cut
   
   #############################################################################
  +# summarize()
  +#############################################################################
  +
  +=head2 summarize()
  +
  +    * Signature: $summarized_rows = $rep->summarize($rows, $columns, $summcolidx, 
$formulas);
  +    * Param:     $rows             [][]
  +    * Param:     $columns          []
  +    * Param:     $summcolidx        []
  +    * Param:     $formulas         {}
  +    * Return:    $summarized_rows  []
  +    * Throws:    P5EEx::Blue::Exception::Repository
  +    * Since:     0.01
  +
  +    Sample Usage: 
  +
  +    @rows = (
  +        [ 5, "Jim", "Green", 13.5, 320, ],
  +        [ 3, "Bob", "Green",  4.2, 230, ],
  +        [ 9, "Ken", "Green", 27.4, 170, ],
  +        [ 2, "Kim", "Blue",  11.7, 440, ],
  +        [ 7, "Jan", "Blue",  55.1,  90, ],
  +        [ 1, "Ben", "Blue",  22.6, 195, ],
  +    );
  +    @columns = ( "id", "name", "team", "rating", "score" );
  +    @summcolidx = ( 2 );  # "team"
  +    %formulas = (
  +        rating => "{sum(rating)}/{count(rating)}",
  +    );
  +
  +    $summarized_rows = $rep->summarize(\@rows, \@columns, \@summcolidx, \%formulas);
  +
  +=cut
  +
  +sub summarize {
  +    my ($self, $rows, $columns, $summcolidx, $formulas) = @_;
  +
  +    my (@summary_rows, $summary_row, $create_summary);
  +    my ($key, $nextkey, $row, $rowidx, $colidx, $numcols, $column, $elem);
  +    my (%total, $formula);
  +
  +    $numcols = $#$columns + 1;
  +
  +    for ($rowidx = 0; $rowidx <= $#$rows; $rowidx++) {
  +        $row = $rows->[$rowidx];
  +
  +        $key = "Total";
  +        $key = join(",", @{$row->[$rowidx]}[@$summcolidx])
  +            if (defined $summcolidx);
  +
  +        # accumulate totals
  +        for ($colidx = 0; $colidx < $numcols; $colidx++) {
  +            $column = $columns->[$colidx];
  +            $elem = $rows->[$rowidx][$colidx];
  +            if (defined $elem && $elem ne "") {
  +                if (defined $total{$column}) {
  +                    $total{"sum($column)"} += ($elem+0);
  +                }
  +                else {
  +                    $total{"sum($column)"} = ($elem+0);
  +                }
  +                $total{"$column"} = $elem;
  +            }
  +        }
  +        if (defined $total{"count(*)"}) {
  +            $total{"count(*)"} ++;
  +        }
  +        else {
  +            $total{"count(*)"} = 1;
  +        }
  +
  +        # look ahead to see if we need to produce a summary row yet
  +        $create_summary = 0;
  +        if ($rowidx == $#$rows) {
  +            $create_summary = 1;
  +        }
  +        else {
  +            $nextkey = "Total";
  +            $nextkey = join(",", @{$rows->[$rowidx+1]}[@$summcolidx])
  +                if (defined $summcolidx);
  +            $create_summary = 1 if ($nextkey ne $key);
  +        }
  +
  +        if ($create_summary) {
  +
  +            $summary_row = [];
  +
  +            for ($colidx = 0; $colidx < $numcols; $colidx++) {
  +                $column = $columns->[$colidx];
  +                $formula = $formulas->{$column};
  +    
  +                $elem = "";
  +                if (defined $formula) {   # match {
  +                    $formula =~ s/\{([^\}]+)\}/\$total{"$1"}/g;
  +                    $formula = "\$elem = $formula;";
  +                    eval $formula;
  +                    #$elem = "[$formula] $@" if ($@);
  +                }
  +                else {
  +                    $elem = $total{"sum($column)"};
  +                }
  +            }
  +    
  +            push (@summary_rows, $summary_row);
  +        }
  +    }
  +    \@summary_rows;
  +}
  +
  +#############################################################################
  +# sort()
  +#############################################################################
  +
  +=head2 sort()
  +
  +    * Signature: $sorted_rows = $rep->sort($rows, $sortcolidx);
  +    * Signature: $sorted_rows = $rep->sort($rows, $sortcolidx, $sorttype);
  +    * Signature: $sorted_rows = $rep->sort($rows, $sortcolidx, $sorttype, $sortdir);
  +    * Param:     $rows             [][]
  +    * Param:     $sortcolidx       []
  +    * Param:     $sorttype         []
  +    * Param:     $sortdir          []
  +    * Return:    $sorted_rows      []
  +    * Throws:    P5EEx::Blue::Exception::Repository
  +    * Since:     0.01
  +
  +    Sample Usage: 
  +
  +    @rows = (
  +        [ 5, "Jim", "Green", 13.5, 320, ],
  +        [ 3, "Bob", "Green",  4.2, 230, ],
  +        [ 9, "Ken", "Green", 27.4, 170, ],
  +        [ 2, "Kim", "Blue",  11.7, 440, ],
  +        [ 7, "Jan", "Blue",  55.1,  90, ],
  +        [ 1, "Ben", "Blue",  22.6, 195, ],
  +    );
  +    # @columns = ( "id", "name", "team", "rating", "score" ); # not needed
  +    @sortcolidx = ( 2, 4 );      # "team", "score" (descending)
  +    @sorttype = ( "C", "N" );    # Character, Numeric
  +    @sortdir = ( "UP", "DOWN" );
  +
  +    $sorted_rows = $rep->sort(\@rows, \@sortcolidx, \@sorttype, \@sortdir);
  +
  +=cut
  +
  +sub sort {
  +    my ($self, $rows, $sortcolidx, $sorttype, $sortdir) = @_;
  +
  +    @P5EEx::Blue::Repository::sort_keys  = @$sortcolidx;
  +    @P5EEx::Blue::Repository::sort_types = ($sorttype ? @$sorttype : ());
  +    @P5EEx::Blue::Repository::sort_dirs  = ($sortdir ? @$sortdir : ());
  +
  +    return [ sort rows_by_indexed_values @$rows ];
  +}
  +
  +#############################################################################
   # serial()
   #############################################################################
   
  @@ -2533,6 +2689,60 @@
   =cut
   
   sub service_type () { 'Repository'; }
  +
  +#############################################################################
  +# rows_by_indexed_values()
  +#############################################################################
  +
  +=head2 rows_by_indexed_values()
  +
  +    * Signature: &P5EEx::Blue::Repository::rows_by_indexed_values($a,$b);
  +    * Param:     $a            []
  +    * Param:     $b            []
  +    * Return:    void
  +    * Throws:    P5EEx::Blue::Exception::Repository
  +    * Since:     0.01
  +
  +    Sample Usage: 
  +
  +    @data = (
  +        [ 5, "Jim", "Red",    13.5, ],
  +        [ 3, "Bob", "Green",   4.2, ],
  +        [ 9, "Ken", "Blue",   27.4, ],
  +        [ 2, "Kim", "Yellow", 11.7, ],
  +        [ 7, "Jan", "Purple", 55.1, ],
  +    );
  +
  +    @P5EEx::Blue::Repository::sort_keys = ( 1, 3, 2 );
  +    @P5EEx::Blue::Repository::sort_types = ("C", "N", "C");
  +    @P5EEx::Blue::Repository::sort_dirs = ("UP", "DOWN", "DOWN");
  +
  +    @sorted_data = sort rows_by_indexed_values @data;
  +
  +The rows_by_indexed_values() function is used to sort rows of data
  +based on indexes, data types, and directions.
  +
  +=cut
  +
  +sub rows_by_indexed_values {
  +    my ($pos, $key, $type, $dir, $sign);
  +    for ($pos = 0; $pos <= $#P5EEx::Blue::Repository::sort_keys; $pos++) {
  +        $key  = $P5EEx::Blue::Repository::sort_keys[$pos];
  +        $type = $P5EEx::Blue::Repository::sort_types[$pos];
  +        $dir  = $P5EEx::Blue::Repository::sort_dirs[$pos];
  +        if (defined $type && $type eq "N") {
  +            $sign = ($a->[$key] <=> $b->[$key]);
  +        }
  +        else {
  +            $sign = ($a->[$key] cmp $b->[$key]);
  +        }
  +        if ($sign) {
  +            $sign = -$sign if (defined $dir && $dir eq "DOWN");
  +            return ($sign);
  +        }
  +    }
  +    return 0;
  +}
   
   #############################################################################
   # DESTROY()
  
  
  


Reply via email to