port the reaction type system to MooseX::Types
[catagits/Reaction.git] / lib / Reaction / InterfaceModel / Collection.pm
1 package Reaction::InterfaceModel::Collection;
2
3 use Reaction::Class;
4 use Scalar::Util qw/refaddr blessed/;
5 use aliased 'Reaction::Meta::InterfaceModel::Object::DomainModelAttribute';
6
7 # WARNING - DANGER: this is just an RFC, please DO NOT USE YET
8
9 class Collection is "Reaction::InterfaceModel::Object", which {
10
11   # consider supporting slice, first, iterator, last etc.
12   # pager functionality should probably be a role
13
14   # IM objects don't have write methods because those are handled through actions,
15   # no support for write actions either unless someone makes a good case for it
16   # many models may not even be writable, so we cant make that assumption...
17
18   # I feel like we should hasa result_class or object_class ?
19   # having this here would remove a lot of PITA complexity from
20   # ObjectClass and SchemaClass when it comes to munging with internals
21
22   #Answer: No, because collections should be able to hold more than one type of object
23
24   # ALL IMPLEMENTATIONS ARE TO ILLUSTRATE POSSIBLE BEHAVIOR ONLY. DON'T CONSIDER
25   # THEM CORRECT, OR FINAL. JUST A ROUGH DRAFT.
26
27   #domain_models are 'ro' unless otherwise specified
28   has _collection_store => (
29                             is  => 'rw',
30                             isa => 'ArrayRef',
31                             lazy_build => 1,
32                             clearer    => "_clear_collection_store",
33                             metaclass  => DomainModelAttribute,
34                            );
35
36   implements _build__collection_store => as { [] };
37
38   implements members => as {
39     my $self = shift;
40     return @{ $self->_collection_store };
41   };
42
43   #return new member or it's index # ?
44   implements add_member => as {
45     my $self = shift;
46     my $new  = shift;
47     confess "Argument passed is not an object" unless blessed $new;
48     confess "Object Passed does not meet constraint isa Reaction::InterfaceModel::Object"
49       unless $new->isa('Reaction::InterfaceModel::Object');
50     my $store = $self->_collection_store;
51     push @$store, $new;
52     return $#$store; #return index # of inserted item
53   };
54
55   implements remove_member => as {
56     my $self = shift;
57     my $rem = shift;
58     confess "Argument passed is not an object" unless blessed $rem;
59     confess "Object Passed does not meet constraint isa Reaction::InterfaceModel::Object"
60       unless $rem->isa('Reaction::InterfaceModel::Object');
61
62     my $addr = refaddr $rem;
63     @{ $self->_collection_store } = grep {$addr ne refaddr $_ } @{ $self->_store };
64   };
65
66   #that was easy..
67   implements count_members => sub{
68     my $self = shift;
69     return scalar @{ $self->_collection_store };
70   };
71
72 };
73
74 1;
75
76 =head1 NAME
77
78 Reaction::InterfaceModel::Collection - Generic collections of
79 L<Reaction::InterfaceModel::Object>s
80
81 =head1 DESCRIPTION
82
83 The base class for C<InterfaceModel::Collection>s. The functionality implemented here
84 is minimal and it is expected that specialized collections be built by sublclassing
85 this and exploiting the roles system.
86
87 =head1 METHODS
88
89 =head2 members
90
91 Returns a list containing all known members of the collection
92
93 =head2 add_member $object
94
95 Will add the object passed to the collection
96
97 =head2 remove_member $object
98
99 Removed the object passed from the collection, if present
100
101 =head2 count_members
102
103 Returns the number of objects in the collection.
104
105 =head1 ATTRIBUTES
106
107 =head2 _collection_store
108
109 Read-write & lazy_build. Holds the arrayref where the collection of objects is
110 presently stored. Has a clearer of C<_clear_collection_store> and a predicate of
111  C<_has_collection_store>.
112
113 =head1 PRIVATE METHODS
114
115 _build__collection_store
116
117 Builder method for attribute_collection_store, returns an empty arrayref
118
119 =head1 AUTHORS
120
121 See L<Reaction::Class> for authors.
122
123 =head1 LICENSE
124
125 See L<Reaction::Class> for the license.
126
127 =cut