initial commit with working tests, docs, and conversion to dzil+podweaver
[catagits/Catalyst-Controller-DBIC-API.git] / lib / Catalyst / Controller / DBIC / API / JoinBuilder.pm
1 package Catalyst::Controller::DBIC::API::JoinBuilder;
2
3 #ABSTRACT: Provides a helper class to automatically keep track of joins in complex searches
4 use Moose;
5 use MooseX::Types::Moose(':all');
6 use Catalyst::Controller::DBIC::API::Types(':all');
7 use namespace::autoclean;
8
9 =attribute_public parent is: ro, isa: 'Catalyst::Controller::DBIC::API::JoinBuilder'
10
11 parent stores the direct ascendant in the datastructure that represents the join
12
13 =cut
14
15 has parent =>
16 (
17     is => 'ro',
18     isa => JoinBuilder,
19     predicate => 'has_parent',
20     weak_ref => 1,
21     trigger => sub { my ($self, $new) = @_; $new->add_child($self); },
22 );
23
24 =attribute_public children is: ro, isa: ArrayRef['Catalyst::Controller::DBIC::API::JoinBuilder'], traits => ['Array']
25
26 children stores the immediate descendants in the datastructure that represents the join.
27
28 Handles the following methods:
29
30     all_children => 'elements'
31     has_children => 'count'
32     add_child => 'push'
33
34 =cut
35
36 has children =>
37 (
38     is => 'ro',
39     isa => ArrayRef[JoinBuilder],
40     traits => ['Array'],
41     default => sub { [] },
42     handles =>
43     {
44         all_children => 'elements',
45         has_children => 'count',
46         add_child => 'push',
47     }
48 );
49
50 =attribute_public joins is: ro, isa: HashRef, lazy_build: true
51
52 joins holds the cached generated join datastructure.
53
54 =cut
55
56 has joins =>
57 (
58     is => 'ro',
59     isa => HashRef,
60     lazy_build => 1,
61 );
62
63 =attribute_public name is: ro, isa: Str, required: 1
64
65 Sets the key for this level in the generated hash
66
67 =cut
68
69 has name =>
70 (
71     is => 'ro',
72     isa => Str,
73     required => 1,
74 );
75
76 =method_private _build_joins
77
78 _build_joins finds the top parent in the structure and then recursively iterates the children building out the join datastructure
79
80 =cut
81
82 sub _build_joins
83 {
84     my ($self) = @_;
85     
86     my $parent;
87     while(my $found = $self->parent)
88     {
89         if($found->has_parent)
90         {
91             $self = $found;
92             next;
93         }
94         $parent = $found;
95     }
96
97     my $builder;
98     $builder = sub
99     {
100         my ($node) = @_;
101         my $foo = {};
102         map { $foo->{$_->name} = $builder->($_) } $node->all_children;
103         return $foo;
104     };
105
106     return $builder->($parent || $self);
107 }
108
109 =head1 DESCRIPTION
110
111 JoinBuilder is used to keep track of joins automgically for complex searches. It accomplishes this by building a simple tree of parents and children and then recursively drilling into the tree to produce a useable join attribute for ->search.
112
113 =cut
114
115 1;