comparison lib/IMPL/ORM/Object.pm @ 407:c6e90e02dd17 ref20150831

renamed Lib->lib
author cin
date Fri, 04 Sep 2015 19:40:23 +0300
parents
children
comparison
equal deleted inserted replaced
406:f23fcb19d3c1 407:c6e90e02dd17
1 package IMPL::ORM::Object;
2 use strict;
3 use warnings;
4
5 use parent qw(IMPL::Object);
6 use IMPL::Class::Property;
7
8 require IMPL::ORM::Entity;
9 require IMPL::ORM::Schema::Entity;
10 require IMPL::ORM::Schema::Field;
11 require IMPL::ORM::Schema::Relation::HasMany;
12 require IMPL::ORM::Schema::Relation::HasOne;
13 require IMPL::ORM::Schema::Relation::Subclass;
14
15 BEGIN {
16 private _direct property _entities => prop_all;
17 public property objectType => prop_all, {type => 'String'};
18
19 sub _PropertyImplementor {
20 'IMPL::ORM::PropertyImplementor'
21 }
22 }
23
24 my %schemaCache;
25
26 sub CTOR {
27 my ($this) = @_;
28
29 while ( my ($class,$schema) = $this->ormGetSchema ) {
30 $this->{$_entities}{$class} = new IMPL::ORM::Entity($class,$schema);
31 }
32 }
33
34 sub ormStore {
35 my ($this,$class,$prop,$value) = @_;
36
37 die IMPL::InvalidOperationException("Cannot find entity for the specified class",$class) unless $this->{$_entities}{$class};
38
39 $this->{$_entities}{$class}->Store($prop,$value);
40 }
41
42 sub ormGet {
43 my ($this,$class,$prop,$value) = @_;
44
45 return $this->{$_entities}{$class} ? $this->{$_entities}{$class}->Get($prop,$value) : undef;
46 }
47
48 sub entityName {
49 (my $self = ref $_[0] || $_[0]) =~ s/^.*?(\w+)$/$1/;
50 return $self;
51 }
52
53 sub ormGetSchema {
54 my ($self,$dataSchema,$surrogate) = @_;
55
56 my $schema = $surrogate || IMPL::ORM::Schema::Entity->new($self->entityName);
57
58 # для текущего класса, проходим по всем свойствам
59 foreach my $ormProp (
60 $self->get_meta(
61 'IMPL::Class::PropertyInfo',
62 sub {
63 UNIVERSAL::isa($_->Implementor, 'IMPL::ORM::PropertyImplementor' )
64 },
65 0
66 )
67 ){
68 if ($ormProp->Mutators & prop_list) {
69 # отношение 1 ко многим
70 my $type = $dataSchema->resolveType($ormProp->Type) or die new IMPL::InvalidOperationException("Failed to resolve a reference type due building schema for a class", $ormProp->Class, $ormProp->Name);
71 $schema->appendChild( new IMPL::ORM::Schema::Relation::HasMany($ormProp->Name, $type->entityName) );
72 } elsif (my $type = $dataSchema->isValueType($ormProp->Type)) {
73 # поле
74 $schema->appendChild( new IMPL::ORM::Schema::Field($ormProp->Name,$ormProp->Type) );
75 } elsif (my $entity = $dataSchema->resolveType($ormProp->Type)) {
76 # отношение ссылка
77 $schema->appendChild( new IMPL::ORM::Schema::Relation::HasOne($ormProp->Name,$entity->entityName));
78 } else {
79 # хз что. Скорее всего не удалось квалифицировать тип свойства не как ссылочный и как поле.
80 die new IMPL::Exception('Uexpected error due building schema for a class', $ormProp->Class, $ormProp->Name,$ormProp->Type);
81 }
82 }
83
84 # Формируем отношения наследования
85 {
86 # локализуем прагму
87 no strict 'refs';
88
89 my $class = ref $self || $self;
90
91 # по всем классам
92 foreach my $super (grep $_->isa(__PACKAGE__), @{"${class}::ISA"}) {
93 my $type = $dataSchema->resolveType($super) or die new IMPL::InvalidOperationException("Failed to resolve a super class due building schema for a class", $class, $super);
94 $schema->appendChild(new IMPL::ORM::Schema::Relation::Subclass($type));
95 }
96 }
97
98 return $schema;
99 }
100
101 1;
102
103 __END__
104
105 =pod
106
107 =head1 DESCRIPTION
108
109 Базовый объект для реляционного отображения,
110 содержит в себе реляционные записи представляющие данный объект.
111
112 Каждый класс отображается в определенную сущность. Сущности хранят
113 состояние объектов в том виде в котором удобно записывать в реляционную базу.
114
115 =cut