Mercurial > pub > Impl
diff Lib/Schema/Form.pm @ 0:03e58a454b20
Создан репозитарий
author | Sergey |
---|---|
date | Tue, 14 Jul 2009 12:54:37 +0400 |
parents | |
children | 16ada169ca75 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Lib/Schema/Form.pm Tue Jul 14 12:54:37 2009 +0400 @@ -0,0 +1,252 @@ +package Configuration; +our $DataDir; +package Schema::Form; +use strict; +use Storable; +use Common; +use URI::file; +use BNFCompiler; +use Schema::Form::Container; +use Schema::Form::Field; +use Schema::Form::Filter; +use Schema::Form::Format; +our @ISA = qw(Object); + +BEGIN { + DeclareProperty Name => ACCESS_READ; + DeclareProperty Body => ACCESS_READ; +} + +sub CTOR { + my ($this,%args) = @_; + + $this->{$Name} = $args{Name}; + +} + +sub SetBody { + my ($this, $containerBody) = @_; + $this->{$Body} = $containerBody; +} + +sub list { + return( map { UNIVERSAL::isa($_,'ARRAY') ? @{$_} : defined $_ ? $_ : () } @_ ); +} + +sub LoadForms { + my ($class,$File,$CacheDir,$Encoding) = @_; + + $Encoding or die new Exception('An encoding must be specified for forms'); + + my $Compiler = new BNFCompiler(SchemaCache => "${DataDir}Cache/",Transform => sub { BNFCompiler::DOM::TransformDOMToHash(@_,{skip_spaces => 1})} ); + $Compiler->LoadBNFSchema(file => 'Schema/form.def'); + + my %Context = (Compiler => $Compiler, Encoding => $Encoding); + + $class->ProcessFile(URI::file->new_abs($File),URI::file->new_abs($CacheDir),\%Context); + + $Compiler->Dispose; + + return $Context{Forms}; +} + +sub ProcessFile { + my ($class,$uriFile,$uriCacheDir,$refContext) = @_; + + return 1 if $refContext->{'Processed'}{$uriFile->as_string}; + $refContext->{'Processed'}{$uriFile->as_string} = 1; + + my $Data; + my $file = $uriFile->file; + my $fnameCached = $file; + $fnameCached =~ s/[\\\/:]+/_/g; + $fnameCached .= '.cfm'; + $fnameCached = URI::file->new($fnameCached)->abs($uriCacheDir)->file; + + if ( -e $fnameCached && -f $fnameCached && ( -M $file >= -M $fnameCached ) ) { + $Data = retrieve($fnameCached); + } else { + my $Compiler = $refContext->{'Compiler'}; + local $/ = undef; + open my $hfile,"<:encoding($refContext->{Encoding})",$file or die new Exception('Failed to open file',$file); + $Data = $Compiler->Parse(<$hfile>); + store($Data,$fnameCached); + } + + + my $uriDir = URI::file->new('./')->abs($uriFile); + + my $needRebuild = 0; + + foreach my $inc (list $Data->{_include}) { + $needRebuild ||= $class->ProcessFile(URI::file->new($inc->{file_name})->abs($uriDir),$uriCacheDir,$refContext); + } + + foreach my $use (list $Data->{_use}) { + $refContext->{Filters}{$use->{alias}} = { Class => join '', list $use->{mod_name} }; + $refContext->{Require}{$use->{mod_name}} = 1; + } + + foreach my $container (list $Data->{container}) { + if ($container->{type} eq 'Form') { + $class->ConstructForm($container,$refContext); + } elsif ($container->{type} eq 'Format') { + $class->ConstructFormat($container,$refContext); + } elsif ($container->{type} eq 'Filter') { + $class->ConstructFilter($container,$refContext); + } + } +} + +sub ProcessContainer { + my ($class,$container,$refContext) = @_; +} + +sub ConstructForm { + my ($class,$container,$refContext) = @_; + + $container->{type} eq 'Form' or die new Exception("Unexpected container type"); + + not $refContext->{Forms}{$container->{name}} or die new Exception('The form is already exists',$container->{name}); + + my $Form = new Schema::Form(Name => $container->{name}); + + $Form->SetBody($class->ConstructGroup($container,$refContext)); + + $refContext->{Forms}{$Form->Name} = $Form; +} + +sub ConstructGroup { + my($class,$container,$refContext) = @_; + + my $Group = new Schema::Form::Container( + Name => $container->{name}, + isMulti => ($container->{multi} ? 1 : 0) + ); + + foreach my $child (list $container->{body}{container}) { + my $obj; + if ($child->{type} eq 'Group') { + $obj = $class->ConstructGroup($child,$refContext); + } else { + $obj = $class->ConstructField($child,$refContext); + } + $Group->AddChild($obj); + } + + foreach my $filter (list $container->{expression}) { + $Group->AddFilter($class->FilterInstance($filter,$refContext,$container->{name})); + } + + foreach my $attr (list $container->{body}{body_property}) { + $Group->Attributes->{$attr->{complex_name}} = $class->ScalarExpression($attr->{expression},$container->{name}); + } + + return $Group; +} + +sub ConstructField { + my ($class,$container,$refContext) = @_; + + my $Format = $refContext->{Formats}{$container->{type}} or die new Exception('An undefined format name', $container->{type}); + + my $Field = Schema::Form::Field->new( + Name => $container->{name}, + isMulti => ($container->{multi} ? 1 : 0), + Format => $Format + ); + + foreach my $filter (list $container->{expression}) { + $Field->AddFilter($class->FilterInstance($filter,$refContext,$container->{name})); + } + + foreach my $attr (list $container->{body}{body_property}) { + $Field->Attributes->{ref $attr->{complex_name} ? join '', @{$attr->{complex_name}} : $attr->{complex_name}} = $class->ScalarExpression($attr->{expression},$container->{name}); + } + + return $Field; +} + +sub FilterInstance { + my ($class,$expr,$refContext,$where) = @_; + + my $filter = $expr->{instance} or die new Exception('Invalid filter syntax',$where); + + my $filterClass = $refContext->{Filters}{$filter->{name}}{Class} or die new Exception('Using undefined filter name',$filter->{name},$where); + + my @Args = map { $class->ScalarExpression($_,$where) } list $filter->{expression}; + + my $Filter = Schema::Form::Filter->new( + Name => $filter->{name}, + Class => $filterClass, + Args => \@Args + ); + + if ($refContext->{Filters}{$filter->{name}}{Attributes}) { + while (my ($name,$value) = each %{$refContext->{Filters}{$filter->{name}}{Attributes}}) { + $Filter->Attributes->{$name} = $value; + } + } + + return $Filter; +} + +sub ScalarExpression { + my ($class,$expr,$where) = @_; + + my $val; + if ($expr->{instance}) { + $val = $expr->{instance}{name}; + } elsif ($expr->{string}) { + $val = join '', list $expr->{string}; + $val =~ s/\\(.)/ + if ($1 eq '"' or $1 eq '\\') { + $1; + } else { + "\\$1"; + } + /ge; + } elsif ($expr->{number}) { + $val = join '', list $expr->{number}; + } else { + die new Exception('Scalar expression required'); + } + + return $val; +} + +sub ConstructFormat { + my ($class,$container,$refContext) = @_; + + my $Format = Schema::Form::Format->new ( + Name => $container->{name} + ); + + foreach my $filter (list $container->{expression}) { + $Format->AddFilter($class->FilterInstance($filter,$refContext,$container->{name})); + } + + foreach my $attr (list $container->{body}{body_property}) { + $Format->Attributes->{ref $attr->{complex_name} ? join '', @{$attr->{complex_name}} : $attr->{complex_name}} = $class->ScalarExpression($attr->{expression},$container->{name}); + } + + $refContext->{Formats}{$Format->Name} = $Format; +} + +sub ConstructFilter { + my ($class,$container,$refContext) = @_; + + foreach my $attr (list $container->{body}{body_property}) { + $refContext->{Filters}{$container->{name}}{Attributes}{ref $attr->{complex_name} ? join '', @{$attr->{complex_name}} : $attr->{complex_name}} = $class->ScalarExpression($attr->{expression},$container->{name}); + } +} + +=pod +Form schema - îïèñàíèå ôîðìû ââîäà è ïðàâèëà êîíòðîëÿ + +Form instance - çíà÷åíèÿ ýëåìåíòîâ ôîðìû + +=cut + + +1;