# HG changeset patch # User cin # Date 1386163913 -14400 # Node ID 010ceafd0c5a8d509c2d1c6a23161afc42500d37 # Parent 608e74bc309f115de7856bfe366daebd86179590 form metadata + tests diff -r 608e74bc309f -r 010ceafd0c5a Lib/IMPL/DOM/Document.pm --- a/Lib/IMPL/DOM/Document.pm Tue Dec 03 17:55:36 2013 +0400 +++ b/Lib/IMPL/DOM/Document.pm Wed Dec 04 17:31:53 2013 +0400 @@ -3,12 +3,16 @@ use warnings; use IMPL::lang; +use IMPL::Const qw(:prop); use IMPL::declare { require => { DOMNode => 'IMPL::DOM::Node' }, base => [ DOMNode => '@_' + ], + props => [ + schemaDocument => PROP_RW ] }; @@ -48,7 +52,7 @@ { my $empty; sub Empty() { - return $empty ? $empty : $empty = __PACKAGE__->new(nodeName => 'Empty'); + return $empty ? $empty : ($empty = __PACKAGE__->new(nodeName => 'Empty')); } } diff -r 608e74bc309f -r 010ceafd0c5a Lib/IMPL/DOM/Navigator.pm --- a/Lib/IMPL/DOM/Navigator.pm Tue Dec 03 17:55:36 2013 +0400 +++ b/Lib/IMPL/DOM/Navigator.pm Wed Dec 04 17:31:53 2013 +0400 @@ -129,12 +129,11 @@ sub Back { my ($this,$steps) = @_; + if ($this->{$_path} and @{$this->{$_path}}) { - if ( (not $steps) || $steps == 1) { + if ( (not defined $steps) || $steps == 1) { $this->{$_state} = pop @{$this->{$_path}}; - } else { - $steps ||= 1; - + } elsif ($steps > 0) { $steps = @{$this->{$_path}} - 1 if $steps >= @{$this->{$_path}}; $this->{$_state} = (splice @{$this->{$_path}},-$steps)[0]; diff -r 608e74bc309f -r 010ceafd0c5a Lib/IMPL/DOM/Navigator/Builder.pm --- a/Lib/IMPL/DOM/Navigator/Builder.pm Tue Dec 03 17:55:36 2013 +0400 +++ b/Lib/IMPL/DOM/Navigator/Builder.pm Wed Dec 04 17:31:53 2013 +0400 @@ -46,6 +46,8 @@ my $node; if (! $this->{$Document}) { + # keep reference to the schema document + $props{schemaDocument} = $this->{$_schemaNavi}->schema; $node = $this->{$Document} = $this->{$_docClass}->new(nodeName => $nodeName,%props); $this->_initNavigator($node); } else { diff -r 608e74bc309f -r 010ceafd0c5a Lib/IMPL/DOM/Navigator/SchemaNavigator.pm --- a/Lib/IMPL/DOM/Navigator/SchemaNavigator.pm Tue Dec 03 17:55:36 2013 +0400 +++ b/Lib/IMPL/DOM/Navigator/SchemaNavigator.pm Wed Dec 04 17:31:53 2013 +0400 @@ -114,6 +114,10 @@ } } +sub schema { + goto &Schema; +} + 1; __END__ diff -r 608e74bc309f -r 010ceafd0c5a Lib/IMPL/DOM/XMLReader.pm --- a/Lib/IMPL/DOM/XMLReader.pm Tue Dec 03 17:55:36 2013 +0400 +++ b/Lib/IMPL/DOM/XMLReader.pm Wed Dec 04 17:31:53 2013 +0400 @@ -91,12 +91,18 @@ $parser->ParseFile($file); my $doc = $parser->Navigator->Document; + my @errors; if ($schema) { - my @errors = $parser->Navigator->BuildErrors; + @errors = $parser->Navigator->BuildErrors; push @errors, $schema->Validate($doc); - die new IMPL::Exception("Loaded document doesn't match the schema", @errors) if @errors; } - return $doc; + + if (wantarray) { + return $doc,\@errors; + } else { + die new IMPL::Exception("Loaded document doesn't match the schema", @errors) if @errors; + return $doc; + } } 1; diff -r 608e74bc309f -r 010ceafd0c5a Lib/IMPL/Resources/Format.pm --- a/Lib/IMPL/Resources/Format.pm Tue Dec 03 17:55:36 2013 +0400 +++ b/Lib/IMPL/Resources/Format.pm Wed Dec 04 17:31:53 2013 +0400 @@ -11,6 +11,7 @@ $args ||= {}; $resolver ||= \&_defaultResolver; + $string ||= ''; $string =~ s/%(\w+(?:\.\w+)*)%/_getvalue($args,$1,"\[$1\]",$resolver)/ge; @@ -28,7 +29,7 @@ $obj = $resolver->($obj,$chunk); } } - return $obj; + return $obj||''; } sub _defaultResolver { diff -r 608e74bc309f -r 010ceafd0c5a Lib/IMPL/Web/View/Metadata/BaseMeta.pm --- a/Lib/IMPL/Web/View/Metadata/BaseMeta.pm Tue Dec 03 17:55:36 2013 +0400 +++ b/Lib/IMPL/Web/View/Metadata/BaseMeta.pm Wed Dec 04 17:31:53 2013 +0400 @@ -57,7 +57,7 @@ my %childMap; my @result; - foreach my $child (@{$this->PopulateProperties($this)}) { + foreach my $child (@{$this->PopulateProperties()}) { $childMap{$child->name} = $child; push @childNames, $child->name; push @result, $child; diff -r 608e74bc309f -r 010ceafd0c5a Lib/IMPL/Web/View/Metadata/FormMeta.pm --- a/Lib/IMPL/Web/View/Metadata/FormMeta.pm Tue Dec 03 17:55:36 2013 +0400 +++ b/Lib/IMPL/Web/View/Metadata/FormMeta.pm Wed Dec 04 17:31:53 2013 +0400 @@ -109,12 +109,12 @@ my ($model,$type); if ($decl->isMultiple) { - $model = \@nodes; + $model = \@nodes; $type = 'ARRAY'; - $args{holdingType} = $decl->type; + $args{holdingType} = $schema->type; } else { $model = shift @nodes; - $type = $decl->type; + $type = $schema->type; } push @props, Meta->new($model,$type,\%args); @@ -132,7 +132,7 @@ my $i = 0; return [ - map $this->_GetItemMeta($_,$i++), @{$this->model || []} + map $this->_GetItemMeta($_,$i++), @{$this->nodes} ]; } @@ -142,22 +142,26 @@ die OpException->new("The operation must be performed on the container") unless $this->isMultiple; - my $node = $this->model->[$index]; + my $node = $this->nodes->[$index]; - return $this->GetItemMeta($node,$index); + return $this->_GetItemMeta($node,$index); } sub _GetItemMeta { my ($this,$node,$index) = @_; + my @nodes; + push @nodes,$node if $node; + return Meta->new( $node, - $this->decl->type, + $this->schema->type, { name => $index, schema => $this->schema, - errors => [grep _IsOwnError([$node],$this->decl,$_), @{$this->errors ||[]} ], - group => $this + errors => [grep _IsErrorRelates([$node],$this->decl,$_), @{$this->errors ||[]} ], + group => $this, + nodes => \@nodes } ); } diff -r 608e74bc309f -r 010ceafd0c5a _test/Resources/person_info2.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/_test/Resources/person_info2.xml Wed Dec 04 17:31:53 2013 +0400 @@ -0,0 +1,18 @@ + + + Norman + Freeman +
+ hellroad + 1 +
+
+ waypass + 2 +
+
+ 2 +
+ true +
+ diff -r 608e74bc309f -r 010ceafd0c5a _test/Test/Web/View.pm --- a/_test/Test/Web/View.pm Tue Dec 03 17:55:36 2013 +0400 +++ b/_test/Test/Web/View.pm Wed Dec 04 17:31:53 2013 +0400 @@ -16,7 +16,8 @@ Schema => 'IMPL::DOM::Schema', Builder => 'IMPL::DOM::Navigator::Builder', Document => 'IMPL::DOM::Document', - XMLReader => 'IMPL::DOM::XMLReader' + XMLReader => 'IMPL::DOM::XMLReader', + MProfiler => '-IMPL::Profiler::Memory' }, base => [ 'IMPL::Test::Unit' => '@_' @@ -44,33 +45,64 @@ test TestFormMetadata => sub { my ($this) = @_; - my $schema = Schema->LoadSchema($this->GetResourceFile('Resources','person.schema.xml')); - my $builder = Builder->new(Document, $schema); - - my $reader = XMLReader->new( Navigator => $builder ); + # preload to avoid the false memory leak dection + Schema->MetaSchema->Validate(Schema->MetaSchema); + Document->Empty(); + require IMPL::DOM::Schema::Validator::RegExp; - $reader->ParseFile("Resources/person_info.xml"); - - my $doc = $builder->document; - my @errors = $builder->buildErrors; - - push @errors, $schema->Validate($doc); + AssertMemoryLeak(sub{ + my ($doc,$errors) = XMLReader->LoadDocument( + $this->GetResourceFile('Resources','person_info2.xml'), + $this->GetResourceFile('Resources','person.schema.xml') + ); + + my $meta = FormMeta->new( + $doc, + $doc->schemaSource->type, + { + decl => $doc->schemaSource, + schema => $doc->schema, + errors => $errors + } + ); + + assert(@{$errors||[]} == 2); - my $meta = FormMeta->new( - $doc, - $doc->schemaSource->type, - { - decl => $doc->schemaSource, - schema => $doc->schema, - errors => \@errors - } - ); - - my $props = $meta->GetProperties; - - my $prop = $meta->GetProperty('address'); - - join ',', map $_->GetProperty('line')->name, @{$prop->GetItems}; + my $props = $meta->GetProperties; + + assertarray( + [map $_->name, @$props], + [qw(firstName lastName age address)] + ); + assertarray( + [map $_->modelType, @$props], + [undef,undef,'number','ARRAY'] + ); + + my $prop = $meta->GetProperty('address'); + + assert($prop); + assert($prop->schema->type eq 'address'); + assert($prop->isMultiple); + + assert(@{$prop->errors || []} == 1); + assertarray( + [map scalar(@{$_->errors || []}), @{$prop->GetItems}], + [0,0,1] + ); + + my $item = $prop->GetItem(2); + + assert(@{$item->errors} == 1); + assert(@{$item->GetOwnErrors()} == 0); + + assert($item->GetProperty('street')); + + assert(@{$item->GetProperty('street')->errors} == 1); + assert(@{$item->GetProperty('street')->GetOwnErrors()} == 1); + + #join ',', map $_->GetProperty('line')->name, @{$prop->GetItems}; + }); };