Mercurial > pub > Impl
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__