File Coverage

blib/lib/HTML/WebDAO/Engine.pm
Criterion Covered Total %
statement 4 6 66.6
branch n/a
condition n/a
subroutine 2 2 100.0
pod n/a
total 6 8 75.0


line stmt bran cond sub pod time code
1             #$Id: Engine.pm 251 2008-03-31 16:24:58Z zag $
2              
3             package HTML::WebDAO::Engine;
4 4     4   9240 use Data::Dumper;
  4         7  
  4         191  
5 4     4   1177 use HTML::WebDAO::Container;
  0            
  0            
6             use HTML::WebDAO::Lex;
7             use HTML::WebDAO::Lib::MethodByPath;
8             use HTML::WebDAO::Lib::RawHTML;
9             use base qw(HTML::WebDAO::Container);
10             use Carp;
11             use strict;
12             __PACKAGE__->attributes qw( _session __obj __events);
13              
14             sub _sysinit {
15             my ( $self, $ref ) = @_;
16             my %hash = @$ref;
17              
18             # Setup $init_hash;
19             my $my_name = $hash{id} || ''; #shift( @{$ref} );
20             unshift(
21             @{$ref},
22             {
23             ref_engine => $self, #! Setup _engine refernce for childs!
24             name_obj => "$my_name"
25             }
26             ); #! Setup _my_name
27             #Save session
28             _session $self $hash{session};
29              
30             # name_obj=>"applic"}); #! Setup _my_name
31             $self->SUPER::_sysinit($ref);
32              
33             #!init _runtime variables;
34             $self->_set_parent($self);
35              
36             #hash "function" -"package"
37             $self->__obj( {} );
38              
39             #init hash of evens names -> @Array of pointers of sub in objects
40             $self->__events( {} );
41              
42             }
43              
44             sub init {
45             my ( $self, %opt ) = @_;
46              
47             #register default clasess
48             $self->register_class(
49             'HTML::WebDAO::Lib::RawHTML' => '_rawhtml_element',
50             'HTML::WebDAO::Lib::MethodByPath' => '_method_call'
51             );
52              
53             #Register by init classes
54             if ( ref( my $classes = $opt{register} ) ) {
55             $self->register_class(%$classes);
56             }
57             my $raw_html = $opt{source};
58             if ( my $lex = $opt{lexer} ) {
59             map { $_->value($self) } @{ $lex->auto };
60             my @objs = map { $_->value($self) } @{ $lex->tree };
61             $self->_add_childs(@objs);
62             }
63             else {
64              
65             #Create childs from source
66             $self->_add_childs( @{ $self->_parse_html($raw_html) } );
67             }
68              
69             }
70              
71             sub _get_obj_by_path {
72             my $self = shift;
73             my ( $obj_p, @path ) = @_;
74             my $id = shift @path;
75             my $res;
76             if ( my $obj = $obj_p->_get_obj_by_name($id) ) {
77             $res = scalar(@path) ? $self->_get_obj_by_path( $obj, @path ) : $obj;
78             }
79             return $res;
80             }
81              
82             sub __restore_session_attributes {
83             my $self = shift;
84              
85             #collect paths as index
86             my %paths;
87             foreach my $object (@_) {
88             my @collection = ( $object, @{ $object->_get_childs } );
89             $paths{ $_->__path2me } = $_ for @collection;
90             }
91             my $sess = $self->_session;
92             my $loaded = $sess->_load_attributes_by_path( keys %paths );
93             while ( my ( $key, $ref ) = each %$loaded ) {
94             next unless exists $paths{$key};
95             $paths{$key}->_set_vars($ref);
96             }
97             }
98              
99             sub __store_session_attributes {
100             my $self = shift;
101              
102             #collect paths as index
103             my %paths;
104             foreach my $object (@_) {
105             my @collection = ( $object, @{ $object->_get_childs } );
106             foreach (@collection) {
107             my $attrs = $_->_get_vars;
108             next unless $attrs;
109             $paths{ $_->__path2me } = $attrs;
110             }
111             }
112             my $sess = $self->_session;
113             $sess->_store_attributes_by_path( \%paths );
114             }
115              
116             sub response {
117             my $self = shift;
118             return $self->_session->response_obj;
119             }
120              
121             =head2 resolve_path $session , ( $url or \@path )
122              
123             Resolve path, find object and call method
124             Can return:
125              
126             undef - not found path or object not have method
127             $object_ref - if object return $self (????)
128             HTML::WebDAO::Response - objects
129              
130            
131              
132             =cut
133              
134             sub resolve_path {
135             my $self = shift;
136             my $sess = shift;
137             my $url = shift;
138             my @path = ();
139             if ( ref($url) eq 'ARRAY' ) {
140             @path = @$url;
141             }
142             else {
143             @path = @{ $sess->call_path($url) };
144             }
145             my $result;
146              
147             #return $self for / pathes
148             return $self unless @path;
149              
150             #try to get object by path
151              
152             if ( my $object = $self->_get_object_by_path( \@path, $sess ) ) {
153              
154             #if object have index_x then stop traverse and call them
155             my $method = ( shift @path ) || 'index_x';
156              
157             #check if $object have method
158             if ( UNIVERSAL::can( $object, $method ) ) {
159              
160             #Ok have method
161             #check if path have more elements
162             my %args = %{ $sess->Params };
163             if ( @path ) {
164              
165             #add special variable
166             $args{__extra_path__} = \@path;
167             }
168              
169             #call method
170             $result = $object->$method(%args);
171             return unless defined $result; #return undef if empty result
172              
173             #if object return $self ?
174             return $result if $object eq $result; #return then
175             #if method return non response object
176             #then create them
177             unless ( UNIVERSAL::isa( $result, 'HTML::WebDAO::Response' ) ) {
178             my $response = $self->response;
179             for ($response) {
180              
181             #set default format : html
182             html $_= $result;
183             }
184             $result = $response;
185             }
186             }
187             else {
188              
189             #don't have method
190             #error404 - not found
191             # $result = $self->response->error404("Not Found : $url");
192             }
193             }
194             else {
195              
196             #not found objects by path !
197             # $result = $self->response->error404("Not Found : $url");
198             }
199             return $result;
200             }
201              
202             sub execute {
203             my $self = shift;
204             my $sess = shift;
205             my $url = shift;
206             my @path = grep { $_ ne '' } @{ $sess->call_path($url) };
207             my $ans = $self->resolve_path( $sess, \@path );
208              
209             #got reference
210             #unless defined then return not found
211             unless ($ans) {
212             my $response = $sess->response_obj;
213             $response->error404( "Url not found:" . join "/", @path );
214             $response->flush;
215             return; #end
216             }
217             unless ( ref $ans ) {
218             _log1 $self "got non referense answer $ans";
219             my $response = $sess->response_obj;
220             $response->error404(
221             "Unknown response path: " . join( "/", @path ) . " ans: $ans" );
222             $response->flush;
223             return; #end
224             }
225              
226             #check referense or not
227             if ( UNIVERSAL::isa( $ans, 'HTML::WebDAO::Response' ) ) {
228            
229             $ans->_print_dep_on_context($sess) unless $ans->_is_file_send;
230             $ans->flush;
231             return;
232             my $res = $ans->html;
233             $ans->print( ref($res) eq 'CODE' ? $res->() : $res );
234             $ans->flush;
235             return; #end
236             }
237             elsif ( UNIVERSAL::isa( $ans, 'HTML::WebDAO::Element' ) ) {
238              
239             #got Element object
240             #do walk over objects
241             my $response = $sess->response_obj;
242             $response->print($_) for @{ $self->fetch($sess) };
243             $response->flush;
244             return; #end
245             }
246             else {
247              
248             #not reference or not definde
249             _log1 $self "Not supported response object. path: "
250             . join( "/", @path )
251             . " ans: $ans";
252             my $response = $sess->response_obj;
253             $response->error404(
254             "Unknown response path: " . join( "/", @path ) . " ans: $ans" );
255             $response->flush;
256             return; #end
257              
258             }
259             }
260              
261             sub Work {
262             my $self = shift;
263             my $sess = shift;
264             my @path = @{ $sess->call_path };
265              
266             # _log1 $self "WOKR: '@path'".Dumper(\@path);
267             ####
268             my $res = $self->_call_method( \@path, %{ $sess->Params } ) if @path;
269              
270             #if not defined $res
271              
272             #first prepare response object
273             my $response = $sess->response_obj;
274             unless ($res) {
275              
276             # $response->print_header();
277             $response->print($_) for @{ $self->fetch($sess) };
278              
279             # $response->error404("Url not found:".join "/",@path);
280             $response->flush;
281             return; #end
282             }
283              
284             if ( ref($res) eq 'HASH'
285             and ( exists $res->{header} or exists $res->{data} ) )
286             {
287              
288             #set headers
289             if ( exists $res->{header} ) {
290             while ( my ( $key, $val ) = each %{ $res->{header} } ) {
291             $response->set_header( $key, $val );
292             }
293             }
294             if ( my $call_back = $res->{call_back} ) {
295             $response->set_callback($call_back)
296             if ref($call_back) eq 'CODE';
297             }
298             $response->print( $res->{data} ) if exists $res->{data};
299             $res = $response;
300             }
301             if ( UNIVERSAL::isa( $res, 'HTML::WebDAO::Response' ) ) {
302              
303             #we gor response !
304             $res->flush;
305             return;
306             }
307             unless ( ref($res) ) {
308             $response->print($res);
309             $response->flush();
310             return;
311             }
312             _log1 $self "Unknown response : $res";
313             $response->print($_) for @{ $self->fetch($sess) };
314             $response->flush;
315             }
316              
317             #fill $self->__events hash event - method
318             sub RegEvent {
319             my ( $self, $ref_obj, $event_name, $ref_sub ) = @_;
320             my $ev_hash = $self->__events;
321             $ev_hash->{$event_name}->{ scalar($ref_obj) } = {
322             ref_obj => $ref_obj,
323             ref_sub => $ref_sub
324             }
325             if ( ref($ref_sub) );
326             return 1;
327             }
328              
329             sub SendEvent {
330             my ( $self, $event_name, @Par ) = @_;
331             my $ev_hash = $self->__events;
332             unless ( exists( $ev_hash->{$event_name} ) ) {
333             _log2 $self "WARN: Event $event_name not exists.";
334             return 0;
335             }
336             foreach my $ref_rec ( keys %{ $ev_hash->{$event_name} } ) {
337             my $ref_sub = $ev_hash->{$event_name}->{$ref_rec}->{ref_sub};
338             my $ref_obj = $ev_hash->{$event_name}->{$ref_rec}->{ref_obj};
339             $ref_obj->$ref_sub( $event_name, @Par );
340             }
341             }
342              
343             =head3 _createObj(,,@parameters)
344              
345             create object by .
346              
347             =cut
348              
349             sub _createObj {
350             my ( $self, $name_obj, $name_func, @par ) = @_;
351             if ( my $pack = _pack4name $self $name_func ) {
352             my $ref_init_hash = {
353             ref_engine => $self->getEngine()
354             , #! Setup _engine refernce for childs!
355             name_obj => $name_obj
356             }; #! Setup _my_name
357             my $obj_ref =
358             $pack->isa('HTML::WebDAO::Element')
359             ? eval "'$pack'\-\>new(\$ref_init_hash,\@par)"
360             : eval "'$pack'\-\>new(\@par)";
361             carp "Error in eval: _createObj $@" if $@;
362             return $obj_ref;
363             }
364             else { _log1 $self "Not registered alias: $name_func"; return }
365             }
366              
367             #sub _parse_html(\@html)
368             #return \@Objects
369             sub _parse_html {
370             my ( $self, $raw_html ) = @_;
371             return [] unless $raw_html;
372              
373             #Mac and DOS line endings
374             $raw_html =~ s/\r\n?/\n/g;
375             my $mass;
376             $mass = [ split( /(.*?<\/WD>)/is, $raw_html ) ];
377             my @res;
378             foreach my $text (@$mass) {
379             my @ref;
380             unless ( $text =~ /^
381             push @ref, $self->_createObj( "none", "_rawhtml_element", \$text )
382             ; #if $text =~ /\s+/;
383             }
384             else {
385             my $lex = new HTML::WebDAO::Lex:: engine => $self;
386             @ref = $lex->lex_data($text); #clean 'empty'
387              
388             # _log3 $self "LEXED:".Dumper([ map {"$_"} @ref])."from $text";
389              
390             }
391             next unless @ref;
392             push @res, @ref;
393             }
394             return \@res;
395             }
396              
397             #Get package for functions name
398             sub _pack4name {
399             my ( $self, $name ) = @_;
400             my $ref = $self->__obj;
401             return $$ref{$name} if ( exists $$ref{$name} );
402             }
403              
404             sub register_class {
405             my ( $self, %register ) = @_;
406             my $_obj = $self->__obj;
407             while ( my ( $class, $alias ) = each %register ) {
408              
409             #check non loaded mods
410             my ( $main, $module ) = $class =~ m/(.*\:\:)?(\S+)$/;
411             $main ||= 'main::';
412             $module .= '::';
413             no strict 'refs';
414             unless ( exists $$main{$module} ) {
415             _log1 $self "Try use $class";
416             eval "use $class";
417             if ($@) {
418             _log1 $self "Error register class :$class with $@ ";
419             return "Error register class :$class with $@ ";
420             next;
421             }
422             }
423             use strict 'refs';
424             $$_obj{$alias} = $class;
425             }
426             return;
427             }
428              
429             sub _destroy {
430             my $self = shift;
431             $self->__store_session_attributes( @{ $self->_get_childs } );
432             $self->SUPER::_destroy;
433             $self->_session(undef);
434             $self->__obj(undef);
435             $self->__events(undef);
436             }
437             1;