Mercurial > pub > Impl
diff Lib/IMPL/DOM/Schema.pm @ 101:d8dc6cad3f55
Schema in progress
author | wizard |
---|---|
date | Thu, 06 May 2010 17:55:59 +0400 |
parents | df6b4f054957 |
children | cf3b6ef2be22 |
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) = @_;