File Coverage

blib/lib/Persistence/Meta/Injection.pm
Criterion Covered Total %
statement 16 18 88.8
branch n/a
condition n/a
subroutine 6 6 100.0
pod n/a
total 22 24 91.6


line stmt bran cond sub pod time code
1             package Persistence::Meta::Injection;
2              
3 1     1   25607 use strict;
  1         3  
  1         40  
4 1     1   6 use warnings;
  1         1  
  1         37  
5 1     1   7 use vars qw($VERSION);
  1         2  
  1         44  
6              
7 1     1   5 use Abstract::Meta::Class ':all';
  1         2  
  1         181  
8 1     1   5 use Carp 'confess';
  1         3  
  1         65  
9 1     1   56 use Persistence::Entity ':all';
  0            
  0            
10             use Persistence::Relationship;
11             use Persistence::Relationship::ToOne;
12             use Persistence::Relationship::OneToMany;
13             use Persistence::Relationship::ManyToMany;
14             use Persistence::ValueGenerator::TableGenerator;
15             use Persistence::ValueGenerator::SequenceGenerator;
16              
17             use Storable qw(store retrieve);
18              
19             $VERSION = 0.01;
20              
21             =head1 NAME
22              
23             Persistence::Meta::Injection - Persisitence meta definition object.
24              
25             =cut
26              
27             =head1 SYNOPSIS
28              
29             use Persistence::Meta::Injection;
30              
31             my $obj = Persistence::Meta::Injection->new;
32              
33             =head1 DESCRIPTION
34              
35             Represents persistence meta data that is loaded as a persistence unit.
36             (Entitties + ORM mapping)
37              
38             =head1 EXPORT
39              
40             None
41              
42             =head2 ATTRIBUTES
43              
44             =over
45              
46             =item entities
47              
48             =cut
49              
50             has '%.entities' => (item_accessor => 'entity', index_by => 'id');
51              
52              
53             =item _entities_subquery_columns
54              
55             =cut
56              
57             has '%._entities_subquery_columns';
58              
59              
60             =item _entities_to_many_relationship
61              
62             =cut
63              
64             has '%._entities_to_many_relationships';
65              
66              
67             =item _entities_to_one_relationship
68              
69             =cut
70              
71             has '%._entities_to_one_relationships';
72              
73              
74             =item orm_files
75              
76             =cut
77              
78             has '@.orm_files';
79              
80              
81             =item entities_files
82              
83             =cut
84              
85             has '@.entities_files';
86              
87              
88             =item sequence_generators
89              
90             =cut
91              
92             has '@.sequence_generators';
93              
94              
95             =item table_generators
96              
97             =cut
98              
99             has '@.table_generators';
100              
101              
102             =item _orm_mapping
103              
104             =cut
105              
106             has '@._orm_mapping';
107              
108              
109             =item entity_manager
110              
111             =cut
112              
113             has '$.entity_manager';
114              
115              
116             =item cached_version
117              
118             =cut
119              
120             has '$.cached_version';
121              
122              
123             =item file_stats
124              
125             =cut
126              
127              
128             has '%.file_stats' => (item_accessor => 'file_stat');
129              
130              
131             =back
132              
133             =head2 METHODS
134              
135             =over
136              
137             =item load_persistence_context
138              
139             =cut
140              
141             sub load_persistence_context {
142             my ($self, $xml, $file) = @_;
143             my $entity_manager = $self->entity_manager;
144            
145             if(! $self->cached_version) {
146             my $entity_files = $self->entities_files;
147             my $orm_files = $self->orm_files;
148             my $entity_xml_hander = $xml->entity_xml_handler;
149             my $orm_xml_handler = $xml->orm_xml_handler;
150             my $prefix_dir = $xml->persistence_dir;
151             for my $entity_ref (@$entity_files) {
152             my $file_name = $prefix_dir . $entity_ref->{file};
153             $self->add_file_stat($file_name);
154             my %overwriten_entity_attributes = (map { $_ ne 'file' ? ($_ => $entity_ref->{$_}) : ()} keys %$entity_ref);
155             my $entity = $entity_xml_hander->parse_file($file_name, \%overwriten_entity_attributes);
156             $self->entity($entity->id, $entity);
157             }
158            
159             $self->_initialise_subquery_columns();
160             $self->_initialise_to_one_relationships();
161             $self->_initialise_to_many_relationships();
162             $self->_initialise_value_generators();
163            
164             for my $orm_ref (@$orm_files) {
165             my $file_name = $prefix_dir . $orm_ref->{file};
166             $self->add_file_stat($file_name);
167             $orm_xml_handler->parse_file($file_name);
168             }
169              
170             if ($xml->use_cache) {
171             $self->_store($xml, $file);
172             }
173             }
174              
175             my %entities = $self->entities;
176             $entity_manager->add_entities(values %entities);
177             $self->crate_orm_mappings();
178             $entity_manager;
179             }
180              
181              
182             =item _store
183              
184             =cut
185              
186             sub _store {
187             my ($self, $xml, $file) = @_;
188             my $cache_file_name = $xml->cache_file_name($file);
189             $self->set_cached_version(1);
190             store $self, $cache_file_name;
191             }
192              
193              
194             =item load_from_cache
195              
196             Loads injection object from cache
197              
198             =cut
199              
200             sub load_from_cache {
201             my ($class, $xml, $file) = @_;
202             my $cache_file_name = $xml->cache_file_name($file);
203             my $result;
204             if(-e $cache_file_name) {
205             $result = retrieve($cache_file_name);
206             }
207             $result
208             }
209              
210              
211             =item can_use_cache
212              
213             Returns true if there are not changes in xml files
214              
215             =cut
216              
217             sub can_use_cache {
218             my ($self) = @_;
219             my $result = 1;
220             my $file_stats = $self->file_stats;
221             return undef unless (%$file_stats);
222             for my $file(keys %$file_stats) {
223             my $modification_time = file_modification_time($file);
224             return if $file_stats->{$file} ne $modification_time;
225             }
226             $result;
227             }
228              
229              
230             =item _initialise_value_generators
231              
232             Initialises value generators
233              
234             =cut
235              
236             sub _initialise_value_generators {
237             my ($self) = @_;
238             $self->_initialise_generators('Persistence::ValueGenerator::TableGenerator', 'table_generators');
239             $self->_initialise_generators('Persistence::ValueGenerator::SequenceGenerator', 'sequence_generators');
240             }
241              
242              
243             =item _initialise_table_value_generators
244              
245             =cut
246              
247             sub _initialise_generators {
248             my ($self, $class, $accessor) = @_;
249             my $entity_manager = $self->entity_manager;
250             my $generators = $self->$accessor;
251             for my $generator (@$generators) {
252             $class->new(%$generator, entity_manager_name => $entity_manager->name);
253             }
254             }
255              
256              
257             =item _initialise_subquery_columns
258              
259             Initialise subquery columns
260              
261             =cut
262              
263             sub _initialise_subquery_columns {
264             my ($self) = @_;
265             my $entities = $self->entities;
266             my $entities_subquery_columns = $self->_entities_subquery_columns;
267             for my $entity_id (keys %$entities_subquery_columns) {
268             my $entity = $entities->{$entity_id};
269             my @subquery_columns;
270             my $subquery_columns = $entities_subquery_columns->{$entity_id};
271             for my $column_definition (@$subquery_columns) {
272             push @subquery_columns,
273             $self->entity_column($column_definition->{entity}, $column_definition->{name});
274             }
275             $entity->add_subquery_columns(@subquery_columns)
276             if @subquery_columns;
277             }
278             }
279              
280              
281             =item _initialise_to_one_relationship
282              
283             Initialise to one relationships
284              
285             =cut
286              
287             sub _initialise_to_one_relationships {
288             my ($self) = @_;
289             $self->_initialise_relationships('to_one_relationships');
290             }
291              
292              
293             =item _initialise_to_many_relationship
294              
295             Initialise to manye relationships
296              
297             =cut
298              
299             sub _initialise_to_many_relationships {
300             my ($self) = @_;
301             $self->_initialise_relationships('to_many_relationships');
302             }
303              
304              
305             =item _initialise_relationships
306              
307             Initialises relationshsips
308             Takes relationship type as parameters.
309             Allowed value: 'to_one_relationships', 'to_many_relationships'
310              
311             =cut
312              
313             sub _initialise_relationships {
314             my ($self, $relationship_type) = @_;
315             my $entities = $self->entities;
316             my $relationship_accessor = "_entities_${relationship_type}";
317             my $entities_relationships = $self->$relationship_accessor;
318             my $mutator = "add_${relationship_type}";
319              
320             for my $entity_id (keys %$entities_relationships) {
321             my $entity = $entities->{$entity_id};
322             my @relationships;
323             my $relationships = $entities_relationships->{$entity_id};
324            
325             for my $relationship (@$relationships) {
326             push @relationships, $self->_relationship($relationship);
327             }
328            
329             if (@relationships) {
330             $entity->$mutator(@relationships)
331             }
332            
333             }
334             }
335              
336              
337              
338             =item crate_orm_mappings
339              
340             =cut
341              
342             sub crate_orm_mappings {
343             my ($self) = @_;
344             my $orm_mapping = $self->_orm_mapping;
345             for (my $i = 0; $i< $#{$orm_mapping}; $i += 2) {
346             $self->create_orm_mapping($orm_mapping->[$i], $orm_mapping->[$i + 1]);
347             }
348             }
349              
350              
351             =item create_orm_mapping
352              
353             Creates orm mappings.
354              
355             =cut
356              
357             sub create_orm_mapping {
358             my ($self, $args, $rules) = @_;
359             my $columns = $rules->{columns};
360             my $lobs = $rules->{lobs};
361             my $to_one_relationships = $rules->{to_one_relationships};
362             my $one_to_many_relationships = $rules->{one_to_many_relationships};
363             my $many_to_many_relationships = $rules->{many_to_many_relationships};
364             $args->{entity_name} = $args->{entity}, delete $args->{entity};
365             my $orm = Persistence::ORM->new(%$args);
366             my $columns_map = {};
367             for my $column (@$columns) {
368             $columns_map->{$column->{name}} = {name => $column->{attribute}};
369             }
370              
371             $orm->set_columns($orm->covert_to_attributes($columns_map));
372             my $lob_map = $orm->covert_to_lob_attributes($lobs);
373             $orm->set_lobs($lob_map);
374            
375             for my $relation (@$to_one_relationships) {
376             $self->_add_to_one_relationship($relation, $orm);
377             }
378             for my $relation (@$one_to_many_relationships) {
379             $self->_add_one_to_many_relationship($relation, $orm);
380             }
381             for my $relation (@$many_to_many_relationships) {
382             $self->_add_many_to_many_relationship($relation, $orm);
383             }
384             $orm;
385             }
386              
387              
388              
389             =item _add_one_to_many_relationship
390              
391             =cut
392              
393             sub _add_one_to_many_relationship {
394             my ($self, $relationship, $orm) = @_;
395             Persistence::Relationship::OneToMany->add_relationship($self->_add_relationship_parameters($relationship, $orm));
396             }
397              
398              
399              
400             =item _add_to_many_to_many_relationship
401              
402             =cut
403              
404             sub _add_many_to_many_relationship {
405             my ($self, $relationship, $orm) = @_;
406             Persistence::Relationship::ManyToMany->add_relationship($self->_add_relationship_parameters($relationship, $orm));
407             }
408              
409              
410             =item _add_to_one_relationship
411              
412             =cut
413              
414             sub _add_to_one_relationship {
415             my ($self, $relationship, $orm) = @_;
416             Persistence::Relationship::ToOne->add_relationship($self->_add_relationship_parameters($relationship, $orm));
417             }
418              
419              
420             =item _add_relationship_parameters
421              
422             =cut
423              
424             sub _add_relationship_parameters {
425             my ($self, $relationship, $orm) = @_;
426             my $attribute = $orm->attribute($relationship->{attribute});
427            
428             my @result = ($orm->class, $relationship->{name}, attribute => $attribute);
429             if (my $fetch_method = $relationship->{fetch_method}) {
430             push @result, 'fetch_method' => Persistence::Relationship->$fetch_method();
431             }
432             if (my $cascade = $relationship->{cascade}) {
433             push @result, 'cascade' => Persistence::Relationship->$cascade();
434             }
435            
436             if (my $join_entity = $relationship->{join_entity}) {
437             push @result, 'join_entity_name' => $join_entity;
438             }
439             @result;
440             }
441              
442              
443              
444             =item _relationship
445              
446             Returns the relationship object.
447             Takes hash_ref, that will be transformed to the new object parameters.
448              
449             =cut
450              
451             sub _relationship {
452             my ($self, $relationship) = @_;
453             my $target_entity = ref($relationship->{target_entity}) ? $relationship->{target_entity}->id : $relationship->{target_entity};
454            
455             my $entity = $self->entity($target_entity)
456             or confess "unknow entity " . $target_entity;
457             $relationship->{target_entity} = $entity;
458             my $condition = $relationship->{condition};
459             $self->_parse_condition($condition) if $condition;
460             sql_relationship(%$relationship);
461             }
462              
463              
464             =item _parse_condition
465              
466             Parses condition object to replacase ant occurence of . to column object.
467              
468             =cut
469              
470             sub _parse_condition {
471             my ($self, $condition) = @_;
472             {
473             my $operand1 = $condition->operand1;
474             my ($entity, $column) = $self->has_column($operand1);
475             $condition->set_operand1($self->entity_column($entity, $column)) if($column)
476             }
477             {
478             my $operand2 = $condition->operand2;
479             my ($entity, $column) = $self->has_column($operand2);
480             $condition->set_operand2($self->entity_column($entity, $column)) if($column)
481             }
482             my $conditions = $condition->conditions;
483             for my $k (@$conditions) {
484             $self->_parse_condition($k);
485             }
486              
487             }
488              
489              
490             =item has_column
491              
492             =cut
493              
494             sub has_column {
495             my ($self, $text) = @_;
496             ($text =~ m /^sql_column:(\w+)\.(\w+)/);
497             }
498              
499             =item entity_column
500              
501             Returns entity column
502              
503             =cut
504              
505             sub entity_column {
506             my ($self, $entity_id, $column_id) = @_;
507             my $entities = $self->entities;
508             my $entity = $entities->{$entity_id}
509             or confess "unknown entity: ${entity_id}";
510             my $column = $entity->column($column_id)
511             or confess "unknown column ${column_id} on entity ${entity_id}";
512             }
513              
514              
515             =item add_file_stat
516              
517             Adds file modification time
518              
519             =cut
520              
521             sub add_file_stat {
522             my ($self, $file) = @_;
523             my $modification_time = file_modification_time($file);
524             $self->file_stat($file, $modification_time);
525             }
526              
527              
528             =item file_modification_time
529              
530             =cut
531              
532             sub file_modification_time {
533             my $file = shift;
534             my $modification_time = (stat $file)[9];
535             }
536              
537              
538             1;
539              
540             __END__