diff Lib/IMPL/DOM/Navigator/Builder.pm @ 34:a8086f85a571

Dom Builder
author Sergey
date Mon, 16 Nov 2009 18:39:25 +0300
parents 7f00786f8210
children f25d021780b3
line wrap: on
line diff
--- a/Lib/IMPL/DOM/Navigator/Builder.pm	Mon Nov 09 16:49:39 2009 +0300
+++ b/Lib/IMPL/DOM/Navigator/Builder.pm	Mon Nov 16 18:39:25 2009 +0300
@@ -2,36 +2,55 @@
 use strict;
 use warnings;
 
-use base qw(IMPL::DOM::Navigator);
+use base qw(IMPL::Object);
 use IMPL::Class::Property;
 use IMPL::Class::Property::Direct;
 require IMPL::DOM::Navigator::SchemaNavigator;
 
 BEGIN {
-    protected _direct property _schemaNavi => prop_all;
+    private _direct property _schemaNavi => prop_all;
+    private _direct property _nodesPath => prop_all;
+    private _direct property _nodeCurrent => prop_all;
+    private _direct property _docClass => prop_all
     public _direct property Document => prop_get | owner_set;
 }
 
-our %CTOR = (
-    'IMPL::DOM::Navigator' => sub { $_[0] } # IMPL::DOM::Navigator($domDocument)
-);
-
 sub CTOR {
-    my ($this,$domDocument,$schema) = @_;
+    my ($this,$docClass,$schema) = @_;
     
-    $this->{$Document} = $domDocument;
-    $this->{$_schemaNavi} = $schema;
+    $this->{$_docClass} = $docClass;
+    $this->{$_schemaNavi} = IMPL::DOM::Navigator::SchemaNavigator->new($schema);
 }
 
 sub NavigateCreate {
     my ($this,$nodeName,%props) = @_;
     
-    
+    if (my $schemaNode = $this->{$_schemaNavi}->NavigateName($nodeName)) {
+        my $class = $schemaNode->can('nativeType') ? $schemaNode->nativeType : 'IMPL::DOM::Node';
+        
+        my $node;
+        if (! $this->{$Document}) {
+            $node = $this->{$Document} = $this->{$_docClass}->new(nodeName => $nodeName,%props);
+        } else {
+            die new IMPL::InvalidOperationException('Can\t create a second top level element');
+            $node = $this->{$Document}->Create($nodeName,$class,\%props);
+            push @{$this->{$_nodesPath}}, $this->{$_nodeCurrent};
+            $this->{$_nodeCurrent}->appendChild($node);
+        }
+        
+        $this->{$_nodeCurrent} = $node;
+        
+        return $node;
+    } else {
+        die new IMPL::InvalidOperationException("The specified node is undefined", $nodeName);
+    }
 }
 
 sub Back {
     my ($this) = @_;
     
+    $this->{$_schemaNavi}->SchemaBack();
+    $this->{$_nodeCurrent} = pop @{$this->{$_nodesPath}};
 }
 
 1;
@@ -67,24 +86,11 @@
 Создает новый узел с указанным именем и переходит в него. В случае если в схеме
 подходящий узел не найден, то вызывается исключение.
 
-При этом схема узла производится по имени, после чего определяется класс для
-создания узла, по алгоритму
-
-=over
-
-=item Проверяется свойство C<type> и если оно есть, то используется оно
+При этом по имени узла ищется его схема, после чего определяется класс для
+создания экземпляра и созданный узел доавляется в документ.
 
-=item Проверяется свойство C<type> самого элемента схемы, если оно есть, то
-используется оно.
-
-=item В качестве класса берется имя узла
-
-=back
-
-Также имя создаваемого узла может быть переопределено свойством C<nodeName>.
-
-Т.о. узел вида C<< <ComplexNode nodeName="Box" type="Container"> >> приведет
-к созданию C<< Container->new(nodeName => 'Box') >>.
+Также имя создаваемого узла НЕ может быть переопределено свойством nodeName, оно
+будет проигнорировано.
 
 =back