Mercurial > pub > Impl
comparison Lib/Schema/Form.pm @ 0:03e58a454b20
Создан репозитарий
author | Sergey |
---|---|
date | Tue, 14 Jul 2009 12:54:37 +0400 |
parents | |
children | 16ada169ca75 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:03e58a454b20 |
---|---|
1 package Configuration; | |
2 our $DataDir; | |
3 package Schema::Form; | |
4 use strict; | |
5 use Storable; | |
6 use Common; | |
7 use URI::file; | |
8 use BNFCompiler; | |
9 use Schema::Form::Container; | |
10 use Schema::Form::Field; | |
11 use Schema::Form::Filter; | |
12 use Schema::Form::Format; | |
13 our @ISA = qw(Object); | |
14 | |
15 BEGIN { | |
16 DeclareProperty Name => ACCESS_READ; | |
17 DeclareProperty Body => ACCESS_READ; | |
18 } | |
19 | |
20 sub CTOR { | |
21 my ($this,%args) = @_; | |
22 | |
23 $this->{$Name} = $args{Name}; | |
24 | |
25 } | |
26 | |
27 sub SetBody { | |
28 my ($this, $containerBody) = @_; | |
29 $this->{$Body} = $containerBody; | |
30 } | |
31 | |
32 sub list { | |
33 return( map { UNIVERSAL::isa($_,'ARRAY') ? @{$_} : defined $_ ? $_ : () } @_ ); | |
34 } | |
35 | |
36 sub LoadForms { | |
37 my ($class,$File,$CacheDir,$Encoding) = @_; | |
38 | |
39 $Encoding or die new Exception('An encoding must be specified for forms'); | |
40 | |
41 my $Compiler = new BNFCompiler(SchemaCache => "${DataDir}Cache/",Transform => sub { BNFCompiler::DOM::TransformDOMToHash(@_,{skip_spaces => 1})} ); | |
42 $Compiler->LoadBNFSchema(file => 'Schema/form.def'); | |
43 | |
44 my %Context = (Compiler => $Compiler, Encoding => $Encoding); | |
45 | |
46 $class->ProcessFile(URI::file->new_abs($File),URI::file->new_abs($CacheDir),\%Context); | |
47 | |
48 $Compiler->Dispose; | |
49 | |
50 return $Context{Forms}; | |
51 } | |
52 | |
53 sub ProcessFile { | |
54 my ($class,$uriFile,$uriCacheDir,$refContext) = @_; | |
55 | |
56 return 1 if $refContext->{'Processed'}{$uriFile->as_string}; | |
57 $refContext->{'Processed'}{$uriFile->as_string} = 1; | |
58 | |
59 my $Data; | |
60 my $file = $uriFile->file; | |
61 my $fnameCached = $file; | |
62 $fnameCached =~ s/[\\\/:]+/_/g; | |
63 $fnameCached .= '.cfm'; | |
64 $fnameCached = URI::file->new($fnameCached)->abs($uriCacheDir)->file; | |
65 | |
66 if ( -e $fnameCached && -f $fnameCached && ( -M $file >= -M $fnameCached ) ) { | |
67 $Data = retrieve($fnameCached); | |
68 } else { | |
69 my $Compiler = $refContext->{'Compiler'}; | |
70 local $/ = undef; | |
71 open my $hfile,"<:encoding($refContext->{Encoding})",$file or die new Exception('Failed to open file',$file); | |
72 $Data = $Compiler->Parse(<$hfile>); | |
73 store($Data,$fnameCached); | |
74 } | |
75 | |
76 | |
77 my $uriDir = URI::file->new('./')->abs($uriFile); | |
78 | |
79 my $needRebuild = 0; | |
80 | |
81 foreach my $inc (list $Data->{_include}) { | |
82 $needRebuild ||= $class->ProcessFile(URI::file->new($inc->{file_name})->abs($uriDir),$uriCacheDir,$refContext); | |
83 } | |
84 | |
85 foreach my $use (list $Data->{_use}) { | |
86 $refContext->{Filters}{$use->{alias}} = { Class => join '', list $use->{mod_name} }; | |
87 $refContext->{Require}{$use->{mod_name}} = 1; | |
88 } | |
89 | |
90 foreach my $container (list $Data->{container}) { | |
91 if ($container->{type} eq 'Form') { | |
92 $class->ConstructForm($container,$refContext); | |
93 } elsif ($container->{type} eq 'Format') { | |
94 $class->ConstructFormat($container,$refContext); | |
95 } elsif ($container->{type} eq 'Filter') { | |
96 $class->ConstructFilter($container,$refContext); | |
97 } | |
98 } | |
99 } | |
100 | |
101 sub ProcessContainer { | |
102 my ($class,$container,$refContext) = @_; | |
103 } | |
104 | |
105 sub ConstructForm { | |
106 my ($class,$container,$refContext) = @_; | |
107 | |
108 $container->{type} eq 'Form' or die new Exception("Unexpected container type"); | |
109 | |
110 not $refContext->{Forms}{$container->{name}} or die new Exception('The form is already exists',$container->{name}); | |
111 | |
112 my $Form = new Schema::Form(Name => $container->{name}); | |
113 | |
114 $Form->SetBody($class->ConstructGroup($container,$refContext)); | |
115 | |
116 $refContext->{Forms}{$Form->Name} = $Form; | |
117 } | |
118 | |
119 sub ConstructGroup { | |
120 my($class,$container,$refContext) = @_; | |
121 | |
122 my $Group = new Schema::Form::Container( | |
123 Name => $container->{name}, | |
124 isMulti => ($container->{multi} ? 1 : 0) | |
125 ); | |
126 | |
127 foreach my $child (list $container->{body}{container}) { | |
128 my $obj; | |
129 if ($child->{type} eq 'Group') { | |
130 $obj = $class->ConstructGroup($child,$refContext); | |
131 } else { | |
132 $obj = $class->ConstructField($child,$refContext); | |
133 } | |
134 $Group->AddChild($obj); | |
135 } | |
136 | |
137 foreach my $filter (list $container->{expression}) { | |
138 $Group->AddFilter($class->FilterInstance($filter,$refContext,$container->{name})); | |
139 } | |
140 | |
141 foreach my $attr (list $container->{body}{body_property}) { | |
142 $Group->Attributes->{$attr->{complex_name}} = $class->ScalarExpression($attr->{expression},$container->{name}); | |
143 } | |
144 | |
145 return $Group; | |
146 } | |
147 | |
148 sub ConstructField { | |
149 my ($class,$container,$refContext) = @_; | |
150 | |
151 my $Format = $refContext->{Formats}{$container->{type}} or die new Exception('An undefined format name', $container->{type}); | |
152 | |
153 my $Field = Schema::Form::Field->new( | |
154 Name => $container->{name}, | |
155 isMulti => ($container->{multi} ? 1 : 0), | |
156 Format => $Format | |
157 ); | |
158 | |
159 foreach my $filter (list $container->{expression}) { | |
160 $Field->AddFilter($class->FilterInstance($filter,$refContext,$container->{name})); | |
161 } | |
162 | |
163 foreach my $attr (list $container->{body}{body_property}) { | |
164 $Field->Attributes->{ref $attr->{complex_name} ? join '', @{$attr->{complex_name}} : $attr->{complex_name}} = $class->ScalarExpression($attr->{expression},$container->{name}); | |
165 } | |
166 | |
167 return $Field; | |
168 } | |
169 | |
170 sub FilterInstance { | |
171 my ($class,$expr,$refContext,$where) = @_; | |
172 | |
173 my $filter = $expr->{instance} or die new Exception('Invalid filter syntax',$where); | |
174 | |
175 my $filterClass = $refContext->{Filters}{$filter->{name}}{Class} or die new Exception('Using undefined filter name',$filter->{name},$where); | |
176 | |
177 my @Args = map { $class->ScalarExpression($_,$where) } list $filter->{expression}; | |
178 | |
179 my $Filter = Schema::Form::Filter->new( | |
180 Name => $filter->{name}, | |
181 Class => $filterClass, | |
182 Args => \@Args | |
183 ); | |
184 | |
185 if ($refContext->{Filters}{$filter->{name}}{Attributes}) { | |
186 while (my ($name,$value) = each %{$refContext->{Filters}{$filter->{name}}{Attributes}}) { | |
187 $Filter->Attributes->{$name} = $value; | |
188 } | |
189 } | |
190 | |
191 return $Filter; | |
192 } | |
193 | |
194 sub ScalarExpression { | |
195 my ($class,$expr,$where) = @_; | |
196 | |
197 my $val; | |
198 if ($expr->{instance}) { | |
199 $val = $expr->{instance}{name}; | |
200 } elsif ($expr->{string}) { | |
201 $val = join '', list $expr->{string}; | |
202 $val =~ s/\\(.)/ | |
203 if ($1 eq '"' or $1 eq '\\') { | |
204 $1; | |
205 } else { | |
206 "\\$1"; | |
207 } | |
208 /ge; | |
209 } elsif ($expr->{number}) { | |
210 $val = join '', list $expr->{number}; | |
211 } else { | |
212 die new Exception('Scalar expression required'); | |
213 } | |
214 | |
215 return $val; | |
216 } | |
217 | |
218 sub ConstructFormat { | |
219 my ($class,$container,$refContext) = @_; | |
220 | |
221 my $Format = Schema::Form::Format->new ( | |
222 Name => $container->{name} | |
223 ); | |
224 | |
225 foreach my $filter (list $container->{expression}) { | |
226 $Format->AddFilter($class->FilterInstance($filter,$refContext,$container->{name})); | |
227 } | |
228 | |
229 foreach my $attr (list $container->{body}{body_property}) { | |
230 $Format->Attributes->{ref $attr->{complex_name} ? join '', @{$attr->{complex_name}} : $attr->{complex_name}} = $class->ScalarExpression($attr->{expression},$container->{name}); | |
231 } | |
232 | |
233 $refContext->{Formats}{$Format->Name} = $Format; | |
234 } | |
235 | |
236 sub ConstructFilter { | |
237 my ($class,$container,$refContext) = @_; | |
238 | |
239 foreach my $attr (list $container->{body}{body_property}) { | |
240 $refContext->{Filters}{$container->{name}}{Attributes}{ref $attr->{complex_name} ? join '', @{$attr->{complex_name}} : $attr->{complex_name}} = $class->ScalarExpression($attr->{expression},$container->{name}); | |
241 } | |
242 } | |
243 | |
244 =pod | |
245 Form schema - îïèñàíèå ôîðìû ââîäà è ïðàâèëà êîíòðîëÿ | |
246 | |
247 Form instance - çíà÷åíèÿ ýëåìåíòîâ ôîðìû | |
248 | |
249 =cut | |
250 | |
251 | |
252 1; |