=head1 SYNOPSIS
+This base class is designed for holding collections of objects which can be
+uniquely identified by a key and added/generated by that same key.
=head1 DESCRIPTION
use strictures 2;
use namespace::autoclean;
use List::AllUtils qw(pairmap);
+use Carp qw(croak);
extends 'Debbugs::OOBase';
+=head1 METHODS
+
+=head2 Debbugs::Collection->new(%params|$params)
+
+Creates a new Debbugs::Collection object.
+
+Parameters:
+
+=over
+
+=item universe
+
+To avoid unnecessarily constructing new members, collections have a universe to
+which existing members can be obtained from. By default the universe is this
+collection. Generally, you should create exactly one universe for each
+collection type.
+
+=item schema
+
+Optional Debbugs::Schema object
+
+
+=back
+
+=head2 $collection->members()
+
+Returns list of members of this collection
+
+=head2 $collection->members_ref()
+
+Returns an ARRAYREF of members of this collection
+
+=head2 $collection->keys_of_members()
+
+Returns a list of the keys of all members of this collection
+
+=head2 $collection->member_key($member)
+
+Given a member, returns the key of that member
+
+=head2 $collection->exists($member_key)
+
+Returns true if a member with $member_key exists in the collection
+
+=head2 $collection->clone()
+
+Returns a clone of this collection with the same universe as this collection
+
+=head2 $collection->limit(@member_keys)
+
+Returns a new collection limited to the list of member keys passed. Will add new
+members to the universe if they do not currently exist.
+
+=head2 $collection->add($member)
+
+Add a member to this collection
+
+=head2 $collection->add_by_key($member_key)
+
+Add a member to this collection by key
+
+=head2 $collection->combine($collection2) or $collection + $collection2
+
+Combines the members of both collections together and returns the new collection
+
+=head2 $collection->get($member_key)
+
+Get member(s) by key, returning undef for keys which do not exist in the
+collection
+
+=head2 $collection->get_or_add_by_key($member_key)
+
+Get or add a member by the member key.
+
+=head2 $collection->count()
+
+Return the number of members in this collection
+
+=head2 $collection->grep({$_ eq 5})
+
+Return the members in this collection which satisfy the condition, setting $_
+locally to each member object
+
+=head2 $collection->join(', ')
+
+Returns the keys of the members of this collection joined
+
+=head2 $collection->apply({$_*2}) $collection->map({$_*2})
+
+Return the list of applying BLOCK to each member
+
+=head2 $collection->sort({$a <=> $b})
+
+Return the list of members sorted by BLOCK
+
+=cut
+
has 'members' => (is => 'bare',
isa => 'ArrayRef',
traits => ['Array'],
wantarray ? return @return: return $return[0];
}
+=head2 $collection->universe
+
+
+=cut
+
has 'universe' => (is => 'ro',
isa => 'Debbugs::Collection',
required => 1,
# $limit->_set_universe($self->universe);
$limit->_set_members([]);
$limit->_clear_member_hash();
- $limit->add($self->universe->get_or_create(@_)) if @_;
+ $limit->add($self->universe->get_or_add_by_key(@_)) if @_;
return $limit;
}
-sub get_or_create {
+sub get_or_add_by_key {
my $self = shift;
return () unless @_;
my @return;
my @exists;
my @need_to_add;
for my $i (0..$#_) {
- # we assume that if it's already a blessed reference, that it's the right
- if (blessed($_[$i])) {
- $return[$i] =
- $_[$i];
+ # we assume that if it's already a blessed reference, that it's the
+ # right object to return
+ if (ref $_[$i]) {
+ croak "Passed a reference instead of a key to get_or_add_by_key";
}
elsif ($self->_member_key_exists($_[$i])) {
push @exists,$i;
return @members_added;
}
+use overload '+' => "combine",
+ '""' => "CARP_TRACE";
+
+sub combine {
+ my $self = shift;
+ my $return = $self->clone;
+ $return->add($_->members) for @_;
+ return $return;
+}
+
sub get {
my $self = shift;
- return map {$self->_get_member($_)}
+ my @res = map {$self->_get_member($_)}
$self->_get_member_hash(@_);
+ wantarray?@res:$res[0];
}
return $_[1];
}
+sub keys_of_members {
+ my $self = shift;
+ return $self->map(sub {$self->member_key($_)});
+}
+
sub exists {
my $self = shift;
return $self->_member_key_exists($self->member_key($_[0]));
}
+sub join {
+ my $self = shift;
+ my $joiner = shift;
+ return CORE::join($joiner,$self->keys_of_members);
+}
+
sub _build_member_hash {
my $self = shift;
my $hash = {};
sub CARP_TRACE {
my $self = shift;
- return 'Debbugs::Collection={n_members='.$self->count().'}';
+ my @members = $self->members;
+ if (@members > 5) {
+ @members = map {$self->member_key($_)}
+ @members[0..4];
+ push @members,'...';
+ } else {
+ @members = map {$self->member_key($_)} @members;
+ }
+ return __PACKAGE__.'={n_members='.$self->count().
+ ',members=('.CORE::join(',',@members).')}';
}