comparison lib/IMPL/DOM/Navigator/Builder.pm @ 407:c6e90e02dd17 ref20150831

renamed Lib->lib
author cin
date Fri, 04 Sep 2015 19:40:23 +0300
parents
children
comparison
equal deleted inserted replaced
406:f23fcb19d3c1 407:c6e90e02dd17
1 package IMPL::DOM::Navigator::Builder;
2 use strict;
3 use warnings;
4
5 use IMPL::Const qw(:prop);
6
7 use parent qw(IMPL::DOM::Navigator);
8 use IMPL::Class::Property;
9 require IMPL::DOM::Navigator::SchemaNavigator;
10 require IMPL::DOM::Schema::ValidationError;
11 use IMPL::DOM::Document;
12
13 BEGIN {
14 private _direct property _schemaNavi => PROP_RW;
15 private _direct property _docClass => PROP_RW;
16 public _direct property Document => PROP_RO;
17 public _direct property ignoreUndefined => PROP_RO;
18 }
19
20 our %CTOR = (
21 'IMPL::DOM::Navigator' => sub { IMPL::DOM::Document->Empty; }
22 );
23
24 sub CTOR {
25 my ($this,$docClass,$schema,%opts) = @_;
26
27 $this->{$_docClass} = $docClass;
28 $this->{$_schemaNavi} = $schema ? IMPL::DOM::Navigator::SchemaNavigator->new($schema) : undef;
29
30 $this->{$ignoreUndefined} = $opts{ignoreUndefined} if $opts{ignoreUndefined};
31 }
32
33 sub NavigateCreate {
34 my ($this,$nodeName,%props) = @_;
35
36 if (my $schemaType = $this->{$_schemaNavi}->NavigateName($nodeName)) {
37 my $class = $schemaType->can('nativeType') ? $schemaType->nativeType || 'IMPL::DOM::Node' : 'IMPL::DOM::Node';
38
39 my $schemaNode = $this->{$_schemaNavi}->SourceSchemaNode;
40
41 $props{schemaType} = $schemaType;
42 $props{schemaNode} = $schemaNode;
43
44 my $node;
45 if (! $this->{$Document}) {
46 # keep reference to the schema document
47 $props{schemaDocument} = $this->{$_schemaNavi}->schema;
48 $node = $this->{$Document} = $this->{$_docClass}->new(nodeName => $nodeName,%props);
49 $this->_initNavigator($node);
50 } else {
51 die new IMPL::InvalidOperationException('Can\'t create a second top level element') unless $this->Current;
52 $node = $this->{$Document}->Create($nodeName,$class,\%props);
53 $this->Current->appendChild($node);
54 $this->internalNavigateNodeSet($node);
55 }
56
57 return $node;
58 } else {
59 die new IMPL::InvalidOperationException("The specified node is undefined", $nodeName)
60 if !$this->ignoreUndefined;
61 return;
62 }
63 }
64
65 sub Back {
66 my ($this) = @_;
67
68 $this->{$_schemaNavi}->SchemaBack();
69 $this->SUPER::Back();
70 }
71
72 sub saveState {
73 my ($this) = @_;
74
75 $this->{$_schemaNavi}->saveState;
76 $this->SUPER::saveState;
77 }
78
79 sub restoreState {
80 my ($this) = @_;
81
82 $this->{$_schemaNavi}->restoreState;
83 $this->SUPER::restoreState;
84 }
85
86 sub document {
87 goto &Document;
88 }
89
90 1;
91
92 __END__
93
94 =pod
95
96 =head1 NAME
97
98 C< IMPL::DOM::Navigator::Builder > - Навигатор, строящий документ по указанной схеме.
99
100 =head1 SYNOPSIS
101
102 =begin code
103
104 my $builder = new IMPL::DOM::Navigator::Builder(new MyApp::Document,$schema);
105 my $reader = new IMPL::DOM::XMLReader(Navigator => $builder);
106
107 $reader->ParseFile("document.xml");
108
109 my @errors = $schema->Validate($builder->Document);
110
111 =end code
112
113 =head1 DESCRIPTION
114
115 Построитель DOM документов по указанной схеме. Обычно используется в связке
116 с объектами для чтения такими как C<IMPL::DOM::XMLReader>.
117
118 =head1 MEMBERS
119
120 =head2 C< CTOR($classDocument,$schema, %opts) >
121
122 Создает новый объект, принимает на вход класс документа (или фабрику, например
123 L<IMPL::Object::Factory>) и схему. В процессе процедуры построения документа
124 будет создан объект документа.
125
126 Необязательные именованные параметры
127
128 =over
129
130 =item C<ignoreUndefined>
131
132 C<NavigateCreate> не будет вызывать исключение, если запрашиваемый узел не
133 найден в схеме, но будет возвращать C<undef>.
134
135 =back
136
137 =head2 C< NavigateCreate($nodeName,%props) >
138
139 Создает новый узел с указанным именем и переходит в него. В случае если в схеме
140 подходящий узел не найден, то вызывается исключение или будет возвращено
141 C<undef> см. C<ignoreUndefined>.
142
143 При этом по имени узла ищется его схема, после чего определяется класс для
144 создания экземпляра узла и созданный узел доавляется в документ. При создании
145 нового узла используется метод документа C<< IMPL::DOM::Document->Create >>
146
147 Свойства узла передаются при создании через параметр C<%props>, но имя
148 создаваемого узла НЕ может быть переопределено свойством C<nodeName>, оно будет
149 проигнорировано.
150
151 Свойства узла будут преобразованы при помощи заданных в схеме заполнителей
152 C<inflator>.
153
154 =head2 C<[get]document >
155
156 Свойство, которое содержит документ по окончании процедуры построения.
157
158 =head2 C<[get]buildErrors>
159
160 Ошибки, возникшие в процессе построения документа.
161
162 =head2 C<[get]ignoreUndefined>
163
164 Опция, заданная при создании построителя, отвечающая за обработку узлов
165 не найденных в схеме.
166
167 =cut