1 # This module is part of debbugs, and
2 # is released under the terms of the GPL version 2, or any later
3 # version (at your option). See the file README and COPYING for more
5 # Copyright 2018 by Don Armstrong <don@donarmstrong.com>.
7 package Debbugs::Collection;
11 Debbugs::Collection -- Collection base class which can generate lots of objects
24 use namespace::autoclean;
25 use List::AllUtils qw(pairmap);
27 extends 'Debbugs::OOBase';
29 has 'members' => (is => 'bare',
33 writer => '_set_members',
34 predicate => '_has_members',
35 handles => {_add => 'push',
36 members => 'elements',
48 return [$self->members];
51 has 'member_hash' => (traits => ['Hash'],
53 # really a HashRef[Int], but type checking is too slow
56 reader => '_member_hash',
57 builder => '_build_member_hash',
58 clearer => '_clear_member_hash',
59 predicate => '_has_member_hash',
60 writer => '_set_member_hash',
61 handles => {# _add_member_hash => 'set',
62 _member_key_exists => 'exists',
63 _get_member_hash => 'get',
67 # because _add_member_hash needs to be fast, we are overriding the default set
68 # method which is very safe but slow, because it makes copies.
69 sub _add_member_hash {
74 throw_error("Hash keys passed to _add_member_hash must be defined" );
77 throw_error("Values passed to _add_member_hash must be integer");
80 while (my ($key, $value) = splice @kv, 0, 2 ) {
82 $self->{member_hash}{$key} = $value
84 wantarray ? return @return: return $return[0];
87 has 'universe' => (is => 'ro',
88 isa => 'Debbugs::Collection',
90 builder => '_build_universe',
91 writer => '_set_universe',
92 predicate => 'has_universe',
96 # By default, the universe is myself
102 my $new = bless { %{$self} }, ref $self;
103 if ($self->_has_members) {
104 $new->_set_members([$self->members]);
106 if ($self->_has_member_hash) {
107 $new->_set_member_hash({%{$self->_member_hash}})
114 return bless { %{$self} }, ref $self;
119 my $limit = $self->_shallow_clone();
120 # Set the universe to whatever my universe is (potentially myself)
121 # $limit->_set_universe($self->universe);
122 $limit->_set_members([]);
123 $limit->_clear_member_hash();
124 $limit->add($self->universe->get_or_create(@_)) if @_;
135 # we assume that if it's already a blessed reference, that it's the right
136 if (blessed($_[$i])) {
140 elsif ($self->_member_key_exists($_[$i])) {
143 push @need_to_add,$i;
146 # create and add by key
148 @return[@need_to_add] =
149 $self->add_by_key(@_[@need_to_add]);
153 $self->get(@_[@exists]);
155 # if we've only been asked to get or create one thing, then it's expected
156 # that we are returning only one thing
163 has 'constructor_args' => (is => 'rw',
166 builder => '_build_constructor_args',
169 sub _build_constructor_args {
175 # we'll assume that add does the right thing. around this in subclasses
176 return $self->add(@_);
182 for my $member (@_) {
183 if (not defined $member) {
184 confess("Undefined member to add");
186 push @members_added,$member;
187 if ($self->exists($member)) {
190 $self->_add($member);
191 $self->_add_member_hash($self->member_key($member),
195 return @members_added;
200 return map {$self->_get_member($_)}
201 $self->_get_member_hash(@_);
211 return $self->_member_key_exists($self->member_key($_[0]));
214 sub _build_member_hash {
218 for my $member ($self->members) {
219 $hash->{$self->member_key($member)} =
227 return 'Debbugs::Collection={n_members='.$self->count().'}';
231 __PACKAGE__->meta->make_immutable;
237 # indent-tabs-mode: nil
238 # cperl-indent-level: 4