comparison lib/IMPL/ORM/Schema.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::Schema;
2 use strict;
3 use warnings;
4
5 use parent qw(IMPL::DOM::Document);
6 use IMPL::Class::Property;
7 require IMPL::ORM::Schema::Entity;
8 require IMPL::ORM::Schema::ValueType;
9
10 our %CTOR = (
11 'IMPL::DOM::Document' => sub { nodeName => 'ORMSchema' }
12 );
13
14 BEGIN {
15 public property mapValueTypes => prop_get | owner_set;
16 public property mapReferenceTypes => prop_get | owner_set;
17 public property mapPending => prop_get | owner_set;
18 public property prefix => prop_get | owner_set;
19 }
20
21 sub CTOR {
22 my ($this ) = @_;
23 $this->mapValueTypes({});
24 $this->mapReferenceTypes({});
25 $this->mapPending({});
26 }
27
28 # return an entity for the specified typename
29 # makes forward declaration if nesessary
30 sub resolveType {
31 my ($this,$typeName) = @_;
32
33 $this = ref $this ? $this : $this->instance;
34
35 if (my $entity = $this->mapReferenceTypes->{$typeName}) {
36 return $entity;
37 } elsif (UNIVERSAL::isa($typeName,'IMPL::ORM::Object')) {
38 return $this->declareReferenceType($typeName);
39 } else {
40 return undef;
41 }
42 }
43
44 sub declareReferenceType {
45 my ($this,$typeName) = @_;
46
47 my $entity = new IMPL::ORM::Schema::Entity($typeName->entityName);
48
49 $this->mapPending->{$typeName} = $entity;
50
51 $this->appendChild($entity);
52
53 return $this->mapReferenceTypes->{$typeName} = $entity;
54 }
55
56 sub _addReferenceType {
57 my ($this,$className) = @_;
58
59 if ( my $entity = delete $this->mapPending->{$className} ) {
60 $className->ormGetSchema($this,$entity);
61 } else {
62 return $this->appendChild( $this->mapReferenceTypes->{$className} = $className->ormGetSchema($this) );
63 }
64
65 }
66
67 # returns valuetype name
68 sub isValueType {
69 my ($this,$typeName) = @_;
70
71 $this = ref $this ? $this : $this->instance;
72
73 return $this->mapValueTypes->{$typeName};
74 }
75
76 my %instances;
77 sub instance {
78 my ($class) = @_;
79
80 return ($instances{$class} || ($instances{$class} = $class->new));
81 }
82
83 sub ValueTypes {
84 my ($this,%classes) = @_;
85
86 $this = ref $this ? $this : $this->instance;
87
88 while ( my ($typeName,$typeReflected) = each %classes ) {
89 $this->mapValueTypes->{$typeName} = $typeReflected;
90 $this->appendChild(IMPL::ORM::Schema::ValueType->new($typeName,$typeReflected));
91 }
92 }
93
94 sub Classes {
95 my ($this,@classNames) = @_;
96
97 $this = ref $this ? $this : $this->instance;
98
99 $this->_addReferenceType($this->prefix . $_) foreach @classNames;
100 }
101
102 sub usePrefix {
103 my ($this,$prefix) = @_;
104
105 $prefix .= '::' if $prefix and $prefix !~ /::$/;
106
107 (ref $this ? $this : $this->instance)->prefix($prefix);
108 }
109
110 sub CompleteSchema {
111 my ($this) = @_;
112
113 $this = ref $this ? $this : $this->instance;
114
115 $_->ormGetSchema($this,delete $this->mapPending->{$_}) foreach (keys %{$this->mapPending});
116 }
117
118 1;
119
120 __END__
121
122 =pod
123
124 =head1 NAME
125
126 C<IMPL::ORM::Schema> Схема отображения классов в реляционную структуру.
127
128 =head1 DESCRIPTION
129
130 Схема данных, представляет собой DOM документ, элементами которой
131 являются сущности.
132
133 Каждый узел - это описание сущности.
134
135 =begin code xml
136
137 <Schema>
138 <Entity entityName="My_Data_Foo">
139 <Field fieldName="Doo" fieldType="String"/>
140 <HasMany name="Boxes" target="My_Data_Box"/>
141 </Entity>
142 <Entity entityName="My_Data_Bar">
143 <Subclass base="My_Data_Foo"/>
144 <Field fieldName="Timestamp" fieldType="Integer"/>
145 </Entity>
146 <Entity entityName="My_Data_Box">
147 <Field fieldName="Capacity" fieldType="Integer"/>
148 </Entity>
149 </Schema>
150
151 =end code xml
152
153 =cut