Mercurial > pub > Impl
annotate Lib/IMPL/DOM/Navigator/Builder.pm @ 245:7c517134c42f
Added Unsupported media type Web exception
corrected resourceLocation setting in the resource
Implemented localizable resources for text messages
fixed TT view scopings, INIT block in controls now sets globals correctly.
author | sergey |
---|---|
date | Mon, 29 Oct 2012 03:15:22 +0400 |
parents | b8c724f6de36 |
children | 2746a8e5a6c4 |
rev | line source |
---|---|
49 | 1 package IMPL::DOM::Navigator::Builder; |
2 use strict; | |
3 use warnings; | |
4 | |
236 | 5 use IMPL::Const qw(:prop); |
6 | |
165 | 7 use parent qw(IMPL::DOM::Navigator); |
49 | 8 use IMPL::Class::Property; |
9 use IMPL::Class::Property::Direct; | |
10 require IMPL::DOM::Navigator::SchemaNavigator; | |
104
196bf443b5e1
DOM::Schema RC0 inflators support, validation and some other things,
wizard
parents:
103
diff
changeset
|
11 require IMPL::DOM::Schema::ValidationError; |
106 | 12 use IMPL::DOM::Document; |
49 | 13 |
14 BEGIN { | |
236 | 15 private _direct property _schemaNavi => PROP_RW; |
16 private _direct property _docClass => PROP_RW; | |
17 public _direct property BuildErrors => PROP_RO | PROP_LIST; | |
18 public _direct property Document => PROP_RO; | |
19 public _direct property ignoreUndefined => PROP_RO; | |
49 | 20 } |
21 | |
106 | 22 our %CTOR = ( |
112 | 23 'IMPL::DOM::Navigator' => sub { IMPL::DOM::Document->Empty; } |
106 | 24 ); |
25 | |
49 | 26 sub CTOR { |
236 | 27 my ($this,$docClass,$schema,%opts) = @_; |
49 | 28 |
29 $this->{$_docClass} = $docClass; | |
30 $this->{$_schemaNavi} = $schema ? IMPL::DOM::Navigator::SchemaNavigator->new($schema) : undef; | |
236 | 31 |
32 $this->{$ignoreUndefined} = $opts{ignoreUndefined} if $opts{ignoreUndefined}; | |
49 | 33 } |
34 | |
35 sub NavigateCreate { | |
36 my ($this,$nodeName,%props) = @_; | |
37 | |
38 if (my $schemaNode = $this->{$_schemaNavi}->NavigateName($nodeName)) { | |
104
196bf443b5e1
DOM::Schema RC0 inflators support, validation and some other things,
wizard
parents:
103
diff
changeset
|
39 my $class = $schemaNode->can('nativeType') ? $schemaNode->nativeType || 'IMPL::DOM::Node' : 'IMPL::DOM::Node'; |
196bf443b5e1
DOM::Schema RC0 inflators support, validation and some other things,
wizard
parents:
103
diff
changeset
|
40 |
148
e6447ad85cb4
DOM objects now have a schema and schemaSource properties
wizard
parents:
113
diff
changeset
|
41 my $schemaSource = $this->{$_schemaNavi}->SourceSchemaNode; |
e6447ad85cb4
DOM objects now have a schema and schemaSource properties
wizard
parents:
113
diff
changeset
|
42 |
104
196bf443b5e1
DOM::Schema RC0 inflators support, validation and some other things,
wizard
parents:
103
diff
changeset
|
43 my @errors = $this->inflateProperties($schemaNode,\%props); |
148
e6447ad85cb4
DOM objects now have a schema and schemaSource properties
wizard
parents:
113
diff
changeset
|
44 $props{schema} = $schemaNode; |
e6447ad85cb4
DOM objects now have a schema and schemaSource properties
wizard
parents:
113
diff
changeset
|
45 $props{schemaSource} = $schemaSource; |
49 | 46 |
47 my $node; | |
48 if (! $this->{$Document}) { | |
49 $node = $this->{$Document} = $this->{$_docClass}->new(nodeName => $nodeName,%props); | |
106 | 50 $this->_initNavigator($node); |
49 | 51 } else { |
206 | 52 die new IMPL::InvalidOperationException('Can create a second top level element') unless $this->Current; |
49 | 53 $node = $this->{$Document}->Create($nodeName,$class,\%props); |
106 | 54 $this->Current->appendChild($node); |
55 $this->internalNavigateNodeSet($node); | |
49 | 56 } |
57 | |
104
196bf443b5e1
DOM::Schema RC0 inflators support, validation and some other things,
wizard
parents:
103
diff
changeset
|
58 if (@errors) { |
194 | 59 $this->BuildErrors->Append( |
60 map { | |
61 IMPL::DOM::Schema::ValidationError->new( | |
236 | 62 node => $node, |
63 source => $schemaSource, | |
64 schema => $schemaNode, | |
65 message => $schemaNode->messageInflateError, | |
66 error => $_ | |
194 | 67 ) |
68 } @errors | |
69 ); | |
104
196bf443b5e1
DOM::Schema RC0 inflators support, validation and some other things,
wizard
parents:
103
diff
changeset
|
70 } |
196bf443b5e1
DOM::Schema RC0 inflators support, validation and some other things,
wizard
parents:
103
diff
changeset
|
71 |
49 | 72 return $node; |
73 } else { | |
236 | 74 die new IMPL::InvalidOperationException("The specified node is undefined", $nodeName) |
238 | 75 if !$this->ignoreUndefined; |
236 | 76 return; |
49 | 77 } |
78 } | |
79 | |
103 | 80 sub inflateProperties { |
194 | 81 my ($this,$schemaNode,$refProps) = @_; |
82 my @errors; | |
83 foreach my $schemaProp ( $schemaNode->selectNodes('Property') ) { | |
84 next if not exists $refProps->{$schemaProp->name}; | |
85 my $result = eval {$schemaProp->inflateValue($refProps->{$schemaProp->name}) }; | |
86 if (my $e = $@) { | |
87 push @errors, $e; | |
88 } else { | |
89 $refProps->{$schemaProp->name} = $result; | |
90 } | |
91 } | |
92 return @errors; | |
103 | 93 } |
94 | |
95 sub inflateValue { | |
194 | 96 my ($this,$value,$node) = @_; |
97 | |
98 $node ||= $this->Current; | |
99 | |
100 my $nodeSchema = $this->{$_schemaNavi}->Current; | |
101 | |
102 my $result = eval { $nodeSchema->inflateValue($value) }; | |
103 if (my $e=$@) { | |
104 $this->BuildErrors->Append(new IMPL::DOM::Schema::ValidationError( | |
105 Schema => $nodeSchema, | |
106 Node => $node, | |
107 Error => $e, | |
108 Message => $nodeSchema->messageInflateError, | |
109 Source => $this->{$_schemaNavi}->SourceSchemaNode | |
110 )); | |
111 return $value; | |
112 } else { | |
113 return $result; | |
114 } | |
103 | 115 } |
116 | |
49 | 117 sub Back { |
118 my ($this) = @_; | |
119 | |
120 $this->{$_schemaNavi}->SchemaBack(); | |
106 | 121 $this->SUPER::Back(); |
49 | 122 } |
123 | |
112 | 124 sub saveState { |
194 | 125 my ($this) = @_; |
126 | |
127 $this->{$_schemaNavi}->saveState; | |
128 $this->SUPER::saveState; | |
112 | 129 } |
130 | |
131 sub restoreState { | |
194 | 132 my ($this) = @_; |
133 | |
134 $this->{$_schemaNavi}->restoreState; | |
135 $this->SUPER::restoreState; | |
112 | 136 } |
137 | |
236 | 138 #compatibility |
139 sub buildErrors { | |
140 goto &BuildErrors; | |
141 } | |
142 | |
49 | 143 1; |
144 | |
145 __END__ | |
64 | 146 |
49 | 147 =pod |
148 | |
64 | 149 =head1 NAME |
150 | |
180 | 151 C< IMPL::DOM::Navigator::Builder > - Навигатор, строящий документ по указанной схеме. |
64 | 152 |
49 | 153 =head1 SYNOPSIS |
154 | |
64 | 155 =begin code |
156 | |
49 | 157 my $builder = new IMPL::DOM::Navigator::Builder(new MyApp::Document,$schema); |
158 my $reader = new IMPL::DOM::XMLReader(Navigator => $builder); | |
159 | |
160 $reader->ParseFile("document.xml"); | |
161 | |
162 my @errors = $schema->Validate($builder->Document); | |
163 | |
64 | 164 =end code |
165 | |
49 | 166 =head1 DESCRIPTION |
167 | |
180 | 168 Построитель DOM документов по указанной схеме. Обычно используется в связке |
169 с объектами для чтения такими как C<IMPL::DOM::XMLReader>. | |
49 | 170 |
171 =head1 METHODS | |
172 | |
173 =over | |
174 | |
64 | 175 =item C< CTOR($classDocument,$schema) > |
49 | 176 |
180 | 177 Создает новый объект, принимает на вход класс документа (или фабрику, например |
178 L<IMPL::Object::Factory>) и схему. В процессе процедуры построения документа | |
179 будет создан объект документа. | |
49 | 180 |
64 | 181 =item C< NavigateCreate($nodeName,\%props) > |
49 | 182 |
180 | 183 Создает новый узел с указанным именем и переходит в него. В случае если в схеме |
184 подходящий узел не найден, то вызывается исключение. | |
49 | 185 |
180 | 186 При этом по имени узла ищется его схема, после чего определяется класс для |
187 создания экземпляра и созданный узел доавляется в документ. При создании | |
188 нового узла используется метод документа C<< IMPL::DOM::Document->Create >> | |
49 | 189 |
180 | 190 Свойства узла передаются при создании через параметр C<%props>, но имя создаваемого |
191 узла НЕ может быть переопределено свойством C<nodeName>, оно будет проигнорировано. | |
64 | 192 |
193 =item C< Document > | |
194 | |
180 | 195 Свойство, которое содержит документ по окончании процедуры построения. |
49 | 196 |
197 =back | |
198 | |
199 =cut |