view Lib/IMPL/DOM/Schema/ValidationError.pm @ 388:648dfaf642e0

DOM refactoring, removed inflators from DOM Schema, DOM validation - in progress
author cin
date Tue, 11 Feb 2014 20:22:01 +0400
parents 2f16f13b000c
children 5aff94ba842f
line wrap: on
line source

package IMPL::DOM::Schema::ValidationError;
use strict;
use warnings;

use overload
    '""' => \&toString,
    'fallback' => 1;

use parent qw(IMPL::Object);
use IMPL::Class::Property;
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};
    if ($args{parent}) {
        $this->{$parent} = $args{parent};
    } elsif ($args{node}) {
        $this->{$parent} = $args{node}->parentNode;
    } else {
        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};
    	}
    }
}

sub toString {
    (my $this) = @_;
    return $this->message;
}

1;

__END__

=pod

=head1 NAME

C<IMPL::DOM::Schema::ValidationError> - Описывает ошибку в документе.

=head1 DESCRIPTION

При проверке документа на ошибки формирования возвращается массив с объектами
C<IMPL::DOM::Schema::ValidationError>, каждая из которых описывает одну ошибку
в документе.

С помощью данного объекта осущетсвляется привязка элемента схемы, элемента документа
и сообщения о причине возникновения ошибки.

Часть ошибок, таких как проверка содержимого на регулярные выражения, привязаны
непосредственно к элементу. Но есть ошибки которые привязываются к родительскому
контейнеру, например отсутсвие обязательного элемента. В таком случае ошибка
содержит свойство C<parent> и по свойству C<source> можно определить элемент
(например его имя), к которому относится ошибка.

=head1 MEMBERS

=over

=item C<[get] node>

Узел в документе который привел к ошибке. Как правило это либо простые узлы, либо
узлы, которые не могут присутствоать в данном месте по схеме.

Данное свойство может быть C<undef>. 

=item C<[get] parent>

Родительский узел в котором произошла ошибка. Используется в случаях, когда C<node>
не указан, например, если по схеме должен существовать дочерний узел с определенным
именем, а в реальном документе его нет.

Также это свойство может использоваться при формировании сообщения.

=item C<[get] schema>

Схема для C<Node> или узла который должен присутсвовать если C<Node> не задан.

=item C<[get] source>

Схема, проверка которой привела к возникновению ошибки. Поскольку схемы могут
использовать ссылки, то данное свойство нужно для получения схемы узла, а не
схемы его типа.

Тоесть проверка схемы узла C<IMPL::DOM::Schema::Node> приводит к проверке схемы
типа, например, C<IMPL::DOM::Schema::ComplexType>, а свойство C<Source> будет
указывать именно на C<IMPL::DOM::Schema::Node>.

=item C<[get] message>

Возвращает форматированное сообщение об ошибке.

=item C<toString()>

Преобразует ошибку к строке, возвращает значение свойства C<Message>

=back

=head1 REMARKS

=begin code

my $doc = IMPL::DOM::XMLReader->LoadDocument('data.xml');
my $schema = IMPL::DOM::Schema->LoadSchema('schema.xml');

my @errors = $schema->Validate($doc);

my $node = $doc->selectSingleNode('user','name');

# Получаем все ошибки относящиеся к данному узлу
my @nodeErrors = grep { ($_->node || $_->parent) == $node } @errors;  

=end code

=cut