/[Frey]/trunk/lib/Frey/ClassLoader.pm
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /trunk/lib/Frey/ClassLoader.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 462 - (show annotations)
Wed Nov 19 18:06:48 2008 UTC (15 years, 5 months ago) by dpavlin
File size: 4617 byte(s)
fix Frey::Role::as_sponge name
1 package Frey::ClassLoader;
2 use Moose;
3
4 =head1 DESCRIPTION
5
6 Load L<Frey> classes
7
8 =cut
9
10 extends 'Frey';
11
12 use Data::Dump qw/dump/;
13 use File::Find;
14
15 our $class_path;
16 our @classes;
17
18 =head2 classes
19
20 Return all local classes by reading from disk
21
22 my @classes = $o->classes;
23
24 =cut
25
26 sub classes {
27 my $self = shift;
28 return @classes if @classes;
29
30 # FIXME there must be better way to do this in Moose style
31 finddepth({ no_chdir => 1, wanted => sub {
32 return unless m{\.pm$};
33 my $class = $_;
34 $class =~ s{^lib/}{};
35 $class =~ s{\.pm$}{};
36 $class =~ s{/}{::}g;
37 $class_path->{ $class } = $_;
38 } }, 'lib');
39 warn "## class_path = ",dump( $class_path ) if $self->debug;
40
41 @classes = sort keys %$class_path;
42 }
43
44 =head2 class_path
45
46 Return any local or loaded class
47
48 $path = $o->class_path( $class );
49
50 =cut
51
52 sub class_path {
53 my ( $self, $class ) = @_;
54 $self->classes unless $class_path;
55 if ( ! defined $class_path->{$class} ) {
56 my $path = $class;
57 $path =~ s{::}{/}g;
58 $path .= '.pm';
59 $path = $INC{$path};
60 warn "# $class from INC $path";
61 $class_path->{$class} = $path || confess "can't find path for $class";
62 }
63 return $class_path->{$class};
64 }
65
66 =head2 loaded_classes
67
68 my $available = $o->loaded_classes;
69 $available->{'Frey'} # true
70
71 =cut
72
73 our $loaded_class;
74 sub loaded_classes { $loaded_class };
75
76 =head2 class_meta
77
78 my ( $meta, $is_role, $instance ) = $o->class_meta( 'Some::Class' );
79
80 =cut
81
82 sub class_meta {
83 my ( $self, $class ) = @_;
84
85 $class ||= $self->class if $self->can('class');
86 warn "# class_meta $class";
87
88 $self->load_class($class);
89
90 my $meta;
91 my $is_role = 0;
92 my $instance;
93
94 if ( ! $class->can('meta') ) {
95 $instance = Moose::Meta::Class->create_anon_class;
96 warn "# class $class isn't Moose, faking anon class" if $self->debug;
97 $meta = $instance->meta;
98 } elsif( $class->meta->isa('Moose::Meta::Role') ) {
99 $is_role = 1;
100 $instance = Frey->new;
101 warn "# apply $class on $instance";
102 $class->meta->apply( $instance );
103 $meta = $instance->meta;
104 } else {
105 $meta = $class->meta;
106 }
107 return ( $meta, $is_role, $instance );
108 }
109
110 sub load_class {
111 my ( $self, $class ) = @_;
112 return if $loaded_class->{$class}++;
113 eval {
114 Class::MOP::load_class($class)
115 };
116 warn $@ if $@; # && $@ !~ m/role/;
117 warn "# load_class $class" if $self->debug && $loaded_class->{$class} == 1;
118 }
119
120 sub load_all_classes {
121 my $self = shift;
122 warn "# loaded_class = ",dump( $loaded_class ) if $self->debug;
123 $self->load_class( $_ ) foreach ( $self->classes );
124 $loaded_class;
125 }
126
127 =head2 class_methods
128
129 my @all_methods = $o->class_methods( $class );
130
131 my $class_method = $o->class_methods( $class );
132 if ( $class_method->{ $method } ) {
133 # $class has $method
134 }
135
136 =cut
137
138 sub class_methods {
139 my ( $self, $class ) = @_;
140
141 confess "need class" unless $class;
142 if ( ! $class->can('meta') ) {
143 warn "# $class doesn't have meta (isn't Moose class)" if $self->debug;
144 return;
145 }
146 my $meta = $class->meta;
147
148 my $attr;
149 my $methods;
150 $attr->{$_}++ foreach $meta->get_attribute_list;
151 my @methods = map { $methods->{$_}++; $_ } grep { ! defined($attr->{$_}) && $_ ne 'meta' } $meta->get_method_list;
152 warn "# methods = ",dump( @methods ) if $self->debug;
153
154 return @methods if wantarray;
155 return $methods;
156 }
157
158 =head2 class_runnable
159
160 my @runnable_methods = $o->class_runnable( $class );
161
162 =cut
163
164 sub class_runnable {
165 my ( $self, $class ) = @_;
166 my @methods = grep { m{^as_} } $self->class_methods( $class );
167 return @methods if wantarray;
168 return \@methods;
169 }
170
171 sub class_inputs {
172 my ( $self, $class ) = @_;
173 my @inputs = grep { m{^(markup/as_data/as_sponge)$} } $self->class_methods( $class );
174 return @inputs if wantarray;
175 return \@inputs;
176 }
177
178 =head2 new_frey_class
179
180 my $instance = $o->new_frey_class( $class, $params );
181
182 This will apply L<Moose::Role> on the fly to provide accessors for
183 C<data> and C<sponge> in form of C<as_*>
184
185 See L<http://www.perlmonks.org/?node_id=602389>
186
187 It is used by L<Frey::Run> and L<Frey::Pipe> to create objects
188
189 =cut
190
191 {
192 package Frey::Role::as_data;
193 use Moose::Role;
194
195 sub as_data {
196 my ($self) = @_;
197 $self->data;
198 }
199
200 package Frey::Role::as_sponge;
201 use Moose::Role;
202 sub as_sponge {
203 my ($self) = @_;
204 $self->sponge;
205 }
206 }
207
208 sub new_frey_class {
209 my ( $self, $class, $params ) = @_;
210 my $instance = $class->new( %$params );
211 if ( $instance->can('data') && ! $instance->can('as_data') ) {
212 Frey::Role::as_data->meta->apply( $instance );
213 warn "# apply as_data role to $class";
214 }
215 if ( $instance->can('sponge') && ! $instance->can('as_sponge') ) {
216 Frey::Role::as_sponge->meta->apply( $instance );
217 warn "# apply as_sponge role to $class";
218 }
219 return $instance;
220 }
221
222 1;

  ViewVC Help
Powered by ViewVC 1.1.26