Mercurial > pub > Impl
diff Lib/Form/Container.pm @ 0:03e58a454b20
Создан репозитарий
author | Sergey |
---|---|
date | Tue, 14 Jul 2009 12:54:37 +0400 (2009-07-14) |
parents | |
children | 16ada169ca75 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Lib/Form/Container.pm Tue Jul 14 12:54:37 2009 +0400 @@ -0,0 +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