comparison Lib/IMPL/template.pm @ 165:76515373dac0

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