changeset 366:935629bf80df

model metadata, in progress
author cin
date Mon, 02 Dec 2013 17:44:38 +0400
parents 7c621bb95e53
children 608e74bc309f
files Lib/IMPL/Web/View/Metadata/BaseMeta.pm Lib/IMPL/Web/View/Metadata/FormMeta.pm Lib/IMPL/Web/View/Metadata/FormProvider.pm
diffstat 3 files changed, 109 insertions(+), 41 deletions(-) [+]
line wrap: on
line diff
--- a/Lib/IMPL/Web/View/Metadata/BaseMeta.pm	Mon Dec 02 02:13:12 2013 +0400
+++ b/Lib/IMPL/Web/View/Metadata/BaseMeta.pm	Mon Dec 02 17:44:38 2013 +0400
@@ -14,6 +14,7 @@
 	props => [
 		model => PROP_RO,
 		modelType => PROP_RO,
+		holdingType => PROP_RO,
 		provider => PROP_RO,
 		name => PROP_RO,
 		label => PROP_RO,
@@ -39,40 +40,57 @@
 	
 	#mixin other args
 	if ($args) {
-		$this->$_($args->{$_}) foreach grep $args->{$_}, qw(name label container template);
+		$this->$_($args->{$_}) foreach grep $args->{$_}, qw(name label container template holdingType);
 	}
 }
 
-sub GetChild {
+sub GetProperty {
 	my ($this,$name) = @_;
 	
-	if(my $child = $this->_childMap->{$name}) {
-		return $child;
-	} else {
-		return $this->_childMap->{$name} = $this->provider->GetChild($this,$name);
-	}
+	$this->_PopulateProperties()
+		unless $this->_childNames;
+	
+	return $this->_childMap->{$name};
 }
 
-sub GetChildren {
+sub GetProperties {
 	my ($this) = @_;
 	
 	if ($this->_childNames) {
 		return [ map $this->_childMap->{$_}, @{$this->_childNames} ];
 	} else {
-		my @childNames;
-		my %childMap;
-		my @result; 
+		return $this->_PopulateProperties;
+	}	
+}
+
+sub _PopulateProperties {
+	my ($this) = @_;
 	
-		foreach my $child (@{$this->provider->PopulateChildren($this)}) {
-			$childMap{$child->name} = $child;
-			push @childNames, $child->name;
-			push @result, $child;
-		}
-		
-		$this->_childMap(\%childMap);
-		$this->_childNames(\@childNames);
-		return \@result;
-	}	
+	my @childNames;
+	my %childMap;
+	my @result; 
+
+	foreach my $child (@{$this->provider->PopulateProperties($this)}) {
+		$childMap{$child->name} = $child;
+		push @childNames, $child->name;
+		push @result, $child;
+	}
+	
+	$this->_childMap(\%childMap);
+	$this->_childNames(\@childNames);
+	return \@result;
+}
+
+sub GetItems {
+	my ($this) = @_;
+	
+	return $this->provider->GetItems($this);
+}
+
+sub GetItem {
+	my ($this,$index) = @_;
+	
+	return $this->provider->GetItem($this,$index);
 }
 
 1;
--- a/Lib/IMPL/Web/View/Metadata/FormMeta.pm	Mon Dec 02 02:13:12 2013 +0400
+++ b/Lib/IMPL/Web/View/Metadata/FormMeta.pm	Mon Dec 02 17:44:38 2013 +0400
@@ -37,7 +37,6 @@
 	shift->decl->isOptional;
 }
 
-
 sub GetOwnErrors {
 	my ($this) = @_;
 	
@@ -88,12 +87,15 @@
 быть более одного в то время, как C<isMultiple = false> или, напротив, ни
 одного при C<isOptional = false>.
 
+Как правило для построения формы данное свойство не требуется.
+
 =head2 C<[get]modelType>
 
 Название типа данных из схемы документа (C<< schema->name >>), если тип не имеет название, то это
 C<ComplexNode> для сложных узлов и C<SimpleNode> для простых.
 
-Для моделей с множественными значениями это свойство означает тип элементов.
+Для моделей с множественными значениями это свойство не задано. Тип элементов
+храниться в свойстве C<holdingType>
 
 =head2 C<[get]decl>
 
@@ -119,10 +121,17 @@
 =begin code
 
 for(my $i=0; $i< 10; $i++) {
-	display_model(
-		$meta->model->[$i],
-		schema => meta->schema, 
-	);
+	display_for($i,'template');
+}
+
+sub display_for {
+	my ($index,$tmpl) = @_;
+	
+	if ($index =~ /^\d+$/) {
+		return render($tmpl, meta => { $meta->GetItem($index) });
+	} else {
+		return render($tmpl, meta => { $meta->GetProperty($index) });
+	}
 }
 
 =end code
--- a/Lib/IMPL/Web/View/Metadata/FormProvider.pm	Mon Dec 02 02:13:12 2013 +0400
+++ b/Lib/IMPL/Web/View/Metadata/FormProvider.pm	Mon Dec 02 17:44:38 2013 +0400
@@ -1,41 +1,82 @@
 package IMPL::Web::View::Metadata::FormProvider;
 use strict;
 
+ues IMPL::lang ;
 use IMPL::declare {
 	require => {
-		Meta => 'IMPL::Web::View::Metadata::FormMeta'
+		Meta => 'IMPL::Web::View::Metadata::FormMeta',
+		
+		Exception => 'IMPL::Exception',
+		ArgException => '-IMPL::InvalidArgumentException'
 	},
 	base => [
 		'IMPL::Object' => undef
 	]
 };
 
-sub GetFormMetadata {
-	my ($this,$model, $form) = @_;
-}
-
-sub PopulateChildren {
+sub PopulateProperties {
 	my ($this,$meta) = @_;
 	
-	map Meta->new($this,), $meta->schema->content->childNodes;
+	die ArgException->new(meta => 'A FormMeta is required')
+		unless is($meta,Meta);
+		
+	my @props;
+		
+	# return empty list of properties in case of multiple values
+	return \@props if $meta->isMultiple;
+		
+	my $navi = SchemaNavigator->new($meta->schema);
+	
+	foreach my $decl (@{$meta->schema->content->childNodes}) {
+		
+		my $schema = $navi->NavigateName($decl->name);
+		
+		my @nodes = $meta->model && $meta->model->selectNodes( sub { $_->schemaSource == $decl } );
+		
+		my %args = (
+			name => $decl->name,
+			decl => $decl,
+			schema => $schema,
+			nodes => \@nodes,
+			errors => [grep _IsErrorRelates(\@nodes,$decl,$_), @{$meta->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(
+			$this,
+			\@nodes,
+			$decl->type,
+			{
+				name => $decl->name,
+				schema => $schema,
+			}
+		)
+	}
 }
 
-sub GetChild {
-	
-}
 
 sub _IsErrorRelates {
-    my ($node,$source,$err) = @_;
+    my ($nodes,$source,$err) = @_;
     
     # this is an own error
-    return 1 if ($node && $err->node && $err->node == $node) || (not($node) && $err->schema == $source );
+    return 1 if ($err->node && grep($err->node == $_, @$nodes)) || (not(@$nodes) && $err->schema == $source );
     
     # this error relates to the child control 
     
-    return 0 unless $node;
+    return 0 unless @$nodes;
     
     for (my $n = $err->parent; $n ; $n = $n->parentNode) {
-        return 1 if $n == $node;
+        return 1 if grep($n == $_, @$nodes);
     }
     
     return 0;