Mercurial > pub > Impl
view Lib/Schema/DataSource.pm @ 1:3b418b134d8c
ORM in progress
author | Sergey |
---|---|
date | Fri, 17 Jul 2009 13:30:46 +0400 |
parents | 03e58a454b20 |
children | 16ada169ca75 |
line wrap: on
line source
package Configuration; our $DataDir; package Schema::DataSource; use Common; use strict; use base qw(Object); use BNFCompiler; use Schema::DB; use Schema; use URI::file; BEGIN { DeclareProperty ProcessedSchemas => ACCESS_NONE; #{ uri => schema } DeclareProperty Types => ACCESS_READ; # Schema DeclareProperty DataSourceBuilder => ACCESS_READ; DeclareProperty Compiler => ACCESS_NONE; } sub CTOR { my ($this,%args) = @_; $this->{$DataSourceBuilder} = $args{'DataSourceBuilder'} or die new Exception('A data source builder is required'); $this->{$Types} = new Schema; $this->{$Compiler} = new BNFCompiler(SchemaCache => "${DataDir}Cache/",Transform => sub { BNFCompiler::DOM::TransformDOMToHash(@_,{skip_spaces => 1})} ); $this->{$Compiler}->LoadBNFSchema(file => 'Schema/schema.def'); } sub as_list { return( map { UNIVERSAL::isa($_,'ARRAY') ? @{$_} : defined $_ ? $_ : () } @_ ); } sub ProcessSchema { my ($this,$uriFile) = @_; return 1 if $this->{$ProcessedSchemas}{$uriFile->as_string}; my $uriDir = URI::file->new('./')->abs($uriFile); $this->{$ProcessedSchemas}->{$uriFile->as_string} = 1; my $Schema = $this->ParseSchema($uriFile); foreach my $item (as_list($Schema->{'header'}{'include_item'})) { my $uriItem = URI::file->new($item->{'file_name'})->abs($uriDir); $this->ProcessSchema($uriItem); } $this->ConstructTypes($Schema); } sub ParseSchema { my ($this,$fileUri) = @_; my $fileName = $fileUri->file; open my $hfile,"$fileName" or die new Exception('Failed to read the file',$fileName,$!); local $/ = undef; my $Schema = $this->{$Compiler}->Parse(<$hfile>); return $Schema; } sub ConstructTypes { my ($this,$schema) = @_; return if not $schema->{'class'}; foreach my $class (as_list($schema->{'class'})){ # объявление типа my $type; my $builder; if ($class->{'type_definition'}{'args_list'}) { $type = $this->{$Types}->CreateTemplate($class->{'type_definition'}{'name'},as_list($class->{'type_definition'}{'args_list'}{'name'})); } else { $type = $this->{$Types}->CreateType($class->{'type_definition'}{'name'}); } $type->SetAttributes(ValueType => 1) if $class->{'value_type'}; my $mappingTip = $this->{$DataSourceBuilder}->GetClassMapping($type); # обрабатываем список базовых классов if ($class->{'base_types'}) { foreach my $typename (as_list($class->{'base_types'}{'type'})) { $type->AddBase(MakeTypeName($typename)); } } # обрабатываем список свойств if ($class->{'property_list'}) { foreach my $property (as_list($class->{'property_list'}{'property'})) { $type->InsertProperty($property->{'name'},MakeTypeName($property->{'type'})); if (my $mapping = $property->{'mapping'}) { $mappingTip->PropertyMapping($property->{'name'},Column => $mapping->{'column_name'},DBType => $mapping->{'db_type'}); } } } } } sub MakeTypeName { my ($typename) = @_; return new Schema::TypeName( $typename->{'name'}, ( $typename->{'template_list'} ? map { MakeTypeName($_) } as_list($typename->{'template_list'}{'type'}) : () ) ); } sub BuildSchema { my ($this,$fileName) = @_; my $uriFile = URI::file->new_abs($fileName); $this->ProcessSchema($uriFile); $this->{$Types}->Close(); foreach my $type ($this->{$Types}->EnumTypes(skip_templates => 1)) { $this->{$DataSourceBuilder}->AddType($type); } } sub DESTROY { my ($this) = @_; $this->{$Compiler}->Dispose; $this->{$DataSourceBuilder}->Dispose; $this->{$Types}->Dispose; } 1;