Mercurial > pub > Impl
comparison Lib/IMPL/Class/Property/Direct.pm @ 0:03e58a454b20
Создан репозитарий
author | Sergey |
---|---|
date | Tue, 14 Jul 2009 12:54:37 +0400 |
parents | |
children | 16ada169ca75 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:03e58a454b20 |
---|---|
1 package IMPL::Class::Property::Direct; | |
2 use strict; | |
3 | |
4 use base qw(IMPL::Object::Accessor Exporter); | |
5 our @EXPORT = qw(_direct); | |
6 | |
7 use IMPL::Class::Property; | |
8 require IMPL::Exception; | |
9 | |
10 __PACKAGE__->mk_accessors qw(ExportField); | |
11 | |
12 sub _direct($) { | |
13 my ($prop_info) = @_; | |
14 $prop_info->Implementor( IMPL::Class::Property::Direct->new({ExportField => 1}) ); | |
15 return $prop_info; | |
16 } | |
17 | |
18 my $access_private = "die new IMPL::Exception('Can\\'t access the private member',\$name,\$class,scalar caller) unless caller eq \$class;"; | |
19 my $access_protected = "die new IMPL::Exception('Can\\'t access the protected member',\$name,\$class,scalar caller) unless caller eq \$class;"; | |
20 | |
21 my $accessor_get_no = 'die new IMPL::Exception(\'The property is write only\',$name,$class) unless $get;'; | |
22 my $accessor_set_no = 'die new IMPL::Exception(\'The property is read only\',$name,$class) unless $set;'; | |
23 my $accessor_set = 'return( $this->{$field} = @_ == 1 ? $_[0] : [@_] );'; | |
24 my $accessor_get = 'return( $this->{$field} );'; | |
25 my $list_accessor_set = 'return( @{ ($this->{$field} = ( (@_ == 1 and ref $_[0] eq \'ARRAY\') ? $_[0] : [@_] ) || [] ) } );'; | |
26 my $list_accessor_get = 'return( @{ $this->{$field} || [] } );'; | |
27 my $custom_accessor_get = 'unshift @_, $this and goto &$get;'; | |
28 my $custom_accessor_set = 'unshift @_, $this and goto &$set;'; | |
29 | |
30 my %accessor_cache; | |
31 sub mk_acessor { | |
32 my ($virtual,$access,$class,$name,$mutators,$field) = @_; | |
33 | |
34 my ($get,$set) = ref $mutators ? ( $mutators->{get}, $mutators->{set}) : ($mutators & prop_get, $mutators & prop_set); | |
35 my $key = join '',$virtual,$access,$get ? 1 : 0,$set ? 1 : 0, (ref $mutators ? 'c' : ($mutators & prop_list() ? 'l' : 's')); | |
36 my $factory = $accessor_cache{$key}; | |
37 if (not $factory) { | |
38 my $code = | |
39 <<BEGIN; | |
40 sub { | |
41 my (\$class,\$name,\$set,\$get,\$field) = \@_; | |
42 my \$accessor; | |
43 \$accessor = sub { | |
44 my \$this = shift; | |
45 BEGIN | |
46 $code .= <<VCALL if $virtual; | |
47 my \$method = \$this->can(\$name); | |
48 return \$this->\$method(\@_) unless \$method == \$accessor or caller->isa(\$class); | |
49 VCALL | |
50 $code .= "$access_private\n" if $access == IMPL::Class::Member::MOD_PRIVATE; | |
51 $code .= "$access_protected\n" if $access == IMPL::Class::Member::MOD_PROTECTED; | |
52 my ($codeGet,$codeSet); | |
53 if (ref $mutators) { | |
54 $codeGet = $get ? $custom_accessor_get : $accessor_get_no; | |
55 $codeSet = $set ? $custom_accessor_set : $accessor_set_no; | |
56 } else { | |
57 if ($mutators & prop_list) { | |
58 $codeGet = $get ? $list_accessor_get : $accessor_get_no; | |
59 $codeSet = $set ? $list_accessor_set : $accessor_set_no; | |
60 } else { | |
61 $codeGet = $get ? $accessor_get : $accessor_get_no; | |
62 $codeSet = $set ? $accessor_set : $accessor_set_no; | |
63 } | |
64 } | |
65 $code .= | |
66 <<END; | |
67 if (\@_) { | |
68 $codeSet | |
69 } else { | |
70 $codeGet | |
71 } | |
72 } | |
73 } | |
74 END | |
75 $factory = eval $code or die new IMPL::Exception('Failed to generate the accessor',$@); | |
76 $accessor_cache{$key} = $factory; | |
77 } | |
78 return $factory->($class,$name,$set,$get, $field); | |
79 } | |
80 | |
81 sub Make { | |
82 my ($self,$propInfo) = @_; | |
83 | |
84 my $isExportField = ref $self ? ($self->ExportField || 0) : 0; | |
85 my ($class,$name,$virt,$access,$mutators) = $propInfo->get qw(Class Name Virtual Access Mutators); | |
86 (my $field = "${class}_$name") =~ s/::/_/g; | |
87 | |
88 my $propGlob = $class.'::'.$name; | |
89 | |
90 no strict 'refs'; | |
91 *$propGlob = mk_acessor($virt,$access,$class,$name,$mutators,$field); | |
92 *$propGlob = \$field if $isExportField; | |
93 | |
94 if (ref $mutators) { | |
95 $propInfo->canGet( $mutators->{get} ? 1 : 0); | |
96 $propInfo->canSet( $mutators->{set} ? 1 : 0); | |
97 } else { | |
98 $propInfo->canGet( ($mutators & prop_get) ? 1 : 0); | |
99 $propInfo->canSet( ($mutators & prop_set) ? 1 : 0); | |
100 } | |
101 } | |
102 | |
103 sub FieldName { | |
104 my ($self,$propInfo) = @_; | |
105 | |
106 my ($class,$name) = $propInfo->get qw(Class Name); | |
107 (my $field = "${class}_$name") =~ s/::/_/g; | |
108 return $field; | |
109 } | |
110 | |
111 1; |