changeset 368:010ceafd0c5a

form metadata + tests
author cin
date Wed, 04 Dec 2013 17:31:53 +0400
parents 608e74bc309f
children 7c784144d2f1
files Lib/IMPL/DOM/Document.pm Lib/IMPL/DOM/Navigator.pm Lib/IMPL/DOM/Navigator/Builder.pm Lib/IMPL/DOM/Navigator/SchemaNavigator.pm Lib/IMPL/DOM/XMLReader.pm Lib/IMPL/Resources/Format.pm Lib/IMPL/Web/View/Metadata/BaseMeta.pm Lib/IMPL/Web/View/Metadata/FormMeta.pm _test/Resources/person_info2.xml _test/Test/Web/View.pm
diffstat 10 files changed, 115 insertions(+), 45 deletions(-) [+]
line wrap: on
line diff
--- 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'));
     }
 }
 
--- 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];
--- 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 {
--- 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__
 
--- 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;
--- 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||'<undef>';
 }
 
 sub _defaultResolver {
--- 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;
--- 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
 		}
 	);
 }
--- /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 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<personInfo code="1552-34af" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://implab.org/person/" xsi:schemaLocation="http://implab.org/person/ person.xsd">
+	<firstName>Norman</firstName>
+	<lastName>Freeman</lastName>
+	<address>
+		<street>hellroad</street>
+		<line>1</line>
+	</address>
+	<address>
+		<street>waypass</street>
+		<line>2</line>
+	</address>
+	<address>
+		<line>2</line>
+	</address>
+	<age>true</age>
+</personInfo>
+
--- 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};	
+	});
 };