diff Lib/IMPL/DOM/Navigator.pm @ 49:16ada169ca75

migrating to the Eclipse IDE
author wizard@linux-odin.local
date Fri, 26 Feb 2010 10:49:21 +0300
parents 1828103371d0
children 196bf443b5e1
line wrap: on
line diff
--- a/Lib/IMPL/DOM/Navigator.pm	Fri Feb 26 01:43:42 2010 +0300
+++ b/Lib/IMPL/DOM/Navigator.pm	Fri Feb 26 10:49:21 2010 +0300
@@ -1,274 +1,274 @@
-package IMPL::DOM::Navigator;
-use strict;
-use warnings;
-
-use base qw(IMPL::Object);
-use IMPL::Class::Property;
-use IMPL::Class::Property::Direct;
-BEGIN {
-    private _direct property _path => prop_all;
-    private _direct property _state => prop_all;
-    private _direct property _savedstates => prop_all;
-    public property Current => {get => \&_getCurrent};
-}
-
-sub CTOR {
-    my ($this,$CurrentNode) = @_;
-    
-    die IMPL::InvalidArgumentException("A starting node is a required paramater") unless $CurrentNode;
-    
-    $this->{$_state} = { alternatives => [ $CurrentNode ], current => 0 };
-}
-
-sub _initNavigator {
-    my ($this,$CurrentNode) = @_;
-    
-    die IMPL::InvalidArgumentException("A starting node is a required paramater") unless $CurrentNode;
-    
-    $this->{$_state} = { alternatives => [ $CurrentNode ], current => 0 };
-    delete $this->{$_path};
-    delete $this->{$_savedstates};
-}
-
-sub _getCurrent {
-    $_[0]->{$_state}{alternatives}[$_[0]->{$_state}{current}]
-}
-
-sub Navigate {
-    my ($this,@path) = @_;
-    
-    return unless @path;
-    
-    my $node;
-    
-    foreach my $query (@path) {
-        if (my $current = $this->Current) {
-            
-            my @alternatives = $current->selectNodes($query);
-            
-            unless (@alternatives) {
-                $current = $this->advanceNavigator or return undef;
-                @alternatives = $current->selectNodes($query);
-            }
-            
-            push @{$this->{$_path}},$this->{$_state};
-            $this->{$_state} = {
-                alternatives => \@alternatives,
-                current => 0,
-                query => $query
-            };
-            
-            $node = $alternatives[0];
-        } else {
-            return undef;
-        }
-    }
-    
-    $node;
-}
-
-sub selectNodes {
-    my ($this,@path) = @_;
-    
-    return internalSelectNodes($this->Current,@path);
-}
-
-sub internalSelectNodes {
-    my $node = shift;
-    my $query = shift;
-    
-    if (@_) {
-        return map internalSelectNodes($_,@_), $node->selectNodes($query);
-    } else {
-        return $node->selectNodes($query);
-    }
-}
-
-sub internalNavigateNodeSet {
-    my ($this,@nodeSet) = @_;
-    
-    push @{$this->{$_path}}, $this->{$_state};
-    
-    $this->{$_state} = {
-        alternatives => \@nodeSet,
-        current => 0
-    };
-    
-    $nodeSet[0];
-}
-
-sub fetch {
-    my ($this) = @_;
-    
-    my $result = $this->Current;
-    $this->advanceNavigator;
-    return $result;
-}
-
-sub advanceNavigator {
-    my ($this) = @_;
-    
-    $this->{$_state}{current}++;
-    
-    if (@{$this->{$_state}{alternatives}} <= $this->{$_state}{current}) {
-        if ( exists $this->{$_state}{query} ) {
-            my $query = $this->{$_state}{query};
-  
-            $this->Back or return undef; # that meams the end of the history
-
-            undef while ( $this->advanceNavigator and not $this->Navigate($query));
-
-            return $this->Current;
-        }
-        return undef;
-    }
-    
-    return $this->Current;
-}
-
-sub doeach {
-    my ($this,$code) = @_;
-    local $_;
-    
-    do {
-        for (my $i = $this->{$_state}{current}; $i < @{$this->{$_state}{alternatives}}; $i++) {
-            $_ = $this->{$_state}{alternatives}[$i];
-            $code->();
-        }
-        $this->{$_state}{current} = @{$this->{$_state}{alternatives}};
-    } while ($this->advanceNavigator);
-}
-
-sub Back {
-    my ($this,$steps) = @_;
-    if ($this->{$_path} and @{$this->{$_path}}) {
-        if ( (not $steps) || $steps == 1) {
-            $this->{$_state} = pop @{$this->{$_path}};
-        } else {
-            $steps ||= 1;
-            
-            $steps = @{$this->{$_path}} - 1 if $steps >= @{$this->{$_path}};
-            
-            $this->{$_state} = (splice @{$this->{$_path}},-$steps)[0];
-        }
-        $this->Current if defined wantarray;
-    } else {
-        return undef;
-    }
-}
-
-sub PathToString {
-    my ($this,$delim) = @_;
-    
-    $delim ||= '/';
-    
-    join($delim,map $_->{alternatives}[$_->{current}]->nodeName, $this->{$_path} ? (@{$this->{$_path}}, $this->{$_state}) : $this->{$_state});
-}
-
-sub clone {
-    my ($this) = @_;
-    
-    my $newNavi = __PACKAGE__->surrogate;
-    
-    $newNavi->{$_path} = [ map { { %{ $_ } }  } @{$this->{$_path}} ] if $this->{$_path};
-    $newNavi->{$_state} = { %{$this->{$_state}} };
-    
-    return $newNavi;
-    
-}
-
-sub saveState {
-    my ($this) = @_;
-    
-    my %state;
-    
-    $state{path} = [ map { { %{ $_ } }  } @{$this->{$_path}} ] if $this->{$_path};
-    $state{state} = { %{$this->{$_state}} };
-    
-    push @{$this->{$_savedstates}}, \%state;
-}
-
-sub restoreState {
-    my ($this) = @_;
-    
-    if ( my $state = pop @{$this->{$_savedstates}||[]} ) {
-        $this->{$_path} = $state->{path};
-        $this->{$_state} = $state->{state};
-    }
-}
-
-sub applyState {
-    my ($this) = @_;
-    
-    pop @{$this->{$_savedstates}||[]};
-}
-
-sub dosafe {
-    my ($this,$transaction) = @_;
-    
-    $this->saveState();
-    
-    my $result;
-    
-    eval {
-        $result = $transaction->();
-    };
-    
-    if ($@) {
-        $this->restoreState();
-        return undef;
-    } else {
-        $this->applyState();
-        return $result;
-    }
-}
-
-1;
-
-__END__
-=pod
-
-=head1 DESCRIPTION
-
-Объект для хождения по дереву DOM объектов.
-
-Результатом навигации является множество узлов (альтернатив).
-
-Состоянием навигатора является текущий набор узлов, позиция в данном наборе,
-а также запрос по которому были получены данные результаты.
-
-Если при навигации указан путь сосящий из нескольких фильтров, то он разбивается
-этапы простой навигации по кадой из частей пути. На каждом элементарном этапе
-навигации образуется ряд альтернатив, и при каждом следующем этапе навигации
-альтернативы предыдущих этапов могут перебираться, до получения положительного
-результата навигации, в противном случае навигация считается невозможной.
-
-=head1 METHODS
-
-=over
-
-=item C<<$obj->new($nodeStart)>>
-
-Создает объект навигатора с указанной начальной позицией.
-
-=item C<<$obj->Navigate([$query,...])>>
-
-Перейти в новый узел используя запрос C<$query>. На данный момент запросом может
-быть только имя узла и будет взят только первый узел. Если по запросу ничего не
-найдено, переход не будет осуществлен.
-
-Возвращает либо новый узел в который перешли, либо C<undef>.
-
-=item C<<$obj->Back()>>
-
-Возвращается в предыдущий узел, если таковой есть.
-
-Возвращает либо узел в который перешли, либо C<undef>.
-
-=item C<<$obj->advanceNavigator()>>
-
-Переходит в следующую альтернативу, соответствующую текущему запросу.
-
-=back
-
-=cut
\ No newline at end of file
+package IMPL::DOM::Navigator;
+use strict;
+use warnings;
+
+use base qw(IMPL::Object);
+use IMPL::Class::Property;
+use IMPL::Class::Property::Direct;
+BEGIN {
+    private _direct property _path => prop_all;
+    private _direct property _state => prop_all;
+    private _direct property _savedstates => prop_all;
+    public property Current => {get => \&_getCurrent};
+}
+
+sub CTOR {
+    my ($this,$CurrentNode) = @_;
+    
+    die IMPL::InvalidArgumentException("A starting node is a required paramater") unless $CurrentNode;
+    
+    $this->{$_state} = { alternatives => [ $CurrentNode ], current => 0 };
+}
+
+sub _initNavigator {
+    my ($this,$CurrentNode) = @_;
+    
+    die IMPL::InvalidArgumentException("A starting node is a required paramater") unless $CurrentNode;
+    
+    $this->{$_state} = { alternatives => [ $CurrentNode ], current => 0 };
+    delete $this->{$_path};
+    delete $this->{$_savedstates};
+}
+
+sub _getCurrent {
+    $_[0]->{$_state}{alternatives}[$_[0]->{$_state}{current}]
+}
+
+sub Navigate {
+    my ($this,@path) = @_;
+    
+    return unless @path;
+    
+    my $node;
+    
+    foreach my $query (@path) {
+        if (my $current = $this->Current) {
+            
+            my @alternatives = $current->selectNodes($query);
+            
+            unless (@alternatives) {
+                $current = $this->advanceNavigator or return undef;
+                @alternatives = $current->selectNodes($query);
+            }
+            
+            push @{$this->{$_path}},$this->{$_state};
+            $this->{$_state} = {
+                alternatives => \@alternatives,
+                current => 0,
+                query => $query
+            };
+            
+            $node = $alternatives[0];
+        } else {
+            return undef;
+        }
+    }
+    
+    $node;
+}
+
+sub selectNodes {
+    my ($this,@path) = @_;
+    
+    return internalSelectNodes($this->Current,@path);
+}
+
+sub internalSelectNodes {
+    my $node = shift;
+    my $query = shift;
+    
+    if (@_) {
+        return map internalSelectNodes($_,@_), $node->selectNodes($query);
+    } else {
+        return $node->selectNodes($query);
+    }
+}
+
+sub internalNavigateNodeSet {
+    my ($this,@nodeSet) = @_;
+    
+    push @{$this->{$_path}}, $this->{$_state};
+    
+    $this->{$_state} = {
+        alternatives => \@nodeSet,
+        current => 0
+    };
+    
+    $nodeSet[0];
+}
+
+sub fetch {
+    my ($this) = @_;
+    
+    my $result = $this->Current;
+    $this->advanceNavigator;
+    return $result;
+}
+
+sub advanceNavigator {
+    my ($this) = @_;
+    
+    $this->{$_state}{current}++;
+    
+    if (@{$this->{$_state}{alternatives}} <= $this->{$_state}{current}) {
+        if ( exists $this->{$_state}{query} ) {
+            my $query = $this->{$_state}{query};
+  
+            $this->Back or return undef; # that meams the end of the history
+
+            undef while ( $this->advanceNavigator and not $this->Navigate($query));
+
+            return $this->Current;
+        }
+        return undef;
+    }
+    
+    return $this->Current;
+}
+
+sub doeach {
+    my ($this,$code) = @_;
+    local $_;
+    
+    do {
+        for (my $i = $this->{$_state}{current}; $i < @{$this->{$_state}{alternatives}}; $i++) {
+            $_ = $this->{$_state}{alternatives}[$i];
+            $code->();
+        }
+        $this->{$_state}{current} = @{$this->{$_state}{alternatives}};
+    } while ($this->advanceNavigator);
+}
+
+sub Back {
+    my ($this,$steps) = @_;
+    if ($this->{$_path} and @{$this->{$_path}}) {
+        if ( (not $steps) || $steps == 1) {
+            $this->{$_state} = pop @{$this->{$_path}};
+        } else {
+            $steps ||= 1;
+            
+            $steps = @{$this->{$_path}} - 1 if $steps >= @{$this->{$_path}};
+            
+            $this->{$_state} = (splice @{$this->{$_path}},-$steps)[0];
+        }
+        $this->Current if defined wantarray;
+    } else {
+        return undef;
+    }
+}
+
+sub PathToString {
+    my ($this,$delim) = @_;
+    
+    $delim ||= '/';
+    
+    join($delim,map $_->{alternatives}[$_->{current}]->nodeName, $this->{$_path} ? (@{$this->{$_path}}, $this->{$_state}) : $this->{$_state});
+}
+
+sub clone {
+    my ($this) = @_;
+    
+    my $newNavi = __PACKAGE__->surrogate;
+    
+    $newNavi->{$_path} = [ map { { %{ $_ } }  } @{$this->{$_path}} ] if $this->{$_path};
+    $newNavi->{$_state} = { %{$this->{$_state}} };
+    
+    return $newNavi;
+    
+}
+
+sub saveState {
+    my ($this) = @_;
+    
+    my %state;
+    
+    $state{path} = [ map { { %{ $_ } }  } @{$this->{$_path}} ] if $this->{$_path};
+    $state{state} = { %{$this->{$_state}} };
+    
+    push @{$this->{$_savedstates}}, \%state;
+}
+
+sub restoreState {
+    my ($this) = @_;
+    
+    if ( my $state = pop @{$this->{$_savedstates}||[]} ) {
+        $this->{$_path} = $state->{path};
+        $this->{$_state} = $state->{state};
+    }
+}
+
+sub applyState {
+    my ($this) = @_;
+    
+    pop @{$this->{$_savedstates}||[]};
+}
+
+sub dosafe {
+    my ($this,$transaction) = @_;
+    
+    $this->saveState();
+    
+    my $result;
+    
+    eval {
+        $result = $transaction->();
+    };
+    
+    if ($@) {
+        $this->restoreState();
+        return undef;
+    } else {
+        $this->applyState();
+        return $result;
+    }
+}
+
+1;
+
+__END__
+=pod
+
+=head1 DESCRIPTION
+
+Объект для хождения по дереву DOM объектов.
+
+Результатом навигации является множество узлов (альтернатив).
+
+Состоянием навигатора является текущий набор узлов, позиция в данном наборе,
+а также запрос по которому были получены данные результаты.
+
+Если при навигации указан путь сосящий из нескольких фильтров, то он разбивается
+этапы простой навигации по кадой из частей пути. На каждом элементарном этапе
+навигации образуется ряд альтернатив, и при каждом следующем этапе навигации
+альтернативы предыдущих этапов могут перебираться, до получения положительного
+результата навигации, в противном случае навигация считается невозможной.
+
+=head1 METHODS
+
+=over
+
+=item C<<$obj->new($nodeStart)>>
+
+Создает объект навигатора с указанной начальной позицией.
+
+=item C<<$obj->Navigate([$query,...])>>
+
+Перейти в новый узел используя запрос C<$query>. На данный момент запросом может
+быть только имя узла и будет взят только первый узел. Если по запросу ничего не
+найдено, переход не будет осуществлен.
+
+Возвращает либо новый узел в который перешли, либо C<undef>.
+
+=item C<<$obj->Back()>>
+
+Возвращается в предыдущий узел, если таковой есть.
+
+Возвращает либо узел в который перешли, либо C<undef>.
+
+=item C<<$obj->advanceNavigator()>>
+
+Переходит в следующую альтернативу, соответствующую текущему запросу.
+
+=back
+
+=cut