Mercurial > pub > Impl
diff Lib/Form/Container.pm @ 49:16ada169ca75
migrating to the Eclipse IDE
author | wizard@linux-odin.local |
---|---|
date | Fri, 26 Feb 2010 10:49:21 +0300 |
parents | 03e58a454b20 |
children | 76515373dac0 |
line wrap: on
line diff
--- a/Lib/Form/Container.pm Fri Feb 26 01:43:42 2010 +0300 +++ b/Lib/Form/Container.pm Fri Feb 26 10:49:21 2010 +0300 @@ -1,170 +1,170 @@ -package Form::Container; -use strict; -use Common; -use Form::Filter; -use base qw(Form::Item); - -BEGIN { - DeclareProperty Schema => ACCESS_READ; - DeclareProperty Children => ACCESS_READ; -} - -sub CTOR { - my ($this,%args) = @_; - $args{Schema} or die new Exception('A schema is required'); - - $this->SUPER::CTOR(@args{qw(Id Form Parent Attributes)}); - $this->{$Schema} = $args{Schema}; -} - -sub ResolveItem { - my ($this,$ItemId) = @_; - - if (my $schemaChild = $this->{$Schema}->FindChild($ItemId->Name)) { - if ($schemaChild->isMulti) { - defined $ItemId->InstanceID or die new Exception('Instance id is required for a muti element'); - if (my $child = $this->{$Children}{$ItemId->Name}[$ItemId->InstanceID]){ - return $child; - } else { - return undef if not $this->Form->AutoCreate; - return $this->{$Children}{$ItemId->Name}[$ItemId->InstanceID] = $this->Form->CreateInstance($schemaChild,$ItemId,$this); - } - - } else { - defined $ItemId->InstanceID and die new Exception('The child is a single element',$this->Id->Canonical,$ItemId->Name); - if(my $child = $this->{$Children}{$ItemId->Name}) { - return $child; - } else { - return undef if not $this->Form->AutoCreate; - return $this->{$Children}{$ItemId->Name} = $this->Form->CreateInstance($schemaChild,$ItemId,$this); - } - } - } else { - die new Exception('The requested item isn\'t exists in the schema', $this->Id->Canonical,$ItemId->Name); - } -} - -sub isEmpty { - my ($this) = @_; - - foreach my $child (values %{$this->{$Children} || {} }) { - if (ref $child eq 'ARRAY') { - foreach my $inst (@$child) { - return 0 if not $child->isEmpty; - } - } else { - return 0 if not $child->isEmpty; - } - } - - return 1; -} - -=pod -Получает дочерние контенеры в виде списка, при том только не пустые контейнеры. -Если дочернний контейнер не множественный, то список будет состоять из одного элемента. -=cut -sub GetChild { - my ($this,$name) = @_; - return unless exists $this->{$Children}{$name}; - return( grep $_, map { UNIVERSAL::isa($_,'ARRAY') ? @{$_} : $_ } $this->{$Children}{$name} ); -} - -=pod -Выполняет фильтры по схеме для себя и всех детей. -Фильтры определяются по схеме и вызываются в различнх контекстах - -* сначала для группы, -* потом для детишек, причем если - * детишки множественные, то - * снсчала для набора детишек, а потом - * для каждого в отдельности -=cut -sub Validate { - my ($this,$rhDisableFilters) = @_; - - $rhDisableFilters ||= {}; - - my @errors; - - foreach my $filter (grep {$_->SUPPORTED_CONTEXT & (Form::Filter::CTX_SINGLE) and not exists $rhDisableFilters->{$_}} map {$_->Instance} $this->{$Schema}->Filters) { - my $result = $filter->Invoke($this,Form::Filter::CTX_SINGLE | Form::Filter::CTX_EXISTENT,$this->{$Schema}); - if ($result->State == Form::FilterResult::STATE_SUCCESS_STOP) { - return (); - } elsif ($result->State == Form::FilterResult::STATE_ERROR) { - push @errors,$result; - } - } - - CHILD_LOOP: foreach my $schemaChild ($this->{$Schema}->Children) { - - if ($schemaChild->isMulti) { - my %DisableFilters; - foreach my $filter (grep {$_->SUPPORTED_CONTEXT & Form::Filter::CTX_SET} map {$_->Instance} $schemaChild->Filters) { - - my $result = $filter->Invoke($this->{$Children}{$schemaChild->Name},Form::Filter::CTX_SET,$schemaChild,$this); - if ($result->State == Form::FilterResult::STATE_ERROR) { - push @errors,$result; - # не проверять другие фильтры вообще - next CHILD_LOOP; - } elsif ($result->State == Form::FilterResult::STATE_SUCCESS_STOP) { - # не проверять другие фильтры вообще - next CHILD_LOOP; - } elsif ($result->State == Form::FilterResult::STATE_SUCCESS_STAY) { - # не проверять данный фильтр на каждом экземпляре - $DisableFilters{$filter} = 1; - } else { - # STATE_SUCCESS - все ок - } - } - - $_ and push @errors,$_->Validate(\%DisableFilters) foreach grep !$_->isEmpty, $this->GetChild($schemaChild->Name); - - } else { - my %DisableFilters; - - # проверяем фильтры, которые могут применяться на несуществующем значении - foreach my $filter (grep { $_->SUPPORTED_CONTEXT & Form::Filter::CTX_SINGLE and not $_->SUPPORTED_CONTEXT & Form::Filter::CTX_EXISTENT} map {$_->Instance} $schemaChild->Filters) { - my $result = $filter->Invoke($this->{$Children}{$schemaChild->Name},Form::Filter::CTX_SINGLE,$schemaChild,$this); - - if ($result->State == Form::FilterResult::STATE_ERROR) { - push @errors,$result; - # не проверять другие фильтры вообще - next CHILD_LOOP; - } elsif ($result->State == Form::FilterResult::STATE_SUCCESS_STOP) { - # не проверять другие фильтры вообще - next CHILD_LOOP; - } else { - # STATE_SUCCESS(_STAY) - все ок - $DisableFilters{$filter} = 1; - } - } - - # если значение существует, то применяем оставшиеся фильтры - push @errors,$this->{$Children}{$schemaChild->Name}->Validate(\%DisableFilters) if $this->{$Children}{$schemaChild->Name}; - } - - } - - return @errors; -} - -sub Dispose { - my ($this) = @_; - - foreach my $child (values %{ $this->{$Children} || {} }) { - if (ref $child eq 'ARRAY') { - foreach my $inst (@$child) { - $inst->Dispose; - } - } else { - die new IMPL::Exception("Child is null",%{ $this->{$Children} }) if not $child; - $child->Dispose; - } - } - - delete @$this{$Schema,$Children}; - - $this->SUPER::Dispose; -} -1; \ No newline at end of file +package Form::Container; +use strict; +use Common; +use Form::Filter; +use base qw(Form::Item); + +BEGIN { + DeclareProperty Schema => ACCESS_READ; + DeclareProperty Children => ACCESS_READ; +} + +sub CTOR { + my ($this,%args) = @_; + $args{Schema} or die new Exception('A schema is required'); + + $this->SUPER::CTOR(@args{qw(Id Form Parent Attributes)}); + $this->{$Schema} = $args{Schema}; +} + +sub ResolveItem { + my ($this,$ItemId) = @_; + + if (my $schemaChild = $this->{$Schema}->FindChild($ItemId->Name)) { + if ($schemaChild->isMulti) { + defined $ItemId->InstanceID or die new Exception('Instance id is required for a muti element'); + if (my $child = $this->{$Children}{$ItemId->Name}[$ItemId->InstanceID]){ + return $child; + } else { + return undef if not $this->Form->AutoCreate; + return $this->{$Children}{$ItemId->Name}[$ItemId->InstanceID] = $this->Form->CreateInstance($schemaChild,$ItemId,$this); + } + + } else { + defined $ItemId->InstanceID and die new Exception('The child is a single element',$this->Id->Canonical,$ItemId->Name); + if(my $child = $this->{$Children}{$ItemId->Name}) { + return $child; + } else { + return undef if not $this->Form->AutoCreate; + return $this->{$Children}{$ItemId->Name} = $this->Form->CreateInstance($schemaChild,$ItemId,$this); + } + } + } else { + die new Exception('The requested item isn\'t exists in the schema', $this->Id->Canonical,$ItemId->Name); + } +} + +sub isEmpty { + my ($this) = @_; + + foreach my $child (values %{$this->{$Children} || {} }) { + if (ref $child eq 'ARRAY') { + foreach my $inst (@$child) { + return 0 if not $child->isEmpty; + } + } else { + return 0 if not $child->isEmpty; + } + } + + return 1; +} + +=pod +Получает дочерние контенеры в виде списка, при том только не пустые контейнеры. +Если дочернний контейнер не множественный, то список будет состоять из одного элемента. +=cut +sub GetChild { + my ($this,$name) = @_; + return unless exists $this->{$Children}{$name}; + return( grep $_, map { UNIVERSAL::isa($_,'ARRAY') ? @{$_} : $_ } $this->{$Children}{$name} ); +} + +=pod +Выполняет фильтры по схеме для себя и всех детей. +Фильтры определяются по схеме и вызываются в различнх контекстах + +* сначала для группы, +* потом для детишек, причем если + * детишки множественные, то + * снсчала для набора детишек, а потом + * для каждого в отдельности +=cut +sub Validate { + my ($this,$rhDisableFilters) = @_; + + $rhDisableFilters ||= {}; + + my @errors; + + foreach my $filter (grep {$_->SUPPORTED_CONTEXT & (Form::Filter::CTX_SINGLE) and not exists $rhDisableFilters->{$_}} map {$_->Instance} $this->{$Schema}->Filters) { + my $result = $filter->Invoke($this,Form::Filter::CTX_SINGLE | Form::Filter::CTX_EXISTENT,$this->{$Schema}); + if ($result->State == Form::FilterResult::STATE_SUCCESS_STOP) { + return (); + } elsif ($result->State == Form::FilterResult::STATE_ERROR) { + push @errors,$result; + } + } + + CHILD_LOOP: foreach my $schemaChild ($this->{$Schema}->Children) { + + if ($schemaChild->isMulti) { + my %DisableFilters; + foreach my $filter (grep {$_->SUPPORTED_CONTEXT & Form::Filter::CTX_SET} map {$_->Instance} $schemaChild->Filters) { + + my $result = $filter->Invoke($this->{$Children}{$schemaChild->Name},Form::Filter::CTX_SET,$schemaChild,$this); + if ($result->State == Form::FilterResult::STATE_ERROR) { + push @errors,$result; + # не проверять другие фильтры вообще + next CHILD_LOOP; + } elsif ($result->State == Form::FilterResult::STATE_SUCCESS_STOP) { + # не проверять другие фильтры вообще + next CHILD_LOOP; + } elsif ($result->State == Form::FilterResult::STATE_SUCCESS_STAY) { + # не проверять данный фильтр на каждом экземпляре + $DisableFilters{$filter} = 1; + } else { + # STATE_SUCCESS - все ок + } + } + + $_ and push @errors,$_->Validate(\%DisableFilters) foreach grep !$_->isEmpty, $this->GetChild($schemaChild->Name); + + } else { + my %DisableFilters; + + # проверяем фильтры, которые могут применяться на несуществующем значении + foreach my $filter (grep { $_->SUPPORTED_CONTEXT & Form::Filter::CTX_SINGLE and not $_->SUPPORTED_CONTEXT & Form::Filter::CTX_EXISTENT} map {$_->Instance} $schemaChild->Filters) { + my $result = $filter->Invoke($this->{$Children}{$schemaChild->Name},Form::Filter::CTX_SINGLE,$schemaChild,$this); + + if ($result->State == Form::FilterResult::STATE_ERROR) { + push @errors,$result; + # не проверять другие фильтры вообще + next CHILD_LOOP; + } elsif ($result->State == Form::FilterResult::STATE_SUCCESS_STOP) { + # не проверять другие фильтры вообще + next CHILD_LOOP; + } else { + # STATE_SUCCESS(_STAY) - все ок + $DisableFilters{$filter} = 1; + } + } + + # если значение существует, то применяем оставшиеся фильтры + push @errors,$this->{$Children}{$schemaChild->Name}->Validate(\%DisableFilters) if $this->{$Children}{$schemaChild->Name}; + } + + } + + return @errors; +} + +sub Dispose { + my ($this) = @_; + + foreach my $child (values %{ $this->{$Children} || {} }) { + if (ref $child eq 'ARRAY') { + foreach my $inst (@$child) { + $inst->Dispose; + } + } else { + die new IMPL::Exception("Child is null",%{ $this->{$Children} }) if not $child; + $child->Dispose; + } + } + + delete @$this{$Schema,$Children}; + + $this->SUPER::Dispose; +} +1;