Mercurial > pub > Impl
diff Lib/IMPL/DOM/Navigator/SchemaNavigator.pm @ 24:7f00786f8210
Первая рабочая реазизация схемы и навигаторов
author | Sergey |
---|---|
date | Mon, 05 Oct 2009 00:48:49 +0400 |
parents | 818c74b038ae |
children | a8086f85a571 |
line wrap: on
line diff
--- a/Lib/IMPL/DOM/Navigator/SchemaNavigator.pm Wed Sep 30 17:43:52 2009 +0400 +++ b/Lib/IMPL/DOM/Navigator/SchemaNavigator.pm Mon Oct 05 00:48:49 2009 +0400 @@ -6,10 +6,15 @@ use IMPL::Class::Property; use IMPL::Class::Property::Direct; +require IMPL::DOM::Schema::ComplexType; +require IMPL::DOM::Schema::NodeSet; +require IMPL::DOM::Schema::AnyNode; + __PACKAGE__->PassThroughArgs; BEGIN { public _direct property Schema => prop_get; + private _direct property _historySteps => prop_all; } sub CTOR { @@ -20,19 +25,72 @@ die new IMPL::InvalidArgumentException("A schema object is required") unless $schema->isa('IMPL::DOM::Schema'); } -sub Navigate { - my ($this,$query) = @_; +my $schemaAnyNode = IMPL::DOM::Schema::ComplexType->new(type => '::AnyNodeType', nativeType => 'IMPL::DOM::ComplexNode')->appendRange( + IMPL::DOM::Schema::NodeSet->new()->appendRange( + IMPL::DOM::Schema::AnyNode->new() + ) +); + +sub NavigateName { + my ($this,$name) = @_; - if (my ($newNode) = $this->Current->selectNodes($query)) { - if (ref $newNode eq 'IMPL::DOM::Schema::Node') { - $newNode = $this->{$Schema}->ResolveType($newNode->type) || $newNode; + # perform a safe navigation + return dosafe $this sub { + my $steps = 1; + # navigate to node + if ( + my $node = $this->Navigate( sub { + $_->isa('IMPL::DOM::Schema::Node') and ( + $_->name eq $name + or + $_->nodeName eq 'AnyNode' + or + ( $_->nodeName eq 'SwitchNode' and $_->selectNodes( sub { $_->name eq $name } ) ) + ) + }) + ) { + if ($node->nodeName eq 'AnyNode') { + # if we navigate to the anynode + # assume it to be ComplexType by default + $node = $node->type ? $this->{$Schema}->resolveType($node->type) : $schemaAnyNode; + } elsif ($node->nodeName eq 'SwitchNode') { + # if we are in the switchnode + # navigate to the target node + $node = $this->Navigate(sub { $_->name eq $name }); + $steps ++; + } + + if ($node->nodeName eq 'Node') { + # if we navigate to a reference + # resolve it + $node = $this->{$Schema}->resolveType($node->type); + $this->internalNavigateNodeSet($node); + $steps++; + } + + # if target node is a complex node + if ($node->isa('IMPL::DOM::Schema::ComplexNode')) { + # navigate to it's content + $this->internalNavigateNodeSet($node->content); + $steps ++; + } + + push @{$this->{$_historySteps}},$steps; + + # return found node schema + return $node; + } else { + die; # abort navigation } - return $this->_NavigateNode($newNode); - } else { - return undef; } } +sub SchemaBack { + my ($this) = @_; + + $this->Back(pop @{$this->{$_historySteps}}) if $this->{$_historySteps}; +} + 1; __END__ @@ -40,7 +98,23 @@ =head1 DESCRIPTION - , , <Node nodeName="SomeName" type="ReferencedType"/>. - . + , + . + +=head1 METHODS + +=over + +=item C<< $navi->NavigateName($name) >> + + . C<name> + +=item C<< $navi->SchemaBack >> + + C<NavigateName>. + + . + +=back =cut \ No newline at end of file