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