From 83f8420b2cac88b11ea6304f7f26952e56bffe80 Mon Sep 17 00:00:00 2001 From: Dan Wells Date: Tue, 7 May 2013 18:19:34 -0400 Subject: [PATCH] Add new get_combined_holdings() method to MFHD.pm This commit adds a new method to the MFHD module which creates an array of compressed holdings from all holdings for a given caption, combining as needed. NOTE: This method is similar to, but much less aggressive/strict than get_compressed_holdings(). Ultimately, get_compressed_holdings() might be deprecated in favor of this. Signed-off-by: Dan Wells Signed-off-by: Lebbeous Fogle-Weekley --- .../src/perlmods/lib/OpenILS/Utils/MFHD.pm | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Utils/MFHD.pm b/Open-ILS/src/perlmods/lib/OpenILS/Utils/MFHD.pm index 32ea066ceb..dff006649e 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Utils/MFHD.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Utils/MFHD.pm @@ -502,6 +502,90 @@ sub get_decompressed_holdings { return @return_holdings; } +# +# create an array of compressed holdings from all holdings for a given caption, +# combining as needed +# +# NOTE: this sub is similar to, but much less aggressive/strict than +# get_compressed_holdings(). Ultimately, get_compressed_holdings() might be +# deprecated in favor of this +# +# TODO: gap marking, gap preservation +# +# TODO: some of this could be moved to the Caption (and/or Holding) object to +# allow for combining in the absense of an overarching MFHD object +# +sub get_combined_holdings { + my $self = shift; + my $caption = shift; + + my @holdings = $self->holdings_by_caption($caption); + return () if !@holdings; + + # basic check for necessary pattern information + if (!scalar keys %{$caption->pattern}) { + carp "Cannot combine without pattern data, returning original holdings"; + return @holdings; + } + + my @sorted_holdings = sort {$a cmp $b} @holdings; + + my @combined_holdings = (shift(@sorted_holdings)); + my $seqno = 1; + $combined_holdings[0]->seqno($seqno); + foreach my $holding (@sorted_holdings) { + # short-circuit: if we hit an open-ended holding, + # it 'includes' all the rest, so just exit the loop + if ($combined_holdings[-1]->is_open_ended) { + last; + } elsif ($holding eq $combined_holdings[-1]) { + # duplicate, skip + next; + } else { + # at this point, we know that $holding is gt $combined_holdings[-1] + # we just need to figure out if they overlap or not + + # first, get the end (or only) holding of [-1] + my $last_holding_end = $combined_holdings[-1]->is_compressed ? + $combined_holdings[-1]->clone->compressed_to_last + : $combined_holdings[-1]->clone; + + # next, make sure $holding isn't fully contained + my $holding_end = $holding->is_compressed ? + $holding->clone->compressed_to_last + : $holding; + # if $holding is fully contained, skip it + if ($holding_end le $last_holding_end) { + next; + } + + # now, get the beginning (or only) holding of $holding + my $holding_start = $holding->is_compressed ? + $holding->clone->compressed_to_first + : $holding; + + if ($last_holding_end->increment ge $holding_start) { + # they overlap, combine them + my $holding_end; + if ($holding->is_compressed) { + $holding_end = $holding->is_open_ended ? + undef + : $holding->compressed_to_last; + } else { + $holding_end = $holding; + } + $combined_holdings[-1]->compressed_end($holding_end); + } else { + # no overlap, start a new group + $holding->seqno(++$seqno); + push(@combined_holdings, $holding); + } + } + } + + return @combined_holdings; +} + ## ## close any open-ended holdings which are followed by another holding by ## combining them -- 2.43.2