File Coverage

web/cgi-bin/yatt.lib/YATT/Class/Configurable.pm
Criterion Covered Total %
statement 72 88 81.8
branch 22 34 64.7
condition n/a
subroutine 16 19 84.2
pod 0 14 0.0
total 110 155 70.9


line stmt bran cond sub pod time code
1             # -*- mode: perl; coding: utf-8 -*-
2             package YATT::Class::Configurable;
3 12     12   53 use strict;
  12         11  
  12         333  
4 12     12   37 use warnings FATAL => qw(all);
  12         12  
  12         458  
5              
6             our %FIELDS;
7 12     12   4784 use fields;
  12         11867  
  12         44  
8             sub MY () {__PACKAGE__}
9 12     12   1098 use YATT::Util::Symbol qw(fields_hash globref);
  12         16  
  12         677  
10 12     12   50 use Carp;
  12         16  
  12         9276  
11              
12             sub new {
13 6292     6292 0 15423 my MY $self = fields::new(shift);
14 6292         353301 $self->before_configure;
15 6292 100       7842 if (@_) {
16 5254         8907 $self->init(@_);
17             } else {
18 1038         1941 $self->after_configure;
19             }
20 6292         17193 $self
21             }
22              
23 3887     3887 0 7342 sub initargs {return}
24              
25             sub init {
26 5254     5254 0 4767 my MY $self = shift;
27 5254 100       7793 if (my @member = $self->initargs) {
28 1909         2585 @{$self}{@member} = splice @_, 0, scalar @member;
  1909         2987  
29             }
30 5254 100       7087 if (@_) {
31 5237         8248 $self->configure(@_);
32             } else {
33 17         60 $self->after_configure;
34             }
35 5254         6951 $self;
36             }
37              
38             sub refid {
39 29     29 0 212 $_[0] + 0;
40             }
41              
42             sub stringify {
43 0     0 0 0 my MY $self = shift;
44 0         0 require Data::Dumper;
45 0         0 sprintf '%s->new(%s)', ref $self
46             , join ", ", Data::Dumper->new
47             ([map($self->{$_}, $self->initargs)
48             , $self->configure])->Terse(1)->Indent(0)->Dump;
49             }
50              
51             sub clone {
52 542     542 0 666 my MY $ref = shift;
53 542         1187 ref($ref)->new(map($ref->{$_}, $ref->initargs)
54             , $ref->configure
55             , @_);
56             }
57              
58             sub cget {
59 2092     2092 0 2385 (my MY $self, my ($cf)) = @_;
60 2092         2337 $cf =~ s/^-//; # For Tcl/Tk co-operatability.
61 2092         3510 my $fields = fields_hash($self);
62 2092 50       4262 croak "Can't cget $cf" unless exists $fields->{"cf_$cf"};
63 2092         7372 $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     6292 0 5136 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 57 (my MY $self, my ($name)) = @_;
93 35         100 my $fields = fields_hash($self);
94 35 50       217 exists $fields->{"cf_$name"} || $self->can("configure_$name");
95             }
96              
97             sub configure {
98 7130     7130 0 6105 my MY $self = shift;
99 7130         11856 my $fields = fields_hash($self);
100 7130 100       11329 unless (@_) {
101             # list all configurable options.
102             return map {
103 775 100       1768 if (m/^cf_(.*)/) {
  6258         10122  
104 4841         9244 ($1 => $self->{$_})
105             } else {
106             ()
107 1417         2579 }
108             } keys %$fields;
109             }
110 6355 50       9318 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       8785 if (@_ % 2) {
115 0         0 croak "Odd number of arguments";
116             }
117              
118 6355         4431 my @task;
119 6355         12740 while (my ($name, $value) = splice @_, 0, 2) {
120 20863 50       23451 croak "undefined name for configure" unless defined $name;
121 20863 100       49549 if (my $sub = $self->can("configure_$name")) {
122 139         458 push @task, [$sub, $value];
123             } else {
124 20724 50       30002 croak "No such config item: $name" unless exists $fields->{"cf_$name"};
125 20724         51899 $self->{"cf_$name"} = $value;
126             }
127             }
128 6355         8052 foreach my $task (@task) {
129 139         425 $task->[0]->($self, $task->[1]);
130             }
131 6355         9878 $self->after_configure;
132 6355         9961 $self;
133             }
134              
135             sub after_configure {
136 7278     7278 0 5873 my MY $self = shift;
137             # $self->SUPER::after_configure;
138 7278         6628 foreach my $cf (grep {/^cf_/} keys %{fields_hash($self)}) {
  51082         73478  
  7278         11738  
139 34537 100       52117 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       44622 my $sub = $self->can("default_$cf") or next;
144 676         1928 $self->{$cf} = $sub->();
145             }
146             }
147              
148             sub define {
149 62     62 0 81 my ($class, $method, $sub) = @_;
150             # XXX: API 以外の関数は弾くべきかもしれない。
151 62         55 *{globref($class, $method)} = $sub;
  62         157  
152             }
153              
154             1;