annotate Lib/IMPL/Class/Property/Direct.pm @ 41:c442eb67fa22

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