File Coverage

web/cgi-bin/yatt.lib/YATT/Class/Configurable.pm
Criterion Covered Total %
statement 71 87 81.6
branch 22 34 64.7
condition n/a
subroutine 16 19 84.2
pod 0 14 0.0
total 109 154 70.7


line stmt bran cond sub pod time code
1             # -*- mode: perl; coding: utf-8 -*-
2             package YATT::Class::Configurable;
3 12     12   70 use strict;
  12         21  
  12         347  
4 12     12   56 use warnings qw(FATAL all NONFATAL misc);
  12         22  
  12         937  
5              
6             our %FIELDS;
7 12     12   9263 use fields;
  12         18643  
  12         64  
8             sub MY () {__PACKAGE__}
9 12     12   1755 use YATT::Util::Symbol qw(fields_hash globref);
  12         22  
  12         782  
10 12     12   63 use Carp;
  12         21  
  12         14633  
11              
12             sub new {
13 6292     6292 0 28452 my MY $self = fields::new(shift);
14 6292         523875 $self->before_configure;
15 6292 100       12602 if (@_) {
16 5254         13829 $self->init(@_);
17             } else {
18 1038         2787 $self->after_configure;
19             }
20 6292         24435 $self
21             }
22              
23 3887     3887 0 11390 sub initargs {return}
24              
25             sub init {
26 5254     5254 0 7047 my MY $self = shift;
27 5254 100       12055 if (my @member = $self->initargs) {
28 1909         3682 @{$self}{@member} = splice @_, 0, scalar @member;
  1909         4740  
29             }
30 5254 100       9681 if (@_) {
31 5237         12172 $self->configure(@_);
32             } else {
33 17         92 $self->after_configure;
34             }
35 5254         11262 $self;
36             }
37              
38             sub refid {
39 29     29 0 223 $_[0] + 0;
40             }
41              
42             sub stringify {
43 0     0 0 0 my MY $self = shift;
44 0         0 require Data::Dumper;
45             sprintf '%s->new(%s)', ref $self
46             , join ", ", Data::Dumper->new
47 0         0 ([map($self->{$_}, $self->initargs)
48             , $self->configure])->Terse(1)->Indent(0)->Dump;
49             }
50              
51             sub clone {
52 542     542 0 764 my MY $ref = shift;
53 542         1627 ref($ref)->new(map($ref->{$_}, $ref->initargs)
54             , $ref->configure
55             , @_);
56             }
57              
58             sub cget {
59 2092     2092 0 3574 (my MY $self, my ($cf)) = @_;
60 2092         3162 $cf =~ s/^-//; # For Tcl/Tk co-operatability.
61 2092         5261 my $fields = fields_hash($self);
62 2092 50       6489 croak "Can't cget $cf" unless exists $fields->{"cf_$cf"};
63 2092         11104 $self->{"cf_$cf"};
64             }
65              
66             sub cgetlist {
67 0     0 0 0 (my MY $self) = shift;
68             map {
69 0 0       0 if (exists $self->{"cf_$_"}) {
  0         0  
70 0         0 ($_ => $self->{"cf_$_"})
71             } else {
72             ()
73 0         0 }
74             } @_;
75             }
76              
77              
78       6292 0   sub before_configure {}
79              
80             sub configkeys {
81 0     0 0 0 my MY $self = shift;
82             return map {
83 0 0       0 if (m/^cf_(.*)/) {
  0         0  
84 0         0 $1
85             } else {
86             ()
87 0         0 }
88             } keys %$self;
89             }
90              
91             sub can_configure {
92 35     35 0 73 (my MY $self, my ($name)) = @_;
93 35         102 my $fields = fields_hash($self);
94 35 50       286 exists $fields->{"cf_$name"} || $self->can("configure_$name");
95             }
96              
97             sub configure {
98 7130     7130 0 9559 my MY $self = shift;
99 7130         17962 my $fields = fields_hash($self);
100 7130 100       18326 unless (@_) {
101             # list all configurable options.
102             return map {
103 775 100       2404 if (m/^cf_(.*)/) {
  6258         15945  
104 4841         14556 ($1 => $self->{$_})
105             } else {
106             ()
107 1417         4172 }
108             } keys %$fields;
109             }
110 6355 50       13985 if (@_ == 1) {
111 0 0       0 croak "No such config item: $_[0]" unless exists $fields->{"cf_$_[0]"};
112 0         0 return $self->{"cf_$_[0]"};
113             }
114 6355 50       15375 if (@_ % 2) {
115 0         0 croak "Odd number of arguments";
116             }
117              
118 6355         7379 my @task;
119 6355         19457 while (my ($name, $value) = splice @_, 0, 2) {
120 20863 50       39029 croak "undefined name for configure" unless defined $name;
121 20863 100       79572 if (my $sub = $self->can("configure_$name")) {
122 139         675 push @task, [$sub, $value];
123             } else {
124 20724 50       51028 croak "No such config item: $name" unless exists $fields->{"cf_$name"};
125 20724         88950 $self->{"cf_$name"} = $value;
126             }
127             }
128 6355         11671 foreach my $task (@task) {
129 139         560 $task->[0]->($self, $task->[1]);
130             }
131 6355         16077 $self->after_configure;
132 6355         15895 $self;
133             }
134              
135             sub after_configure {
136 7278     7278 0 10108 my MY $self = shift;
137             # $self->SUPER::after_configure;
138 7278         8207 foreach my $cf (grep {/^cf_/} keys %{fields_hash($self)}) {
  51082         122659  
  7278         17793  
139 34537 100       79246 next if defined $self->{$cf};
140             # XXX: should be:
141             # (my $name = $cf) =~ s/^cf_//;
142             # my $sub = $self->can("default_$name") or next;
143 16562 100       73949 my $sub = $self->can("default_$cf") or next;
144 676         2658 $self->{$cf} = $sub->();
145             }
146             }
147              
148             sub define {
149 62     62 0 144 my ($class, $method, $sub) = @_;
150             # XXX: API 以外の関数は弾くべきかもしれない。
151 62         88 *{globref($class, $method)} = $sub;
  62         179  
152             }
153              
154             1;