Mercurial > pub > Impl
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 |