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         19  
  12         460  
4 12     12   59 use warnings qw(FATAL all NONFATAL misc);
  12         23  
  12         605  
5              
6             our %FIELDS;
7 12     12   9638 use fields;
  12         19354  
  12         66  
8             sub MY () {__PACKAGE__}
9 12     12   1800 use YATT::Util::Symbol qw(fields_hash globref);
  12         28  
  12         830  
10 12     12   66 use Carp;
  12         22  
  12         14995  
11              
12             sub new {
13 6304     6304 0 22391 my MY $self = fields::new(shift);
14 6304         528010 $self->before_configure;
15 6304 100       14468 if (@_) {
16 5266         14196 $self->init(@_);
17             } else {
18 1038         3110 $self->after_configure;
19             }
20 6304         25321 $self
21             }
22              
23 3899     3899 0 11483 sub initargs {return}
24              
25             sub init {
26 5266     5266 0 7567 my MY $self = shift;
27 5266 100       12983 if (my @member = $self->initargs) {
28 1909         3535 @{$self}{@member} = splice @_, 0, scalar @member;
  1909         5095  
29             }
30 5266 100       10392 if (@_) {
31 5249         12068 $self->configure(@_);
32             } else {
33 17         63 $self->after_configure;
34             }
35 5266         11478 $self;
36             }
37              
38             sub refid {
39 29     29 0 225 $_[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 922 my MY $ref = shift;
53 542         1366 ref($ref)->new(map($ref->{$_}, $ref->initargs)
54             , $ref->configure
55             , @_);
56             }
57              
58             sub cget {
59 2092     2092 0 3700 (my MY $self, my ($cf)) = @_;
60 2092         3962 $cf =~ s/^-//; # For Tcl/Tk co-operatability.
61 2092         5496 my $fields = fields_hash($self);
62 2092 50       6837 croak "Can't cget $cf" unless exists $fields->{"cf_$cf"};
63 2092         10815 $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       6304 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 92 (my MY $self, my ($name)) = @_;
93 35         110 my $fields = fields_hash($self);
94 35 50       266 exists $fields->{"cf_$name"} || $self->can("configure_$name");
95             }
96              
97             sub configure {
98 7142     7142 0 10274 my MY $self = shift;
99 7142         18644 my $fields = fields_hash($self);
100 7142 100       18534 unless (@_) {
101             # list all configurable options.
102             return map {
103 775 100       2486 if (m/^cf_(.*)/) {
  6258         16649  
104 4841         16970 ($1 => $self->{$_})
105             } else {
106             ()
107 1417         2525 }
108             } keys %$fields;
109             }
110 6367 50       13548 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 6367 50       13449 if (@_ % 2) {
115 0         0 croak "Odd number of arguments";
116             }
117              
118 6367         7159 my @task;
119 6367         19971 while (my ($name, $value) = splice @_, 0, 2) {
120 20923 50       42342 croak "undefined name for configure" unless defined $name;
121 20923 100       81027 if (my $sub = $self->can("configure_$name")) {
122 139         706 push @task, [$sub, $value];
123             } else {
124 20784 50       51834 croak "No such config item: $name" unless exists $fields->{"cf_$name"};
125 20784         94484 $self->{"cf_$name"} = $value;
126             }
127             }
128 6367         12036 foreach my $task (@task) {
129 139         537 $task->[0]->($self, $task->[1]);
130             }
131 6367         16623 $self->after_configure;
132 6367         16009 $self;
133             }
134              
135             sub after_configure {
136 7290     7290 0 10062 my MY $self = shift;
137             # $self->SUPER::after_configure;
138 7290         9464 foreach my $cf (grep {/^cf_/} keys %{fields_hash($self)}) {
  51262         128499  
  7290         19841  
139 34669 100       81007 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 16646 100       71959 my $sub = $self->can("default_$cf") or next;
144 676         2544 $self->{$cf} = $sub->();
145             }
146             }
147              
148             sub define {
149 62     62 0 135 my ($class, $method, $sub) = @_;
150             # XXX: API 以外の関数は弾くべきかもしれない。
151 62         91 *{globref($class, $method)} = $sub;
  62         188  
152             }
153              
154             1;