package NGCP::BulkProcessor::DSSorter; use strict; ## no critic # guarantee stability, regardless of algorithm use sort 'stable'; use NGCP::BulkProcessor::Logging qw(getlogger); use NGCP::BulkProcessor::LogError qw(sortconfigerror); use NGCP::BulkProcessor::Table; require Exporter; our @ISA = qw(Exporter); our @EXPORT_OK = qw( sort_by_config_ids sort_by_configs ); #my $logger = getlogger(__PACKAGE__); sub new { my $class = shift; my $self = {}; $self->{sortconfig} = NGCP::BulkProcessor::Table->new(); bless($self,$class); return $self; } sub add_sorting { my $self = shift; my ($sorting_id,$numeric,$dir,$memberchain) = @_; if (defined $memberchain and ref $memberchain eq 'ARRAY') { my @fieldnames = @$memberchain; if ((scalar @fieldnames) > 0) { $self->{sortconfig}->addrow_nodupe($numeric,$dir,@fieldnames); } } else { sortconfigerror($sorting_id,'chain of object members undefined/invalid',getlogger(__PACKAGE__)); } } sub clear_sorting { my $self = shift; $self->{sortconfig}->clear(); } sub sort_array { my $self = shift; my $array_ptr = shift; my $sortconfig = $self->{sortconfig}; my $sorter = sub ($$) { my $a = shift; my $b = shift; my $result = 0; for (my $i = 0; $i < $sortconfig->rowcount(); $i++) { my $j = 2; my $membername = $sortconfig->element($i,$j); my $item_a = ($a ? $a->{$membername} : undef); my $item_b = ($b ? $b->{$membername} : undef); $j++; $membername = $sortconfig->element($i,$j); while (defined $membername) { $item_a = ($item_a ? $item_a->{$membername} : undef); $item_b = ($item_b ? $item_b->{$membername} : undef); $j++; $membername = $sortconfig->element($i,$j); } $result = ($result or ( $sortconfig->element($i,0) ? ($item_a <=> $item_b) : ($item_a cmp $item_b) ) * $sortconfig->element($i,1) ); } return $result; }; my @sorted = (); if (defined $array_ptr and ref $array_ptr eq 'ARRAY') { @sorted = sort $sorter @$array_ptr; } return \@sorted; } sub sort_by_config_ids { my ($array_ptr, $sorting_ids_ref, $sortingconfigurations) = @_; if (defined $array_ptr and ref $array_ptr eq 'ARRAY') { if (defined $sorting_ids_ref and ref $sorting_ids_ref eq 'ARRAY') { if (defined $sortingconfigurations and ref $sortingconfigurations eq 'HASH') { my @sorting_ids = @{$sorting_ids_ref}; if ((scalar @sorting_ids) > 0) { my $sorter = NGCP::BulkProcessor::DSSorter->new(); foreach my $sorting_id (@sorting_ids) { my $sc = $sortingconfigurations->{$sorting_id}; if (defined $sc and ref $sc eq 'HASH') { $sorter->add_sorting($sorting_id, $sc->{numeric}, $sc->{dir}, $sc->{memberchain}); } else { sortconfigerror($sorting_id, 'missing/invalid sorting configuration', getlogger(__PACKAGE__)); } } return $sorter->sort_array($array_ptr); } } else { sortconfigerror(undef, 'missing/invalid sorting configurations', getlogger(__PACKAGE__)); } } return $array_ptr; } else { return []; } } sub sort_by_configs { my ($array_ptr,$sortingconfigurations) = @_; if (defined $array_ptr and ref $array_ptr eq 'ARRAY') { if (defined $sortingconfigurations and ref $sortingconfigurations eq 'ARRAY') { my @scs = @$sortingconfigurations; if ((scalar @scs) > 0) { my $sorter = NGCP::BulkProcessor::DSSorter->new(); my $sorting_id = -1; foreach my $sc (@scs) { #my $sc = $sortingconfigurations->{$sorting_id}; if (defined $sc and ref $sc eq 'HASH') { $sorter->add_sorting($sorting_id, $sc->{numeric}, $sc->{dir}, $sc->{memberchain}); } else { sortconfigerror($sorting_id, 'invalid sorting configuration', getlogger(__PACKAGE__)); } $sorting_id -= 1; } return $sorter->sort_array($array_ptr); } } return $array_ptr; } else { return []; } } 1;