49
|
1 package IMPL::DOM::Schema;
|
|
2 use strict;
|
|
3 use warnings;
|
|
4
|
|
5 require IMPL::DOM::Schema::ComplexNode;
|
|
6 require IMPL::DOM::Schema::ComplexType;
|
|
7 require IMPL::DOM::Schema::SimpleNode;
|
|
8 require IMPL::DOM::Schema::SimpleType;
|
|
9 require IMPL::DOM::Schema::Node;
|
|
10 require IMPL::DOM::Schema::AnyNode;
|
|
11 require IMPL::DOM::Schema::NodeList;
|
|
12 require IMPL::DOM::Schema::NodeSet;
|
|
13 require IMPL::DOM::Schema::Property;
|
|
14 require IMPL::DOM::Schema::SwitchNode;
|
|
15
|
|
16 use base qw(IMPL::DOM::Document);
|
|
17 use IMPL::Class::Property;
|
|
18 use IMPL::Class::Property::Direct;
|
|
19
|
|
20 our %CTOR = (
|
|
21 'IMPL::DOM::Document' => sub { nodeName => 'schema' }
|
|
22 );
|
|
23
|
|
24 BEGIN {
|
|
25 private _direct property _TypesMap => prop_all;
|
|
26 public _direct property BaseSchemas => prop_get | owner_set;
|
|
27 private _direct property _Validators => prop_all;
|
|
28 }
|
|
29
|
|
30 sub resolveType {
|
|
31 $_[0]->{$_TypesMap}->{$_[1]};
|
|
32 }
|
|
33
|
|
34 sub Create {
|
|
35 my ($this,$nodeName,$class,$refArgs) = @_;
|
|
36
|
|
37 die new IMPL::Exception('Invalid node class') unless $class->isa('IMPL::DOM::Schema::Node');
|
|
38
|
|
39 goto &SUPER::Create;
|
|
40 }
|
|
41
|
|
42 sub Process {
|
|
43 my ($this) = @_;
|
|
44
|
|
45 $this->{$_TypesMap} = { map { $_->type, $_ } $this->selectNodes(sub { $_[0]->nodeName eq 'ComplexType' || $_[0]->nodeName eq 'SimpleType' } ) };
|
|
46 }
|
|
47
|
|
48 sub Validate {
|
|
49 my ($this,$node) = @_;
|
|
50
|
|
51 if ( my ($schemaNode) = $this->selectNodes(sub { $_[0]->name eq $node->nodeName })) {
|
|
52 $schemaNode->Validate($node);
|
|
53 } else {
|
|
54 return new IMPL::DOM::Schema::ValidationError(Message=> "A specified document doesn't match the schema");
|
|
55 }
|
|
56 }
|
|
57
|
|
58 my $schema;
|
|
59
|
|
60 sub MetaSchema {
|
|
61
|
|
62 return $schema if $schema;
|
|
63
|
|
64 $schema = new IMPL::DOM::Schema;
|
|
65
|
|
66 $schema->appendRange(
|
|
67 IMPL::DOM::Schema::ComplexNode->new(name => 'schema')->appendRange(
|
|
68 IMPL::DOM::Schema::NodeSet->new()->appendRange(
|
|
69 IMPL::DOM::Schema::Node->new(name => 'ComplexNode', type => 'ComplexNode', minOccur => 0, maxOccur=>'unbounded'),
|
|
70 IMPL::DOM::Schema::Node->new(name => 'ComplexType', type => 'ComplexType', minOccur => 0, maxOccur=>'unbounded'),
|
|
71 IMPL::DOM::Schema::Node->new(name => 'SimpleNode', type => 'SimpleNode', minOccur => 0, maxOccur=>'unbounded'),
|
|
72 IMPL::DOM::Schema::Node->new(name => 'SimpleType', type => 'SimpleType', minOccur => 0, maxOccur=>'unbounded'),
|
|
73 IMPL::DOM::Schema::SimpleNode->new(name => 'Node', minOccur => 0, maxOccur=>'unbounded'),
|
|
74 IMPL::DOM::Schema::SimpleNode->new(name => 'Include', minOccur => 0, maxOccur=>'unbounded')->appendRange(
|
|
75 IMPL::DOM::Schema::Property->new(name => 'source')
|
|
76 )
|
|
77 ),
|
|
78 ),
|
|
79 IMPL::DOM::Schema::ComplexType->new(type => 'NodeSet', nativeType => 'IMPL::DOM::Schema::NodeSet')->appendRange(
|
|
80 IMPL::DOM::Schema::NodeSet->new()->appendRange(
|
|
81 IMPL::DOM::Schema::Node->new(name => 'ComplexNode', type => 'ComplexNode', minOccur => 0, maxOccur=>'unbounded'),
|
|
82 IMPL::DOM::Schema::Node->new(name => 'SimpleNode', type => 'SimpleNode', minOccur => 0, maxOccur=>'unbounded'),
|
|
83 IMPL::DOM::Schema::SimpleNode->new(name => 'Node', minOccur => 0, maxOccur=>'unbounded'),
|
|
84 IMPL::DOM::Schema::SwitchNode->new(minOccur => 0, maxOccur => 1)->appendRange(
|
|
85 IMPL::DOM::Schema::SimpleNode->new(name => 'AnyNode'),
|
|
86 IMPL::DOM::Schema::Node->new(name => 'SwitchNode',type => 'SwitchNode')
|
|
87 )
|
|
88 )
|
|
89 ),
|
|
90 IMPL::DOM::Schema::ComplexType->new(type => 'SwitchNode', nativeType => 'IMPL::DOM::Schema::SwitchNode')->appendRange(
|
|
91 IMPL::DOM::Schema::NodeSet->new()->appendRange(
|
|
92 IMPL::DOM::Schema::Node->new(name => 'ComplexNode', type=>'ComplexNode', minOccur => 0, maxOccur=>'unbounded'),
|
|
93 IMPL::DOM::Schema::Node->new(name => 'SimpleNode', type=>'SimpleNode', minOccur => 0, maxOccur=>'unbounded'),
|
|
94 IMPL::DOM::Schema::SimpleNode->new(name => 'Node', minOccur => 0, maxOccur=>'unbounded'),
|
|
95 )
|
|
96 ),
|
|
97 IMPL::DOM::Schema::ComplexType->new(type => 'NodeList', nativeType => 'IMPL::DOM::Schema::NodeList')->appendRange(
|
|
98 IMPL::DOM::Schema::NodeSet->new()->appendRange(
|
|
99 IMPL::DOM::Schema::Node->new(name => 'ComplexNode', type => 'ComplexNode', minOccur => 0, maxOccur=>'unbounded'),
|
|
100 IMPL::DOM::Schema::Node->new(name => 'SimpleNode', type => 'SimpleNode', minOccur => 0, maxOccur=>'unbounded'),
|
|
101 IMPL::DOM::Schema::Node->new(name => 'SwitchNode',type => 'SwitchNode', minOccur => 0, maxOccur=>'unbounded'),
|
|
102 IMPL::DOM::Schema::SimpleNode->new(name => 'Node', minOccur => 0, maxOccur=>'unbounded'),
|
|
103 IMPL::DOM::Schema::SimpleNode->new(name => 'AnyNode', minOccur => 0, maxOccur=>'unbounded'),
|
|
104 )
|
|
105 ),
|
|
106 IMPL::DOM::Schema::ComplexType->new(type => 'ComplexType', nativeType => 'IMPL::DOM::Schema::ComplexType')->appendRange(
|
|
107 IMPL::DOM::Schema::NodeList->new()->appendRange(
|
|
108 IMPL::DOM::Schema::SwitchNode->new()->appendRange(
|
|
109 IMPL::DOM::Schema::Node->new(name => 'NodeSet', type => 'NodeSet'),
|
|
110 IMPL::DOM::Schema::Node->new(name => 'NodeList',type => 'NodeList'),
|
|
111 ),
|
|
112 IMPL::DOM::Schema::AnyNode->new(maxOccur => 'unbounded', minOccur => 0, type=>'Validator')
|
|
113 ),
|
|
114 new IMPL::DOM::Schema::Property(name => 'type')
|
|
115 ),
|
|
116 IMPL::DOM::Schema::ComplexType->new(type => 'ComplexNode', nativeType => 'IMPL::DOM::Schema::ComplexNode')->appendRange(
|
|
117 IMPL::DOM::Schema::NodeList->new()->appendRange(
|
|
118 IMPL::DOM::Schema::SwitchNode->new()->appendRange(
|
|
119 IMPL::DOM::Schema::Node->new(name => 'NodeSet', type => 'NodeSet'),
|
|
120 IMPL::DOM::Schema::Node->new(name => 'NodeList',type => 'NodeList'),
|
|
121 ),
|
|
122 IMPL::DOM::Schema::AnyNode->new(maxOccur => 'unbounded', minOccur => 0, type=>'Validator')
|
|
123 ),
|
|
124 new IMPL::DOM::Schema::Property(name => 'name')
|
|
125 ),
|
|
126 IMPL::DOM::Schema::ComplexType->new(type => 'SimpleType', nativeType => 'IMPL::DOM::Schema::SimpleType')->appendRange(
|
|
127 IMPL::DOM::Schema::NodeSet->new()->appendRange(
|
|
128 IMPL::DOM::Schema::AnyNode->new(maxOccur => 'unbounded', minOccur => 0, type=>'Validator')
|
|
129 ),
|
|
130 new IMPL::DOM::Schema::Property(name => 'type')
|
|
131 ),
|
|
132 IMPL::DOM::Schema::ComplexType->new(type => 'SimpleNode', nativeType => 'IMPL::DOM::Schema::SimpleNode')->appendRange(
|
|
133 IMPL::DOM::Schema::NodeSet->new()->appendRange(
|
|
134 IMPL::DOM::Schema::AnyNode->new(maxOccur => 'unbounded', minOccur => 0, type=>'Validator')
|
|
135 ),
|
|
136 new IMPL::DOM::Schema::Property(name => 'name')
|
|
137 ),
|
|
138 IMPL::DOM::Schema::ComplexType->new(type => 'Validator', nativeType => 'IMPL::DOM::Schema::Validator')->appendRange(
|
|
139 IMPL::DOM::Schema::NodeList->new()->appendRange(
|
|
140 IMPL::DOM::Schema::AnyNode->new(maxOccur => 'unbounded', minOccur => 0)
|
|
141 ),
|
|
142 new IMPL::DOM::Schema::Property(name => 'name')
|
|
143 )
|
|
144 );
|
|
145
|
|
146 $schema->Process;
|
|
147
|
|
148 return $schema;
|
|
149 }
|
|
150
|
|
151 1;
|
|
152
|
|
153 __END__
|
|
154
|
|
155 =pod
|
|
156
|
|
157 =head1 DESCRIPTION
|
|
158
|
|
159 Схема документа. Наследует C<IMPL::DOM::Document>
|
|
160
|
|
161 =head1 METHODS
|
|
162
|
|
163 =over
|
|
164
|
|
165 =item C<< $obj->Process() >>
|
|
166
|
|
167 Обновляет таблицу типов из содержимого.
|
|
168
|
|
169 =item C<< $obj->ResolveType($typeName) >>
|
|
170
|
|
171 Возвращает схему типа c именем C<$typeName>.
|
|
172
|
|
173 =back
|
|
174
|
|
175 =head1 DESCRIPTION
|
|
176
|
|
177 DOM схема - это документ, состоящий из определенных узлов, описывающая структуру
|
|
178 других документов.
|
|
179
|
|
180 =head1 META SCHEMA
|
|
181
|
|
182 Схема для описания схемы, эта схема используется для постороения других схем
|
|
183
|
|
184 <schema>
|
|
185 <ComplexNode name="schema">
|
|
186 <NodeSet>
|
|
187 <Node minOcuur="0" maxOccur="unbounded" name="ComplexNode" type="ComplexNode"/>
|
|
188 <Node minOcuur="0" maxOccur="unbounded" name="SimpleNode" type="SimpleNode"/>
|
|
189 <Node minOcuur="0" maxOccur="unbounded" name="ComplexType" type="ComplexType"/>
|
|
190 <Node minOcuur="0" maxOccur="unbounded" name="SimpleType" type="SimpleType"/>
|
|
191 <SimpleNode minOcuur="0" maxOccur="unbounded" name="Node"/>
|
|
192 <SimpleNode minOcuur="0" maxOccur="unbounded" name="Include"/>
|
|
193 </NodeSet>
|
|
194 </ComplexNode>
|
|
195
|
|
196 <ComplexType type="NodeContainer">
|
|
197 <NodeSet>
|
|
198 <Node minOcuur="0" maxOccur="unbounded" name="ComplexNode" type="ComplexNode"/>
|
|
199 <Node minOcuur="0" maxOccur="unbounded" name="SimpleNode" type="SimpleNode"/>
|
|
200 <SimpleNode minOcuur="0" maxOccur="unbounded" name="Node"/>
|
|
201 </NodeSet>
|
|
202 </ComplexType>
|
|
203
|
|
204 <ComplexType type="ComplexType">
|
|
205 <NodeList>
|
|
206 <Node name="NodeSet" type="NodeContainer" minOcuur=0/>
|
|
207 <Node name="NodeList" type="NodeContainer" minOccur=0/>
|
|
208 <AnyNode minOccur="0" maxOccur="unbounded" type="Validator"/>
|
|
209 </NodeList>
|
|
210 </ComplexType>
|
|
211
|
|
212 <ComplexType type="ComplexNode">
|
|
213 <NodeList>
|
|
214 <Node name="NodeSet" type="NodeContainer" minOcuur=0/>
|
|
215 <Node name="NodeList" type="NodeContainer" minOccur=0/>
|
|
216 <AnyNode minOccur="0" maxOccur="unbounded" type="Validator"/>
|
|
217 </NodeList>
|
|
218 </ComplexType>
|
|
219
|
|
220 <ComplexType type="SimpleNode">
|
|
221 <NodeSet>
|
|
222 <AnyNode minOccur=0 maxOccur="unbounded" type="Validator"/>
|
|
223 </NodeSet>
|
|
224 </ComplexType>
|
|
225
|
|
226 <ComplexType type="SimpleType">
|
|
227 <NodeSet>
|
|
228 <AnyNode minOccur=0 maxOccur="unbounded" type="Validator"/>
|
|
229 </NodeSet>
|
|
230 </ComplexType>
|
|
231
|
|
232 <ComplexType type="Validator">
|
|
233 <NodeSet>
|
|
234 <AnyNode minOccur=0 maxOccur="unbounded"/>
|
|
235 </NodeSet>
|
|
236 </ComplexType>
|
|
237
|
|
238 </schema>
|
|
239
|
|
240 =cut
|