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) = @_;