Mercurial > pub > Impl
changeset 389:5aff94ba842f
DOM Schema refactoring complete
author | cin |
---|---|
date | Wed, 12 Feb 2014 13:36:24 +0400 |
parents | 648dfaf642e0 |
children | de1f875e8875 |
files | Lib/IMPL/DOM/Schema.pm Lib/IMPL/DOM/Schema/AnyNode.pm Lib/IMPL/DOM/Schema/ComplexType.pm Lib/IMPL/DOM/Schema/Label.pm Lib/IMPL/DOM/Schema/NodeList.pm Lib/IMPL/DOM/Schema/NodeSet.pm Lib/IMPL/DOM/Schema/Property.pm Lib/IMPL/DOM/Schema/SimpleType.pm Lib/IMPL/DOM/Schema/SwitchNode.pm Lib/IMPL/DOM/Schema/ValidationError.pm Lib/IMPL/DOM/Schema/Validator.pm Lib/IMPL/DOM/Schema/Validator/Compare.pm Lib/IMPL/DOM/Schema/Validator/RegExp.pm Lib/IMPL/DOM/XMLReader.pm Lib/IMPL/Web/View/Metadata/FormMeta.pm _test/Test/Web/View.pm |
diffstat | 16 files changed, 338 insertions(+), 242 deletions(-) [+] |
line wrap: on
line diff
--- a/Lib/IMPL/DOM/Schema.pm Tue Feb 11 20:22:01 2014 +0400 +++ b/Lib/IMPL/DOM/Schema.pm Wed Feb 12 13:36:24 2014 +0400 @@ -19,7 +19,6 @@ Validator => 'IMPL::DOM::Schema::Validator', Builder => 'IMPL::DOM::Navigator::Builder', XMLReader => 'IMPL::DOM::XMLReader', # XMLReader references Schema - InflateFactory => 'IMPL::DOM::Schema::InflateFactory', Loader => 'IMPL::Code::Loader', StringMap => 'IMPL::Resources::StringLocaleMap' }, @@ -61,7 +60,7 @@ return $type if $type; foreach my $base ($this->baseSchemas) { - last if $type = $base->resolveType($typeName); + last if $type = $base->ResolveType($typeName); } die IMPL::KeyNotFoundException->new($typeName) @@ -242,16 +241,14 @@ Node->new(name => 'Property', type=>'Property', maxOccur=>'unbounded', minOccur=>0), AnyNode->new(maxOccur => 'unbounded', minOccur => 0, type=>'Validator') ), - Property->new(name => 'type'), - Property->new(name => 'inflator', optional => 1, inflator => 'IMPL::DOM::Schema::InflateFactory') + Property->new(name => 'type') ), ComplexType->new(type => 'SimpleNode', nativeType => 'IMPL::DOM::Schema::SimpleNode')->appendRange( NodeList->new()->appendRange( Node->new(name => 'Property', type=>'Property', maxOccur=>'unbounded', minOccur=>0), AnyNode->new(maxOccur => 'unbounded', minOccur => 0, type=>'Validator') ), - Property->new(name => 'name'), - Property->new(name => 'inflator', optional => 1, inflator => 'IMPL::DOM::Schema::InflateFactory') + Property->new(name => 'name') ), ComplexType->new(type => 'Validator', nativeType => 'IMPL::DOM::Schema::Validator')->appendRange( NodeList->new()->appendRange( @@ -262,8 +259,7 @@ NodeList->new()->appendRange( AnyNode->new(maxOccur => 'unbounded', minOccur => 0) ), - Property->new(name => 'name'), - Property->new(name => 'inflator', optional => 1, inflator => 'IMPL::DOM::Schema::InflateFactory') + Property->new(name => 'name') ), SimpleType->new(type => 'Node', nativeType => 'IMPL::DOM::Schema::Node')->appendRange( Property->new(name => 'name'),
--- a/Lib/IMPL/DOM/Schema/AnyNode.pm Tue Feb 11 20:22:01 2014 +0400 +++ b/Lib/IMPL/DOM/Schema/AnyNode.pm Wed Feb 12 13:36:24 2014 +0400 @@ -2,17 +2,17 @@ use strict; use warnings; -use parent qw(IMPL::DOM::Schema::Node); - -our %CTOR = ( - 'IMPL::DOM::Schema::Node' => sub { - my %args = @_; - $args{nodeName} ||= 'AnyNode'; - $args{name} = '::any'; - - %args; - } -); +use IMPL::declare { + base => [ + 'IMPL::DOM::Schema::Node' => sub { + my %args = @_; + $args{nodeName} ||= 'AnyNode'; + $args{name} = '::any'; + + %args; + } + ] +}; 1;
--- a/Lib/IMPL/DOM/Schema/ComplexType.pm Tue Feb 11 20:22:01 2014 +0400 +++ b/Lib/IMPL/DOM/Schema/ComplexType.pm Wed Feb 12 13:36:24 2014 +0400 @@ -3,6 +3,10 @@ use warnings; use IMPL::declare { + require => { + Label => 'IMPL::DOM::Schema::Label', + ValidationError => 'IMPL::DOM::Schema::ValidationError' + }, base => [ 'IMPL::DOM::Schema::ComplexNode' => sub { my %args = @_; @@ -24,18 +28,18 @@ my ($this,%args) = @_; $this->{$nativeType} = $args{nativeType}; - $this->{$messageWrongType} = $args{messageWrongType} || "A complex node '%node.path%' is expected to be %schema.nativeType%"; + $this->{$messageWrongType} = $args{messageWrongType} || "A complex node '%node.path%' is expected to be %schemaType.nativeType%"; } sub Validate { my ($this, $node,$ctx) = @_; if ($this->{$nativeType}) { - return new IMPL::DOM::Schema::ValidationError( + return ValidationError->new ( node => $node, schemaNode => $ctx->{schemaNode} || $this, schemaType => $this, - message => $this->messageWrongType + message => $this->_MakeLabel($this->messageWrongType) ) unless $node->isa($this->{$nativeType}); } @@ -46,5 +50,15 @@ $_[0]->nodeName.'[type='.$_[0]->type.']'; } +sub _MakeLabel { + my ($this,$label) = @_; + + if ($label =~ /^ID:(\w+)$/) { + return Label->new($this->document->stringMap, $1); + } else { + return $label; + } +} + 1;
--- a/Lib/IMPL/DOM/Schema/Label.pm Tue Feb 11 20:22:01 2014 +0400 +++ b/Lib/IMPL/DOM/Schema/Label.pm Wed Feb 12 13:36:24 2014 +0400 @@ -50,4 +50,10 @@ return $this->_map->GetString($this->_id); } +sub Format { + my ($this,$args) = @_; + + return $this->_map->GetString($this->_id,$args); +} + 1; \ No newline at end of file
--- a/Lib/IMPL/DOM/Schema/NodeList.pm Tue Feb 11 20:22:01 2014 +0400 +++ b/Lib/IMPL/DOM/Schema/NodeList.pm Wed Feb 12 13:36:24 2014 +0400 @@ -6,7 +6,8 @@ use IMPL::declare { require => { ValidationError => 'IMPL::DOM::Schema::ValidationError', - AnyNode => '-IMPL::DOM::Schema::AnyNode' + AnyNode => '-IMPL::DOM::Schema::AnyNode', + Label => 'IMPL::DOM::Schema::Label' }, base => [ 'IMPL::DOM::Node' => sub { nodeName => 'NodeList' } @@ -21,7 +22,7 @@ my ($this,%args) = @_; $this->messageUnexpected($args{messageUnexpected} || 'A %node.nodeName% isn\'t allowed in %node.parentNode.path%'); - $this->messageNodesRequired($args{messageNodesRequired} || 'A %schema.name% is required in the node %parent.path%'); + $this->messageNodesRequired($args{messageNodesRequired} || 'A %schemaNode.name% is required in the node %parent.path%'); } sub Validate { @@ -38,60 +39,67 @@ while ($info and not $info->{anyNode} and $info->{nodeName} ne $child->nodeName) { # if possible of course :) return ValidationError->new ( - message => $this->messageUnexpected, + message => $this->_MakeLabel( $this->messageUnexpected ), node => $child, parent => $node, schemaNode => $info->{schemaNode} - ) if $info->{Min} > $info->{Seen}; + ) if $info->{min} > $info->{seen}; # we trying to skip a schema node which has a quantifier $info = shift @nodes; } # return error if no more children allowed return ValidationError->new ( - message => $this->messageUnexpected, + message => $this->_MakeLabel( $this->messageUnexpected ), node => $child, parent => $node ) unless $info; # it's ok, we found schema element for child - # but it may be any node or switching node wich would not satisfy current child # validate - while (my @errors = $info->{schemaNode}->Validate($child)) { - if( $info->{anyNode} and $info->{Seen} >= $info->{Min} ) { + while (my @errors = $info->{schemaNode}->Validate( $child ) ) { + if( $info->{anyNode} and $info->{seen} >= $info->{min} ) { # in case of any or switch node, skip it if possible next if $info = shift @nodes; } return @errors; } - $info->{Seen}++; + $info->{seen}++; # check count limits - return new IMPL::DOM::Schema::ValidationError ( - message => $this->messageUnexpected, + return ValidationError->new( + message => $this->_MakeLabel( $this->messageUnexpected ), node => $child, parent => $node, - source => $sourceSchema, - ) if $info->{Max} and $info->{Seen} > $info->{Max}; + schemaNode => $info->{schemaNode}, + ) if $info->{max} and $info->{seen} > $info->{max}; } # no more children left (but may be should :) while ($info) { - return new IMPL::DOM::Schema::ValidationError ( - error => 1, - message => $this->messageNodesRequired, - source => $sourceSchema, + return ValidationError->new( + message => $this->_MakeLabel( $this->messageNodesRequired ), parent => $node, - schema => $info->{Schema} - ) if $info->{Seen} < $info->{Min}; + schemaNode => $info->{schemaNode} + ) if $info->{seen} < $info->{min}; $info = shift @nodes; } return; } +sub _MakeLabel { + my ($this,$label) = @_; + + if ($label =~ /^ID:(\w+)$/) { + return Label->new($this->document->stringMap, $1); + } else { + return $label; + } +} + 1; __END__
--- a/Lib/IMPL/DOM/Schema/NodeSet.pm Tue Feb 11 20:22:01 2014 +0400 +++ b/Lib/IMPL/DOM/Schema/NodeSet.pm Wed Feb 12 13:36:24 2014 +0400 @@ -2,25 +2,28 @@ use strict; use warnings; -use parent qw(IMPL::DOM::Node); -use IMPL::Class::Property; -use IMPL::DOM::Property qw(_dom); - -our %CTOR = ( - 'IMPL::DOM::Node' => sub { nodeName => 'NodeSet' } -); - -BEGIN { - public _dom property messageUnexpected => prop_all; - public _dom property messageMax => prop_all; - public _dom property messageMin => prop_all; -} +use IMPL::Const qw(:prop); +use IMPL::declare { + require => { + Label => 'IMPL::DOM::Schema::Label', + ValidationError => 'IMPL::DOM::Schema::ValidationError', + AnyNode => '-IMPL::DOM::Schema::AnyNode' + }, + base => [ + 'IMPL::DOM::Node' => sub { nodeName => 'NodeSet' } + ], + props => [ + messageUnexpected => { get => 1, set => 1, dom => 1}, + messageMax => { get => 1, set => 1, dom => 1}, + messageMin => { get => 1, set => 1, dom => 1} + ] +}; sub CTOR { my ($this,%args) = @_; $this->messageMax( $args{messageMax} || 'Too many %node.nodeName% nodes'); - $this->messageMin( $args{messageMin} || '%schema.name% nodes expected'); + $this->messageMin( $args{messageMin} || '%schemaNode.name% nodes expected'); $this->messageUnexpected( $args{messageUnexpected} || 'A %node.nodeName% isn\'t allowed in %node.parentNode.path%'); } @@ -31,52 +34,58 @@ my %nodes; my $anyNode; - my $sourceSchema = $ctx->{Source} || $this->parentNode; foreach (@{$this->childNodes}) { - if ($_->isa('IMPL::DOM::Schema::AnyNode')) { - $anyNode = {Schema => $_, Min => $_->minOccur, Max => $_->maxOccur eq 'unbounded' ? undef : $_->maxOccur , Seen => 0 }; + if ($_->isa(AnyNode)) { + $anyNode = {schemaNode => $_, min => $_->minOccur, max => $_->maxOccur eq 'unbounded' ? undef : $_->maxOccur , seen => 0 }; } else { - $nodes{$_->name} = {Schema => $_, Min => $_->minOccur, Max => $_->maxOccur eq 'unbounded' ? undef : $_->maxOccur , Seen => 0 }; + $nodes{$_->name} = {schemaNode => $_, min => $_->minOccur, max => $_->maxOccur eq 'unbounded' ? undef : $_->maxOccur , seen => 0 }; } } foreach my $child ( @{$node->childNodes} ) { if (my $info = $nodes{$child->nodeName} || $anyNode) { - $info->{Seen}++; - push @errors,new IMPL::DOM::Schema::ValidationError ( - source => $sourceSchema, + $info->{seen}++; + push @errors,ValidationError->new( + schemaNode => $info->{schemaNode}, node => $child, parent => $node, - schema => $info->{Schema}, - message => $this->messageMax - ) if ($info->{Max} and $info->{Seen} > $info->{Max}); + message => $this->_MakeLabel($this->messageMax) + ) if ($info->{max} and $info->{seen} > $info->{max}); - if (my @localErrors = $info->{Schema}->Validate($child)) { + if (my @localErrors = $info->{schemaNode}->Validate($child)) { push @errors,@localErrors; } } else { - push @errors, new IMPL::DOM::Schema::ValidationError ( - source => $sourceSchema, + push @errors, ValidationError->new( node => $child, parent => $node, - message => $this->messageUnexpected + message => $this->_MakeLabel($this->messageUnexpected) ) } } foreach my $info (values %nodes) { - push @errors, new IMPL::DOM::Schema::ValidationError ( - source => $sourceSchema, - schema => $info->{Schema}, + push @errors, ValidationError->new( + schemaNode => $info->{schemaNode}, parent => $node, - message => $this->messageMin - ) if $info->{Min} > $info->{Seen}; + message => $this->_MakeLabel($this->messageMin) + ) if $info->{min} > $info->{seen}; } return @errors; } +sub _MakeLabel { + my ($this,$label) = @_; + + if ($label =~ /^ID:(\w+)$/) { + return Label->new($this->document->stringMap, $1); + } else { + return $label; + } +} + 1; __END__
--- a/Lib/IMPL/DOM/Schema/Property.pm Tue Feb 11 20:22:01 2014 +0400 +++ b/Lib/IMPL/DOM/Schema/Property.pm Wed Feb 12 13:36:24 2014 +0400 @@ -2,56 +2,66 @@ use strict; use warnings; -use parent qw(IMPL::DOM::Schema::SimpleNode); -require IMPL::DOM::Node; -use IMPL::Class::Property; -use IMPL::DOM::Property qw(_dom); - -__PACKAGE__->PassThroughArgs; - -BEGIN { - public _dom property messageRequired => prop_all; -} - -our %CTOR = ( - 'IMPL::DOM::Schema::SimpleNode' => sub { - my %args = @_; - - $args{maxOccur} = 1; - $args{minOccur} = delete $args{optional} ? 0 : 1; - $args{nodeName} ||= 'Property'; - $args{messageInflateError} ||= "Failed to inflate a property '%schema.name%' of a node '%node.path%': %error.message%"; - - return %args; - } -); +use IMPL::declare { + require => { + Label => 'IMPL::DOM::Schema::Label', + DOMNode => 'IMPL::DOM::Node', + ValidationError => 'IMPL::DOM::Schema::ValidationError' + }, + base => [ + 'IMPL::DOM::Schema::SimpleNode' => sub { + my %args = @_; + + $args{maxOccur} = 1; + $args{minOccur} = delete $args{optional} ? 0 : 1; + $args{nodeName} ||= 'Property'; + + return %args; + } + ], + props => [ + messageRequired => { get => 1, set => 1, dom => 1 } + ] +}; sub CTOR { my ($this,%args) = @_; - $this->messageRequired($args{messageRequired} || 'A property %schema.name% is required in the %node.qname%'); + $this->messageRequired($args{messageRequired} || 'A property %schemaNode.name% is required in the %node.qname%'); } sub Validate { my ($this,$node,$ctx) = @_; - my $prop = $this->name; - # buld a pseudo node for the property value - my $nodeProp = new IMPL::DOM::Node(nodeName => '::property', nodeValue => eval { $node->$prop() } || $node->nodeProperty($prop)); + my $nodeValue = $node->nodeProperty($this->name); - if ($nodeProp->nodeValue) { - # we have a value so validate it - return $this->SUPER::Validate($nodeProp,$ctx); + if (length $nodeValue) { + # we have a value so validate it + + # buld a pseudo node for the property value + my $nodeProp = DOMNode->new(nodeName => '::property', nodeValue => $nodeValue); + + return $this->SUPER::Validate($nodeProp); + } elsif($this->minOccur) { # we don't have a value but it's a mandatory property - return new IMPL::DOM::Schema::ValidationError( - message => $this->messageRequired, + return ValidationError->new( + message => $this->_MakeLabel($this->messageRequired), node => $node, - schema => $this, - source => $ctx && $ctx->{Source} || $this + schemaNode => $this ); } return (); } +sub _MakeLabel { + my ($this,$label) = @_; + + if ($label =~ /^ID:(\w+)$/) { + return Label->new($this->document->stringMap, $1); + } else { + return $label; + } +} + 1;
--- a/Lib/IMPL/DOM/Schema/SimpleType.pm Tue Feb 11 20:22:01 2014 +0400 +++ b/Lib/IMPL/DOM/Schema/SimpleType.pm Wed Feb 12 13:36:24 2014 +0400 @@ -2,43 +2,44 @@ use strict; use warnings; -use parent qw(IMPL::DOM::Schema::SimpleNode); -use IMPL::Class::Property; -use IMPL::DOM::Property qw(_dom); - -BEGIN { - public _dom _direct property nativeType => prop_get; - public _dom _direct property messageWrongType => prop_get; -} - -our %CTOR = ( - 'IMPL::DOM::Schema::SimpleNode' => sub { - my %args = @_; - $args{nodeName} = 'SimpleType'; - $args{minOccur} = 0; - $args{maxOccur} = 'unbounded'; - $args{name} ||= 'SimpleType'; - delete @args{qw(nativeType messageWrongType)}; - %args - } -); +use IMPL::declare { + require => { + Label => 'IMPL::DOM::Schema::Label', + ValidationError => 'IMPL::DOM::Schema::ValidationError' + }, + base => [ + 'IMPL::DOM::Schema::SimpleNode' => sub { + my %args = @_; + $args{nodeName} = 'SimpleType'; + $args{minOccur} = 0; + $args{maxOccur} = 'unbounded'; + $args{name} ||= 'SimpleType'; + delete @args{qw(nativeType messageWrongType)}; + %args + } + ], + props => [ + nativeType => { get => 1, set => 1, direct => 1, dom => 1}, + messageWrongType => { get => 1, set => 1, direct => 1, dom => 1 } + ] +}; sub CTOR { my ($this,%args) = @_; $this->{$nativeType} = $args{nativeType} if $args{nativeType}; - $this->{$messageWrongType} = $args{messageWrongType} || "A simple node '%node.path%' is expected to be %schema.nativeType%"; + $this->{$messageWrongType} = $args{messageWrongType} || "A simple node '%node.path%' is expected to be %schemaType.nativeType%"; } sub Validate { my ($this, $node, $ctx) = @_; if ($this->{$nativeType}) { - return new IMPL::DOM::Schema::ValidationError( + return ValidationError->new( node => $node, - source => $ctx && $ctx->{Source} || $this, - schema => $this, - message => $this->messageWrongType + schemaNode => $ctx->{schemaNode} || $this, + schemaType => $this, + message => $this->_MakeLabel($this->messageWrongType) ) unless $node->isa($this->{$nativeType}); } return $this->SUPER::Validate($node,$ctx); @@ -48,6 +49,16 @@ $_[0]->nodeName.'[type='.$_[0]->type.']'; } +sub _MakeLabel { + my ($this,$label) = @_; + + if ($label =~ /^ID:(\w+)$/) { + return Label->new($this->document->stringMap, $1); + } else { + return $label; + } +} + 1; __END__
--- a/Lib/IMPL/DOM/Schema/SwitchNode.pm Tue Feb 11 20:22:01 2014 +0400 +++ b/Lib/IMPL/DOM/Schema/SwitchNode.pm Wed Feb 12 13:36:24 2014 +0400 @@ -2,24 +2,24 @@ use strict; use warnings; -use parent qw(IMPL::DOM::Schema::AnyNode); -use IMPL::Class::Property; -require IMPL::DOM::Schema::ValidationError; -use IMPL::DOM::Property qw(_dom); - -our %CTOR = ( - 'IMPL::DOM::Schema::AnyNode' => sub { - my %args = @_; - - $args{nodeName} ||= 'SwitchNode'; - - %args; - } -); - -BEGIN { - public _dom property messageNoMatch => prop_all; -} +use IMPL::declare { + require => { + Label => 'IMPL::DOM::Schema::Label', + ValidationError => 'IMPL::DOM::Schema::ValidationError' + }, + base => [ + 'IMPL::DOM::Schema::AnyNode' => sub { + my %args = @_; + + $args{nodeName} ||= 'SwitchNode'; + + %args; + } + ], + props => [ + messageNoMatch => { get => 1, set => 1, dom => 1 } + ] +}; sub CTOR { my ($this,%args) = @_; @@ -31,16 +31,25 @@ my ($this,$node,$ctx) = @_; if ( my ($schema) = $this->selectNodes(sub {$_[0]->name eq $node->nodeName} ) ) { - return $schema->Validate($node); + return $schema->Validate($node,$ctx); } else { - return new IMPL::DOM::Schema::ValidationError( + return ValidationError->new( node => $node, - source => $this, - message => $this->messageNoMatch + message => $this->_MakeLabel($this->messageNoMatch) ); } } +sub _MakeLabel { + my ($this,$label) = @_; + + if ($label =~ /^ID:(\w+)$/) { + return Label->new($this->document->stringMap, $1); + } else { + return $label; + } +} + 1; __END__
--- a/Lib/IMPL/DOM/Schema/ValidationError.pm Tue Feb 11 20:22:01 2014 +0400 +++ b/Lib/IMPL/DOM/Schema/ValidationError.pm Wed Feb 12 13:36:24 2014 +0400 @@ -6,24 +6,32 @@ '""' => \&toString, 'fallback' => 1; -use parent qw(IMPL::Object); -use IMPL::Class::Property; +use IMPL::lang qw(is); +use IMPL::Const qw(:prop); +use IMPL::declare { + require => { + Label => '-IMPL::DOM::Schema::Label' + }, + base => [ + 'IMPL::Object' => undef + ], + props => [ + node => PROP_RO | PROP_DIRECT, + schemaNode => PROP_RO | PROP_DIRECT, + schemaType => PROP_RO | PROP_DIRECT, + parent => PROP_RO | PROP_DIRECT, + message => PROP_RO | PROP_DIRECT + ] +}; use IMPL::Resources::Format qw(FormatMessage); -BEGIN { - public _direct property node => prop_get; # target document node (if exists) - public _direct property schema => prop_get; # a schema for the target node (if exists) - public _direct property source => prop_get; # a schema which triggered this error (can be equal to the Schema) - public _direct property parent => prop_get; - public _direct property message => prop_get; # displayable message -} - sub CTOR { my ($this,%args) = @_; $this->{$node} = $args{node}; - $this->{$schema} = $args{schema} if $args{schema}; - $this->{$source} = $args{source} if $args{source}; + $this->{$schemaNode} = $args{schemaNode} if $args{schemaNode}; + $this->{$schemaType} = $args{schemaType} if $args{schemaType}; + if ($args{parent}) { $this->{$parent} = $args{parent}; } elsif ($args{node}) { @@ -32,13 +40,10 @@ die new IMPL::InvalidArgumentException("A 'parent' or a 'node' parameter is required"); } - if(my $msg = $args{message}) { - if (my($msgId) = ( $msg =~ /^ID:([\w\.]+)$/ ) ) { - $this->{$message} = ($args{schema} || $args{source})->document->stringMap->GetString($msgId, \%args); - } else { - $this->{$message} = FormatMessage(delete $args{message}, \%args) if $args{message}; - } + if ($args{message}) { + $this->{$message} = is($args{message},Label) ? $args{message}->Format(\%args) : FormatMessage($args{message}, \%args) ; } + } sub toString {
--- a/Lib/IMPL/DOM/Schema/Validator.pm Tue Feb 11 20:22:01 2014 +0400 +++ b/Lib/IMPL/DOM/Schema/Validator.pm Wed Feb 12 13:36:24 2014 +0400 @@ -1,10 +1,12 @@ package IMPL::DOM::Schema::Validator; use strict; -use parent qw(IMPL::DOM::Node); require IMPL::Exception; - -__PACKAGE__->PassThroughArgs; +use IMPL::declare { + base => [ + 'IMPL::DOM::Node' => '@_' + ] +}; sub Validate { my ($this,$node) = @_;
--- a/Lib/IMPL/DOM/Schema/Validator/Compare.pm Tue Feb 11 20:22:01 2014 +0400 +++ b/Lib/IMPL/DOM/Schema/Validator/Compare.pm Wed Feb 12 13:36:24 2014 +0400 @@ -1,30 +1,32 @@ package IMPL::DOM::Schema::Validator::Compare; use strict; -use parent qw(IMPL::DOM::Schema::Validator); - +use IMPL::Const qw(:prop); +use IMPL::declare { + require => { + Label => 'IMPL::DOM::Schema::Label', + ValidationError => 'IMPL::DOM::Schema::ValidationError' + }, + base => [ + 'IMPL::DOM::Schema::Validator' => sub { + my %args = @_; + $args{nodeName} ||= 'Compare'; + delete @args{qw(targetProperty op nodePath optional message)}; + %args; + } + ], + props => [ + targetProperty => PROP_RW, + op => PROP_RW, + nodePath => PROP_RW, + optional => PROP_RW, + _pathTranslated => PROP_RW, + _targetNode => PROP_RW, + _schemaNode => PROP_RW, + message => PROP_RW + ] +}; use IMPL::Resources::Format qw(FormatMessage); -use IMPL::Class::Property; - -BEGIN { - public property targetProperty => prop_all; - public property op => prop_all; - public property nodePath => prop_all; - public property optional => prop_all; - private property _pathTranslated => prop_all; - private property _targetNode => prop_all; - private property _sourceSchema => prop_all; - public property message => prop_all; -} - -our %CTOR = ( - 'IMPL::DOM::Schema::Validator' => sub { - my %args = @_; - $args{nodeName} ||= 'Compare'; - delete @args{qw(targetProperty op nodePath optional message)}; - %args; - } -); our %Ops = ( '=' => \&_equals, @@ -47,7 +49,7 @@ $this->targetProperty($args{targetProperty} || 'nodeValue'); $this->op( $Ops{ $args{op} || '=' } ) or die new IMPL::InvalidArgumentException("Invalid parameter value",'op',$args{op},$this->path); $this->nodePath($args{nodePath}) or die new IMPL::InvalidArgumentException("The argument is required", 'nodePath', $this->path); - $this->message($args{message} || 'The value of %node.path% %source.op% %value% (%source.nodePath%)' ); + $this->message($args{message} || 'The value of %node.path% %schemaNode.op% %value% (%schemaNode.nodePath%)' ); $this->optional($args{optional}) if $args{optional}; } @@ -94,8 +96,10 @@ Schema => $this->parentNode, Node => $this->_targetNode, schema => $this->parentNode, + schemaType => $this->parentNode, node => $this->_targetNode, - source => $this->_sourceSchema + source => $this->_schemaNode, + schemaNode => $this->_schemaNode },\&_resovleProperty) ) or return 0 foreach @parsedFilters; return 1; @@ -117,9 +121,10 @@ my @result; - my $Source = $ctx && $ctx->{Source} || $this->parentNode; + my $schemaNode = $ctx->{schemaNode}; + my $schemaType = $ctx->{schemaType}; - $this->_sourceSchema($Source); + $this->_schemaNode($schemaNode); $this->_targetNode($node); @@ -138,26 +143,26 @@ $value = $foreignNode->nodeValue; } - push @result, new IMPL::DOM::Schema::ValidationError( + push @result, ValidationError->new( node => $node, foreignNode => $foreignNode, value => $value, - source => $Source, - schema => $this->parentNode, - message => $this->message + schemaNode => $schemaNode, + schemaType => $schemaType, + message => $this->_MakeLabel($this->message) ) unless $this->op->(_resovleProperty($node,$this->targetProperty),$value); } elsif (not $this->optional) { - push @result, new IMPL::DOM::Schema::ValidationError( + push @result, ValidationError->new( node => $node, value => '', - source => $Source, - schema => $this->parentNode, - message => $this->message + schemaNode => $schemaNode, + schemaType => $schemaType, + message => $this->_MakeLabel( $this->message ) ); } $this->_targetNode(undef); - $this->_sourceSchema(undef); + $this->_schemaNode(undef); return @result; } @@ -216,6 +221,16 @@ $_[0] >= $_[1]; } +sub _MakeLabel { + my ($this,$label) = @_; + + if ($label =~ /^ID:(\w+)$/) { + return Label->new($this->document->stringMap, $1); + } else { + return $label; + } +} + 1; __END__ @@ -235,8 +250,8 @@ <schema> <SimpleType type="retype_field"> - <Property name="linkedNode" message="Для узла %Node.nodeName% необходимо задать свойство %Source.name%"/> - <Compare op="eq" nodePath="sibling:*[nodeName eq '%Node.linkedNode%']"/> + <Property name="linkedNode" message="Для узла %node.nodeName% необходимо задать свойство %schemaNode.name%"/> + <Compare op="eq" nodePath="sibling:*[nodeName eq '%node.linkedNode%']"/> </SimpleType> </schema>
--- a/Lib/IMPL/DOM/Schema/Validator/RegExp.pm Tue Feb 11 20:22:01 2014 +0400 +++ b/Lib/IMPL/DOM/Schema/Validator/RegExp.pm Wed Feb 12 13:36:24 2014 +0400 @@ -1,27 +1,30 @@ package IMPL::DOM::Schema::Validator::RegExp; use strict; -use parent qw(IMPL::DOM::Schema::Validator); -our %CTOR = ( - 'IMPL::DOM::Schema::Validator' => sub { - my %args = @_; - $args{nodeName} ||= 'RegExp'; - %args; - } -); - -use IMPL::Class::Property; - -BEGIN { - public property message => prop_all; - public property launder => prop_all; - private property _rx => prop_all; -} +use IMPL::Const qw(:prop); +use IMPL::declare { + require => { + Label => 'IMPL::DOM::Schema::Label', + ValidationError => 'IMPL::DOM::Schema::ValidationError' + }, + base => [ + 'IMPL::DOM::Schema::Validator' => sub { + my %args = @_; + $args{nodeName} ||= 'RegExp'; + %args; + } + ], + props => [ + message => { get => 1, set =>1, dom =>1 }, + launder => { get => 1, set =>1, dom =>1 }, + _rx => { get=> 1, set=> 1} + ] +}; sub CTOR { my ($this,%args) = @_; - $this->message($args{message} || "A %node.nodeName% doesn't match to the format %schema.display%"); + $this->message($args{message} || "A %node.nodeName% doesn't match to the format %schemaNode.label%"); } sub Validate { @@ -29,11 +32,11 @@ my $rx = $this->_rx() || $this->_rx( map qr{$_}, $this->nodeValue ); - return new IMPL::DOM::Schema::ValidationError( + return ValidationError->new ( node => $node, - source => $ctx && $ctx->{Source} || $this->parentNode, - schema => $this->parentNode, - message => $this->message + schemaNode => $ctx->{schemaNode}, + schemaType => $ctx->{schemaType}, + message => $this->_MakeLabel($this->message) ) unless (not $node->isComplex) and $node->nodeValue =~ /($rx)/; $node->nodeValue($1) if $this->launder; @@ -41,4 +44,14 @@ return (); } +sub _MakeLabel { + my ($this,$label) = @_; + + if ($label =~ /^ID:(\w+)$/) { + return Label->new($this->document->stringMap, $1); + } else { + return $label; + } +} + 1;
--- a/Lib/IMPL/DOM/XMLReader.pm Tue Feb 11 20:22:01 2014 +0400 +++ b/Lib/IMPL/DOM/XMLReader.pm Wed Feb 12 13:36:24 2014 +0400 @@ -93,7 +93,6 @@ my $doc = $parser->Navigator->Document; my @errors; if ($schema) { - @errors = $parser->Navigator->BuildErrors; push @errors, $schema->Validate($doc); }
--- a/Lib/IMPL/Web/View/Metadata/FormMeta.pm Tue Feb 11 20:22:01 2014 +0400 +++ b/Lib/IMPL/Web/View/Metadata/FormMeta.pm Wed Feb 12 13:36:24 2014 +0400 @@ -95,9 +95,8 @@ sub _IsOwnError { my ($nodes,$source,$err) = @_; - - #TODO: review filter - return 1 if ($err->node && grep($err->node == $_, @$nodes)) || (not(@$nodes) && $err->schema == $source ); + + return 1 if ($err->node && grep($err->node == $_, @$nodes)) || (not(@$nodes) && $err->schemaNode && $err->schemaNode == $source ); return 0; }
--- a/_test/Test/Web/View.pm Tue Feb 11 20:22:01 2014 +0400 +++ b/_test/Test/Web/View.pm Wed Feb 12 13:36:24 2014 +0400 @@ -59,10 +59,10 @@ my $meta = FormMeta->new( $doc, - $doc->schemaSource->type, + $doc->schemaNode->type, { - decl => $doc->schemaSource, - schema => $doc->schema, + decl => $doc->schemaNode, + schema => $doc->schemaType, errors => $errors } );