Mercurial > pub > Impl
changeset 101:d8dc6cad3f55
Schema in progress
author | wizard |
---|---|
date | Thu, 06 May 2010 17:55:59 +0400 |
parents | df6b4f054957 |
children | cf3b6ef2be22 |
files | Lib/IMPL/DOM/Schema.pm Lib/IMPL/DOM/Schema/Property.pm Lib/IMPL/DOM/Schema/Validator.pm _test/Resources/types.xml _test/Test/DOM/Schema.pm |
diffstat | 5 files changed, 82 insertions(+), 5 deletions(-) [+] |
line wrap: on
line diff
--- a/Lib/IMPL/DOM/Schema.pm Thu May 06 00:54:17 2010 +0400 +++ b/Lib/IMPL/DOM/Schema.pm Thu May 06 17:55:59 2010 +0400 @@ -12,10 +12,14 @@ require IMPL::DOM::Schema::NodeSet; require IMPL::DOM::Schema::Property; require IMPL::DOM::Schema::SwitchNode; +require IMPL::DOM::Schema::Validator; +require IMPL::DOM::Navigator::Builder; +require IMPL::DOM::XMLReader; use base qw(IMPL::DOM::Document); use IMPL::Class::Property; use IMPL::Class::Property::Direct; +use File::Spec; our %CTOR = ( 'IMPL::DOM::Document' => sub { nodeName => 'schema' } @@ -23,6 +27,7 @@ BEGIN { private _direct property _TypesMap => prop_all; + public _direct property baseDir => prop_all; public _direct property BaseSchemas => prop_get | owner_set; private _direct property _Validators => prop_all; } @@ -36,15 +41,66 @@ die new IMPL::Exception('Invalid node class') unless $class->isa('IMPL::DOM::Node'); - goto &SUPER::Create; + if ($class->isa('IMPL::DOM::Schema::Validator')) { + $class = "IMPL::DOM::Schema::Validator::$nodeName"; + local $@; + unless (eval {$class->can('new')}) { + eval "require $class; 1;"; + my $e = $@; + die new IMPL::Exception("Invalid validator",$class,$e) if $e; + } + } + + return $this->SUPER::Create($nodeName,$class,$refArgs); } sub Process { my ($this) = @_; + # process instructions + $this->Include($_) foreach map $_->nodeProperty('source'), $this->selectNodes('Include'); + + # build types map $this->{$_TypesMap} = { map { $_->type, $_ } $this->selectNodes(sub { $_[0]->nodeName eq 'ComplexType' || $_[0]->nodeName eq 'SimpleType' } ) }; } +sub Include { + my ($this,$file) = @_; + + my $schema = $this->LoadSchema($file); + + $this->appendRange( $schema->childNodes ); +} + +sub LoadSchema { + my ($this,$file,$base) = @_; + + my $class = ref $this || $this; + + my $reader = new IMPL::DOM::XMLReader( + Navigator => new IMPL::DOM::Navigator::Builder( + $class, + $class->MetaSchema + ) + ); + + $reader->ParseFile($file) or die new IMPL::Exception("Failed to load a schema",$file); + + my $schema = $reader->Navigator->Document; + + my ($vol,$dir) = File::Spec->splitpath($file); + + $schema->baseDir($dir); + + my @errors = $class->MetaSchema->Validate($schema); + + die new IMPL::Exception("Schema is invalid",$file,map( $_->Message, @errors ) ) if @errors; + + $schema->Process; + + return $schema; +} + sub Validate { my ($this,$node) = @_;
--- a/Lib/IMPL/DOM/Schema/Property.pm Thu May 06 00:54:17 2010 +0400 +++ b/Lib/IMPL/DOM/Schema/Property.pm Thu May 06 17:55:59 2010 +0400 @@ -36,7 +36,7 @@ if ($this->minOccur) { my $prop = $this->name; - my $nodeProp = new IMPL::DOM::Node(nodeName => '::property', nodeValue => $node->$prop() || $node->nodePropety($prop)); + my $nodeProp = new IMPL::DOM::Node(nodeName => '::property', nodeValue => eval { $node->$prop() } || $node->nodeProperty($prop)); if (! $nodeProp->nodeValue) { return new IMPL::DOM::Schema::ValidationError(
--- a/Lib/IMPL/DOM/Schema/Validator.pm Thu May 06 00:54:17 2010 +0400 +++ b/Lib/IMPL/DOM/Schema/Validator.pm Thu May 06 17:55:59 2010 +0400 @@ -23,6 +23,7 @@ C<IMPL::DOM::Schema::Validator> - Базовый класс для ограничений на простые значения. =head1 DESCRIPTION + От основных элементов схемы его отличает то, что в конечном документе он не соответсвует никаким узлам и поэтому у него отсутствуют свойства C<minOcuur,maxOccur,name>.
--- a/_test/Resources/types.xml Thu May 06 00:54:17 2010 +0400 +++ b/_test/Resources/types.xml Thu May 06 17:55:59 2010 +0400 @@ -2,6 +2,9 @@ <SimpleType type="email" nativeType="SCALAR"> <RegExp message="Неверный формат %Node.name_no%">^\w+(\.\w+)*@$\w+(\.\w+)+</RegExp> </SimpleType> - <SimpleType name="scalar" nativeType="SCALAR"/> - <SimpleType name="date" nativeType="DateTime"/> + <SimpleType type="scalar" nativeType="SCALAR"/> + <SimpleType type="date" nativeType="DateTime"> + <Property name="timezone" optional="1"/> + <Property name="locale" optional="1"/> + </SimpleType> </schema> \ No newline at end of file
--- a/_test/Test/DOM/Schema.pm Thu May 06 00:54:17 2010 +0400 +++ b/_test/Test/DOM/Schema.pm Thu May 06 17:55:59 2010 +0400 @@ -8,7 +8,8 @@ __PACKAGE__->PassThroughArgs; -require IMPL::DOM::Schema; +use IMPL::DOM::Schema; +use IMPL::DOM::Navigator::Builder; BEGIN { shared public property SampleSchema => prop_all; @@ -100,5 +101,21 @@ failed "A wrong data validated corretly" unless $this->SampleSchema->Validate($data); }; +test LoadXmlSchemaTypes => sub { + my ($this) = @_; + + my $schema = IMPL::DOM::Schema->LoadSchema("Resources/types.xml") or failed "Failed to parse schema"; + + return 1; +}; + +test LoadXmlSchemaData => sub { + my ($this) = @_; + + my $schema = IMPL::DOM::Schema->LoadSchema("Resources/form.xml") or failed "Failed to parse schema"; + + return 1; +}; + 1;