diff Lib/IMPL/DOM/Navigator/Builder.pm @ 104:196bf443b5e1

DOM::Schema RC0 inflators support, validation and some other things, Minor and major fixes almost for everything. A 'Source' property of the ValidationErrors generated from a NodeSet or a NodeList is subject to change in the future.
author wizard
date Tue, 11 May 2010 02:42:59 +0400
parents c289ed9662ca
children 83e356614c1e
line wrap: on
line diff
--- a/Lib/IMPL/DOM/Navigator/Builder.pm	Fri May 07 18:17:40 2010 +0400
+++ b/Lib/IMPL/DOM/Navigator/Builder.pm	Tue May 11 02:42:59 2010 +0400
@@ -6,12 +6,14 @@
 use IMPL::Class::Property;
 use IMPL::Class::Property::Direct;
 require IMPL::DOM::Navigator::SchemaNavigator;
+require IMPL::DOM::Schema::ValidationError;
 
 BEGIN {
     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 BuildErrors => prop_get | prop_list;
     public _direct property Document => prop_get | owner_set;
 }
 
@@ -26,8 +28,9 @@
     my ($this,$nodeName,%props) = @_;
     
     if (my $schemaNode = $this->{$_schemaNavi}->NavigateName($nodeName)) {
-        my $class = $schemaNode->can('nativeType') ? $schemaNode->nativeType : 'IMPL::DOM::Node';
-        $this->inflateProperties($schemaNode,\%props);
+        my $class = $schemaNode->can('nativeType') ? $schemaNode->nativeType || 'IMPL::DOM::Node' : 'IMPL::DOM::Node';
+        
+        my @errors = $this->inflateProperties($schemaNode,\%props);
         
         my $node;
         if (! $this->{$Document}) {
@@ -41,6 +44,20 @@
         
         $this->{$_nodeCurrent} = $node;
         
+        if (@errors) {
+        	$this->BuildErrors->Append(
+        		map {
+					IMPL::DOM::Schema::ValidationError->new(
+						Node => $node,
+						Source => $this->{$_schemaNavi}->SourceSchemaNode,
+						Schema => $schemaNode,
+						Message => $schemaNode->messageInflateError,
+						Error => $_
+					)        			
+        		} @errors
+        	);
+        }
+        
         return $node;
     } else {
         die new IMPL::InvalidOperationException("The specified node is undefined", $nodeName);
@@ -49,22 +66,36 @@
 
 sub inflateProperties {
 	my ($this,$schemaNode,$refProps) = @_;
-	
-	$refProps->{$_->name} = $_->inflator->new($refProps->{$_->name})
-		foreach $schemaNode->selectNodes(
-			sub {
-				$_->nodeName eq 'Property' and exists $refProps->{$_->name} and $_->inflator 
-			}
-		);
+	my @errors;
+	foreach my $schemaProp ( $schemaNode->selectNodes('Property') ) {
+		next if not exists $refProps->{$schemaProp->name};
+		my $result = eval {$schemaProp->inflateValue($refProps->{$schemaProp->name}) };
+		if (my $e = $@) {
+			push @errors, $e;
+		} else {
+			$refProps->{$schemaProp->name} = $result;
+		}		
+	}
+	return @errors;
 }
 
 sub inflateValue {
-	my ($this,$value) = @_;
-	my $schemaNode = $this->{$_schemaNavi}->Current;
-	if ($schemaNode->can('inflator') and my $inflator = $schemaNode->inflator) {
-		return $inflator->new($value);
+	my ($this,$value,$node) = @_;
+	
+	my $nodeSchema = $this->{$_schemaNavi}->Current;
+	
+	my $result = eval { $nodeSchema->inflateValue($value) };
+	if (my $e=$@) {
+		$this->BuildErrors->Append(new IMPL::DOM::Schema::ValidationError(
+			Schema =>  $nodeSchema,
+			Node => $node,
+			Error => $e,
+			Message => $nodeSchema->messageInflateError,
+			Source => $this->{$_schemaNavi}->SourceSchemaNode
+		));
+		return $value;
 	} else {
-		return $value;
+		return $result;
 	}
 }