annotate lib/IMPL/template.pm @ 413:af8d359ee4cc ref20150831

working on di container
author cin
date Thu, 24 Sep 2015 12:19:30 +0300
parents c6e90e02dd17
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
407
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
1 package IMPL::template;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
2 use strict;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
3 use warnings;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
4
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
5 use IMPL::Class::Template();
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
6
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
7 sub import {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
8 shift;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
9 my %args = @_;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
10
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
11 my $class = caller;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
12
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
13 my @paramNames = grep m/\w+/, @{$args{parameters} || []};
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
14 my $declare = $args{declare};
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
15 my @isa = (@{$args{base} || []}, $class);
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
16 my %instances;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
17
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
18 no strict 'refs';
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
19
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
20 push @{"${class}::ISA"}, 'IMPL::Class::Template';
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
21
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
22 *{"${class}::$_"} = sub { die IMPL::InvalidOperationException("A template parameter isn't available here") }
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
23 foreach @paramNames;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
24
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
25 *{"${class}::spec"} = sub {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
26 my ($self,@params) = @_;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
27
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
28 my $specClass = $self->makeName(@params);
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
29
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
30 return $specClass if $instances{$specClass};
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
31
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
32 $instances{$specClass} = 1;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
33
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
34 for (my $i=0; $i < @paramNames; $i++) {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
35 my $param = $params[$i];
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
36 *{"${specClass}::$paramNames[$i]"} = sub { $param };
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
37 }
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
38
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
39 @{"${specClass}::ISA"} = @isa;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
40
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
41 &$declare($specClass) if $declare;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
42 return $specClass;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
43 };
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
44 }
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
45
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
46 1;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
47
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
48 __END__
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
49
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
50 =pod
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
51
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
52 =head1 NAME
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
53
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
54 C<IMPL::template> директива для объявления шаблона.
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
55
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
56 =head1 SYNPOSIS
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
57
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
58 =begin code
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
59
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
60 package KeyValuePair;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
61
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
62 use IMPL::Class::Property;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
63
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
64 use IMPL::template (
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
65 parameters => [qw(TKey TValue))],
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
66 base => [qw(IMPL::Object IMPL::Object::Autofill)],
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
67 declare => sub {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
68 my ($class) = @_;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
69 public $class->CreateProperty(key => prop_get | owner_set, { type => $class->TKey } );
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
70 public $class->CreateProperty(value => prop_all, { type => $class->TValue} );
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
71
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
72 $class->PassThroughArgs;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
73 }
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
74 );
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
75
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
76 BEGIN {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
77 public property id => prop_get | owner_set, { type => 'integer'};
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
78 }
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
79
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
80 __PACKAGE__->PassThroughArgs;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
81
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
82 package MyCollection;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
83
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
84 use IMPL::Class::Property;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
85
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
86 use IMPL::lang;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
87 use IMPL::template(
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
88 parameters => [qw(TKey TValue)],
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
89 base => [qw(IMPL::Object)],
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
90 declare => sub {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
91 my ($class) = @_;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
92 my $item_t = spec KeyValuePair($class->TKey,$class->TValue);
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
93
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
94 public $class->CreateProperty(items => prop_get | prop_list, { type => $item_t } );
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
95
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
96 $class->static_accessor( ItemType => $item_t );
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
97 }
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
98 )
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
99
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
100 sub Add {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
101 my ($this,$key,$value) = @_;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
102
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
103 die new IMPL::ArgumentException( key => "Invalid argument type" ) unless is $key, $this->TKey;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
104 die new IMPL::ArgumentException( value => "Invalid argument type" ) unless is $value, $this->TValue;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
105
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
106 $this->items->AddLast( $this->ItemType->new( key => $key, value => $value ) );
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
107 }
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
108
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
109 package main;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
110
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
111 use IMPL::require {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
112 TFoo => 'Some::Package::Foo',
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
113 TBar => 'Some::Package::Bar'
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
114 };
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
115
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
116 my $TCol = spec MyCollection(TFoo, TBar);
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
117
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
118 =end code
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
119
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
120 =head1 DESCRIPTION
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
121
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
122 Шаблоны используются для динамической генерации классов. Процесс создания класса
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
123 по шаблону называется специализацией, при этом создается новый класс:
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
124
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
125 =over
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
126
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
127 =item 1
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
128
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
129 Обявляется новый пакет с именем, вычисленным из имени и параметров шаблона
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
130
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
131 =item 2
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
132
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
133 Формируется массив C<@ISA> для созаднного класса, в который добавляется имя шаблона
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
134
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
135 =item 3
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
136
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
137 Формируются методы с именами параметров шаблона, возвращающие реальные значения параметров
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
138
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
139 =item 4
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
140
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
141 Вызывается метод для конструирования специализиции
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
142
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
143 =back
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
144
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
145 =head1 MEMBERS
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
146
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
147 =over
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
148
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
149 =item C<spec(@params)>
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
150
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
151 Метод, создающий специализацию шаблона. Может быть вызван как оператор.
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
152
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
153 =back
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
154
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
155 =cut