File Coverage

lib/Oryx/Association.pm
Criterion Covered Total %
statement 6 62 9.6
branch 0 22 0.0
condition 0 4 0.0
subroutine 2 19 10.5
pod 15 15 100.0
total 23 122 18.8


line stmt bran cond sub pod time code
1             package Oryx::Association;
2              
3 15     15   91 use base qw(Oryx::MetaClass);
  15         28  
  15         6473  
4              
5             =head1 NAME
6              
7             Association - abstract base class for Association types
8              
9             =head1 SYNOPSIS
10              
11             my $assoc = Oryx::Association->new($meta, $source);
12            
13             $assoc->source; # association from
14             $assoc->class; # association to
15             $assoc->role; # name of association accessor
16             $assoc->type; # Array, Hash, Reference etc.
17             $assoc->constraint; # Aggregate or Composition
18             $assoc->is_weak;
19             $assoc->update_backrefs;
20             $assoc->link_table;
21              
22             =head1 DESCRIPTION
23              
24             This module represents an abstract base class for Oryx association
25             types.
26              
27             =head1 METHODS
28              
29             =over
30              
31             =item new( $meta, $source )
32              
33             The constructor returns the correct instance of the correct
34             subclass based on the C field of the C<$meta> hashref passed
35             as an argument. The C<$source> argument is the name of the class
36             in which this association is defined (see L)
37              
38             =cut
39              
40             sub new {
41 0     0 1   my ($class, $meta, $source) = @_;
42              
43 0           my $type_class = $class.'::'.$meta->{type};
44 0 0         eval "use $type_class"; $class->_croak($@) if $@;
  0            
45              
46 0           my $self = $type_class->new({
47             meta => $meta,
48             source => $source,
49             });
50              
51 0           eval 'use '.$self->class;
52 0 0         $self->_croak($@) if $@;
53              
54 15     15   90 no strict 'refs';
  15         38  
  15         10901  
55 0           *{$source.'::'.$self->role} = $self->_mk_accessor;
  0            
56              
57 0           return $self;
58             }
59              
60             =item create
61              
62             Abstract (see implementing subclasses)
63              
64             =item retrieve
65              
66             Abstract (see implementing subclasses)
67              
68             =item update
69              
70             Abstract (see implementing subclasses)
71              
72             =item delete
73              
74             Abstract (see implementing subclasses)
75              
76             =item search
77              
78             Abstract (see implementing subclasses)
79              
80             =item construct
81              
82             Abstract (see implementing subclasses)
83              
84             =cut
85              
86 0     0 1   sub create { $_[0]->_croak("abstract") }
87 0     0 1   sub retrieve { $_[0]->_croak("abstract") }
88 0     0 1   sub update { $_[0]->_croak("abstract") }
89 0     0 1   sub delete { $_[0]->_croak("abstract") }
90 0     0 1   sub search { $_[0]->_croak("abstract") }
91 0     0 1   sub construct { $_[0]->_croak("abstract") }
92              
93             sub _mk_accessor {
94 0     0     my $assoc = shift;
95 0           my $assoc_name = $assoc->role;
96             return sub {
97 0     0     my $self = shift;
98 0 0         $self->{$assoc_name} = shift if @_;
99 0           $self->{$assoc_name};
100 0           };
101             }
102              
103             =item source
104              
105             Simple accessor to the source class in which this association is
106             defined.
107              
108             =cut
109              
110             sub source {
111 0     0 1   my $self = shift;
112 0           $self->{source};
113             }
114              
115             =item class
116              
117             Simple accessor to the target class with which the source class has
118             an associtation.
119              
120             =cut
121              
122             sub class {
123 0     0 1   my $self = shift;
124 0 0         unless (defined $self->{class}) {
125 0           $self->{class} = $self->getMetaAttribute("class");
126             }
127 0           $self->{class};
128             }
129              
130             =item role
131              
132             Simple accessor to the association accessor name defined in the
133             source class. Defaults to the target class' table name.
134              
135             =cut
136              
137             sub role {
138 0     0 1   my $self = shift;
139 0 0         unless (defined $self->{role}) {
140 0           $self->{role} = $self->getMetaAttribute("role");
141 0 0         unless ($self->{role}) {
142             # set some sensible defaults for creating the accessor
143 0           $self->{role} = $self->class->table;
144             }
145             }
146 0           $self->{role};
147             }
148              
149             =item type
150              
151             Reference, Array or Hash... defaults to Reference.
152              
153             =cut
154              
155             sub type {
156 0     0 1   my $self = shift;
157 0 0         unless (defined $self->{type}) {
158 0   0       $self->{type} = $self->getMetaAttribute("type")
159             || 'Reference';
160             }
161 0           $self->{type};
162             }
163              
164             =item is_weak
165              
166             Simple accessor to the C meta-attribute. This is used
167             for stopping Reference association types from creating a column
168             in the target class for storing a reverse association.
169              
170             =cut
171              
172 0     0 1   sub is_weak { $_[0]->getMetaAttribute('is_weak') }
173              
174             =item constraint
175              
176             Simple accessor to the C meta-attribute. Values are:
177             Aggregate or Composition ... Aggregate is the default,
178             Composition causes deletes to cascade.
179              
180             =cut
181              
182             sub constraint {
183 0     0 1   my $self = shift;
184 0 0         unless (defined $self->{constraint}) {
185 0   0       $self->{constraint} = $self->getMetaAttribute("constraint")
186             || 'Aggregate';
187             }
188 0           $self->{constraint};
189             }
190              
191             =item update_backrefs
192              
193             Updates reverse Reference associations.
194              
195             B Currently, reverse associations are made up of two
196             unidirectional associations... link tables are therefore not shared.
197             This will be fixed.
198              
199             =cut
200              
201             sub update_backrefs {
202 0     0 1   my ($self, $obj, @things) = @_;
203 0           foreach my $rev_assoc (values %{$self->class->associations}) {
  0            
204 0 0         unless ($rev_assoc->type eq 'Reference') {
205 0           $self->_carp(
206             'weak associations not supported for non-Reference types'
207             );
208 0           next;
209             }
210 0 0         if ($rev_assoc->class eq $self->source) {
211 0           my $backref = $rev_assoc->role;
212 0           foreach my $target (@things) {
213 0           $target->$backref($obj);
214 0 0         $target->update unless $rev_assoc->is_weak;
215             }
216             }
217             }
218             }
219              
220             =item link_table
221              
222             Returns a name for the link table for this association. Not relevant
223             for Reference associations as these don't require a link table.
224              
225             This is just a shortcut for:
226              
227             $self->source->table.'_'.$self->role.'_'.$self->class->table
228              
229             Override for custom association types as needed.
230              
231             =cut
232              
233             sub link_table {
234 0     0 1   my $self = shift;
235 0           return $self->source->table.'_'.$self->role.'_'.$self->class->table;
236             }
237              
238             1;
239              
240             =back
241              
242             =head1 AUTHOR
243              
244             Richard Hundt
245              
246             =head1 THANKS TO
247              
248             Andrew Sterling Hanencamp
249              
250             =head1 LICENCE
251              
252             This module is free software and may be used under the same terms as
253             Perl itself.
254              
255             =cut
256