diff Lib/IMPL/Web/View/Metadata/FormMeta.pm @ 367:608e74bc309f

form metadata, mostly done
author cin
date Tue, 03 Dec 2013 17:55:36 +0400
parents 935629bf80df
children 010ceafd0c5a
line wrap: on
line diff
--- a/Lib/IMPL/Web/View/Metadata/FormMeta.pm	Mon Dec 02 17:44:38 2013 +0400
+++ b/Lib/IMPL/Web/View/Metadata/FormMeta.pm	Tue Dec 03 17:55:36 2013 +0400
@@ -5,7 +5,9 @@
 use IMPL::declare {
 	require => {
 		Exception => 'IMPL::Exception',
-		ArgException => '-IMPL::InvalidArgumentException'
+		ArgException => '-IMPL::InvalidArgumentException',
+		OpException => '-IMPL::InvalidOperationException',
+		SchemaNavigator => 'IMPL::DOM::Navigator::SchemaNavigator'
 	},
 	base => [
 		'IMPL::Web::View::Metadata::BaseMeta' => '@_'
@@ -14,43 +16,152 @@
 		nodes => PROP_RO,
 		decl  => PROP_RO,
 		schema => PROP_RO,
-		errors => PROP_RO
+		errors => PROP_RO,
+		group => PROP_RO
 	]
 };
 
+use constant {
+	Meta => __PACKAGE__
+};
+
 sub CTOR {
-	my ($this,$provider,$model,$type,$args) = @_;
+	my ($this,$model,$type,$args) = @_;
 	
 	if ($args) {
-		$this->$_($args->{$_}) foreach grep $args->{$_}, qw(decl schema nodes errors);
+		$this->$_($args->{$_}) foreach grep $args->{$_}, qw(decl schema nodes errors group);
 	}
 	
 	$this->$_() || die ArgException->new($_ => "The $_ is required")
-		foreach qw(decl schema);
+		foreach qw(schema);
 }
 
 sub isMultiple {
-	shift->decl->isMultiple;
+	my ($this) = @_;
+	$this->decl && $this->decl->isMultiple;
 }
 
 sub isOptional {
-	shift->decl->isOptional;
+	my ($this) = @_;
+	not($this->decl) || $this->decl->isOptional;
 }
 
 sub GetOwnErrors {
 	my ($this) = @_;
 	
-	my $node = undef;
-	
-	$node = not($this->isMultiple) && $this->nodes ? $this->nodes->[0] : undef;
+	my $nodes = $this->nodes;
 	
 	return [
-		grep {
-			($node && $_->node && $_->node == $node) || (not($node) && $_->schema == $this->decl )
-		} @{$this->errors || []}
+		grep _IsOwnError($nodes,$this->decl,$_), @{$this->errors || []}
 	];
 }
 
+sub _IsOwnError {
+    my ($nodes,$source,$err) = @_;
+    
+    return 1 if ($err->node && grep($err->node == $_, @$nodes)) || (not(@$nodes) && $err->schema == $source );
+    
+    return 0;
+}
+
+sub _IsErrorRelates {
+    my ($nodes,$source,$err) = @_;
+    
+    # this is an own error
+    return 1 if _IsOwnError($nodes,$source,$err);
+    
+    # this error relates to the child control 
+    
+    return 0 unless @$nodes;
+    
+    for (my $n = $err->parent; $n ; $n = $n->parentNode) {
+        return 1 if grep($n == $_, @$nodes);
+    }
+    
+    return 0;
+} 
+
+sub PopulateProperties {
+	my ($this) = @_;
+	
+	my @props;
+		
+	# return empty list of properties in case of multiple values
+	return \@props if $this->isMultiple;
+		
+	my $navi = SchemaNavigator->new($this->schema);
+	
+	foreach my $decl (@{$this->schema->content->childNodes}) {
+		
+		my $schema = $navi->NavigateName($decl->name);
+		$navi->SchemaBack();
+		
+		my @nodes = $this->model && $this->model->selectNodes( sub { $_->schemaSource == $decl } );
+		
+		my %args = (
+			name => $decl->name,
+			decl => $decl,
+			schema => $schema,
+			nodes => \@nodes,
+			errors => [grep _IsErrorRelates(\@nodes,$decl,$_), @{$this->errors || []}]
+		);
+		
+		my ($model,$type);
+		
+		if ($decl->isMultiple) {
+			$model = \@nodes;
+			$type = 'ARRAY';
+			$args{holdingType} = $decl->type;
+		} else {
+			$model = shift @nodes;
+			$type = $decl->type;
+		}
+
+		push @props, Meta->new($model,$type,\%args);
+	}
+	
+	return \@props;
+}
+
+sub GetItems {
+	my ($this) = @_;
+	
+	die OpException->new("The operation must be performed on the container")
+		unless $this->isMultiple;
+		
+	my $i = 0;
+	
+	return [
+		map $this->_GetItemMeta($_,$i++), @{$this->model || []}
+	];
+}
+
+sub GetItem {
+	my ($this,$index) = @_;
+	
+	die OpException->new("The operation must be performed on the container")
+		unless $this->isMultiple;
+		
+	my $node = $this->model->[$index];
+	
+	return $this->GetItemMeta($node,$index);
+}
+
+sub _GetItemMeta {
+	my ($this,$node,$index) = @_;
+	
+	return Meta->new(
+		$node,
+		$this->decl->type,
+		{
+			name => $index,
+			schema => $this->schema,
+			errors => [grep _IsOwnError([$node],$this->decl,$_), @{$this->errors ||[]} ],
+			group => $this
+		}
+	);
+}
+
 1;
 
 __END__