/[Frey]/trunk/lib/Frey/Introspect.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/Introspect.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 66 - (show annotations)
Wed Jul 9 12:08:07 2008 UTC (15 years, 9 months ago) by dpavlin
File size: 5548 byte(s)
moved error catching into Frey::Server
1 package Frey::Introspect;
2
3 use Moose;
4 use Carp;
5 use Class::MOP;
6 use Moose::Meta::Role;
7 use Moose::Meta::Class;
8 use Scalar::Util qw/blessed/;
9 use Data::Dump qw/dump/;
10 use File::Slurp;
11 use List::Util;
12
13 use Continuity::Widget::DomNode;
14 use lib 'lib';
15
16 extends 'Frey';
17
18 has 'package' => (
19 is => 'rw',
20 isa => 'Str',
21 required => 1,
22 );
23
24 has 'path' => (
25 is => 'rw',
26 );
27
28 =head2 load_package
29
30 my ( $class, $meta, $is_role ) = $o->load_package( 'Some::Package' );
31
32 =cut
33
34 sub load_package {
35 my ( $self ) = @_;
36
37 my $package = $self->package;
38
39 #intercept role application so we can accurately generate
40 #method and attribute information for the parent class.
41 #this is fragile, but there is not better way that i am aware of
42 my $rmeta = Moose::Meta::Role->meta;
43 $rmeta->make_mutable if $rmeta->is_immutable;
44 my $original_apply = $rmeta->get_method("apply")->body;
45 $rmeta->remove_method("apply");
46 my @roles_to_apply;
47 $rmeta->add_method("apply", sub{push(@roles_to_apply, [@_])});
48 #load the package with the hacked Moose::Meta::Role
49
50 #eval { Class::MOP::load_class($package); };
51 #confess "Failed to load package ${package} $@" if $@;
52 Class::MOP::load_class($package);
53
54 my $meta = $package->meta;
55
56 my ($class, $is_role);
57 if($package->meta->isa('Moose::Meta::Role')){
58 $is_role = 1;
59 # we need to apply the role to a class to be able to properly introspect it
60 $class = Moose::Meta::Class->create_anon_class;
61 $original_apply->($meta, $class);
62 } else {
63 #roles don't have superclasses ...
64 $class = $meta;
65 }
66 return ( $class, $meta, $is_role );
67 }
68
69 =head2 joose
70
71 my $js = $o->joose( 'Some::Package' );
72
73 =cut
74
75 sub joose {
76 my ($self) = @_;
77
78 my ( $class, $meta, $is_role ) = $self->load_package;
79
80 if ( ! $is_role ) {
81 my @superclasses = map{ $_->meta->name }
82 grep { $_ ne 'Moose::Object' } $meta->superclasses;
83 warn "superclasses ",dump( @superclasses );
84 }
85
86 my $out;
87
88 my ( $m, $c ) = split(/::/, $class->name, 2);
89 my $filename = $m . '.' . ( $c ? "$c." : '' ) . 'js';
90
91 $out .= "Module(\"$m\", function (m) {\n\tClass(\"$c\", {\n\t\thas: {\n";
92
93 foreach ( $class->get_attribute_list ) {
94 $out .= "\t\t\t$_: {\n";
95
96 my $attr = $class->get_attribute($_);
97 my $is = $attr->_is_metadata;
98 $out .= "\t\t\t\tis: \"$is\",\n" if defined $is;
99 $out .= "\t\t\t\tlazy: true,\n" if $attr->is_lazy;
100 $out .= "\t\t\t\trequired: true,\n" if $attr->is_required;
101 $out .= "\t\t\t\tinit: \"" . $attr->init_arg . "\",\n" if $attr->init_arg; # FIXME
102
103 if( defined(my $isa = $attr->_isa_metadata) ){
104 if( blessed $isa ){
105 while( blessed $isa ){
106 $isa = $isa->name;
107 }
108 }
109 $isa =~ s/\s+\|\s+undef//gi;
110 $out .= "\t\t\t\tisa: Moose.$isa,\n";
111 }
112
113
114 $out .= "\t\t\t},\n";
115
116 }
117
118 $out .= "\t\t},\n\t\tmeta: Frey.HTML,
119 classMethods: {
120 renderHTML: function () {
121 return new Joose.SimpleRequest().getText(\"/~/" . $self->package . "\")
122 },\n";
123
124 $out .= "\t\t},\n";
125
126 $out .= "\t}),\n";
127
128 $out =~ s/,\n$/\n/;
129 $out .= "});\n";
130
131 $out .= "\nconsole.log( 'loaded " . $class->name . " from $filename' );\n";
132
133 warn $class->dump(2);
134
135 warn "method_list = ",dump( $class->get_method_list );
136 warn dump( map{ $class->get_method($_)->name } sort $class->get_method_list );
137
138 # print $out;
139 my $path = "static/blib/$filename";
140 write_file( $path, $out );
141 warn "# created $path\n";
142 $self->path( $path );
143
144 return $out;
145 }
146
147 =head2 methods
148
149 my @methods = $o->methods;
150
151 =cut
152
153 sub methods {
154 my $self = shift;
155
156 my ( $class, $meta, $is_role ) = $self->load_package;
157
158 my $attr;
159 $attr->{$_}++ foreach $class->get_attribute_list;
160 my @methods = grep { ! defined($attr->{$_}) } $class->get_method_list;
161 warn "# methods = ",dump( @methods );
162
163 return @methods;
164 }
165
166 =head1 OUTPUT GENERATION
167
168 =head2 html
169
170 $o->html( $request );
171
172 =cut
173
174 our @javascript = ( qw'
175 ../lib/Joose.js
176 ');
177
178 sub html {
179 my ( $self, $request ) = @_;
180
181 while (1) {
182
183 my $js = Continuity::Widget::DomNode->create(
184 map {
185 ( script => { type => 'text/javascript', src => $_ } )
186 } @javascript
187 )->to_string;
188
189 $js .= << '__END_OF_JS__';
190 <script type="text/javascript">
191 joose.loadComponents("../lib")
192
193 function $(id) {
194 return document.getElementById(id)
195 }
196
197 </script>
198 __END_OF_JS__
199
200 warn "# >>> js\n$js\n" if $self->debug;
201
202 my ( $class, $meta, $is_role ) = $self->load_package();
203
204 my $methods;
205 if ( $class->can('meta') ) {
206 $methods = Continuity::Widget::DomNode->create(
207 ul => [
208 map { (
209 li => [ a => { href => '/~/' . $self->package . '/' . $_ } => [ $_ ] ]
210 ) } $self->methods
211 ]
212 )->to_string;
213 } else {
214 $methods = '<b>not introspectable</b>';
215 }
216
217 my $attributes = Continuity::Widget::DomNode->create(
218 ul => [
219 map {
220 my $attr = $class->get_attribute($_);
221 warn "## $_ ", $attr->is_required ? 'required' : 'optional';
222 ( li => [ a => { href => '/~/' . $self->package . '/' . $_ } => [ $_ ], ( $attr->is_required ? ' <b>required</b>' : '' ) ] )
223 } $class->get_attribute_list
224 ],
225 )->to_string;
226
227 my $doc = Continuity::Widget::DomNode->create(
228 html => [
229 head => [
230 link => { rel=>"stylesheet", href=>"/static/app.css", type=>"text/css", media=>"screen" },
231 $js,
232 title => [ 'Introspect ', $self->package ],
233 ],
234 body => [
235 h1 => [ $self->package ],
236 h2 => [ 'Methods' ],
237 $methods,
238 h2 => [ 'Atrributes' ],
239 $attributes,
240 ],
241 ]
242 );
243
244 $request->print($doc->to_string);
245 warn "# >>> html\n", $doc->to_string, "\n";
246 $request->next;
247 }
248 warn "# exit html";
249 }
250
251 =head1 SEE ALSO
252
253 L<MooseX::AutoDoc> on which this code is based
254
255 =cut
256
257 1;

  ViewVC Help
Powered by ViewVC 1.1.26