line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# |
2
|
|
|
|
|
|
|
# This file is part of Config-Model-Itself |
3
|
|
|
|
|
|
|
# |
4
|
|
|
|
|
|
|
# This software is Copyright (c) 2007-2017 by Dominique Dumont. |
5
|
|
|
|
|
|
|
# |
6
|
|
|
|
|
|
|
# This is free software, licensed under: |
7
|
|
|
|
|
|
|
# |
8
|
|
|
|
|
|
|
# The GNU Lesser General Public License, Version 2.1, February 1999 |
9
|
|
|
|
|
|
|
# |
10
|
|
|
|
|
|
|
package Config::Model::Itself ; |
11
|
|
|
|
|
|
|
$Config::Model::Itself::VERSION = '2.011'; |
12
|
8
|
|
|
8
|
|
2134696
|
use Mouse ; |
|
8
|
|
|
|
|
24
|
|
|
8
|
|
|
|
|
50
|
|
13
|
8
|
|
|
8
|
|
2858
|
use Config::Model 2.103; |
|
8
|
|
|
|
|
149
|
|
|
8
|
|
|
|
|
255
|
|
14
|
8
|
|
|
8
|
|
110
|
use 5.010; |
|
8
|
|
|
|
|
33
|
|
15
|
|
|
|
|
|
|
|
16
|
8
|
|
|
8
|
|
42
|
use IO::File ; |
|
8
|
|
|
|
|
21
|
|
|
8
|
|
|
|
|
991
|
|
17
|
8
|
|
|
8
|
|
47
|
use Log::Log4perl 1.11; |
|
8
|
|
|
|
|
98
|
|
|
8
|
|
|
|
|
45
|
|
18
|
8
|
|
|
8
|
|
337
|
use Carp ; |
|
8
|
|
|
|
|
16
|
|
|
8
|
|
|
|
|
362
|
|
19
|
8
|
|
|
8
|
|
40
|
use Data::Dumper ; |
|
8
|
|
|
|
|
16
|
|
|
8
|
|
|
|
|
278
|
|
20
|
8
|
|
|
8
|
|
40
|
use File::Find ; |
|
8
|
|
|
|
|
16
|
|
|
8
|
|
|
|
|
303
|
|
21
|
8
|
|
|
8
|
|
38
|
use File::Path ; |
|
8
|
|
|
|
|
45
|
|
|
8
|
|
|
|
|
285
|
|
22
|
8
|
|
|
8
|
|
65
|
use File::Basename ; |
|
8
|
|
|
|
|
16
|
|
|
8
|
|
|
|
|
359
|
|
23
|
8
|
|
|
8
|
|
3122
|
use Data::Compare ; |
|
8
|
|
|
|
|
63757
|
|
|
8
|
|
|
|
|
47
|
|
24
|
8
|
|
|
8
|
|
23128
|
use Path::Tiny 0.062; |
|
8
|
|
|
|
|
152
|
|
|
8
|
|
|
|
|
331
|
|
25
|
8
|
|
|
8
|
|
47
|
use Mouse::Util::TypeConstraints; |
|
8
|
|
|
|
|
23
|
|
|
8
|
|
|
|
|
70
|
|
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
my $logger = Log::Log4perl::get_logger("Backend::Itself"); |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
subtype 'ModelPathTiny' => as 'Object' => where { $_->isa('Path::Tiny') }; |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
coerce 'ModelPathTiny' => from 'Str' => via {path($_)} ; |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
# find all .pl file in model_dir and load them... |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
around BUILDARGS => sub { |
36
|
|
|
|
|
|
|
my $orig = shift; |
37
|
|
|
|
|
|
|
my $class = shift; |
38
|
|
|
|
|
|
|
my %args = @_; |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
my $legacy = delete $args{model_object}; |
41
|
|
|
|
|
|
|
if ($legacy) { |
42
|
|
|
|
|
|
|
$args{config_model} = $legacy->instance->config_model; |
43
|
|
|
|
|
|
|
$args{meta_instance} = $legacy->instance; |
44
|
|
|
|
|
|
|
$args{meta_root} = $legacy; |
45
|
|
|
|
|
|
|
} |
46
|
|
|
|
|
|
|
return $class->$orig( %args ); |
47
|
|
|
|
|
|
|
}; |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
has 'config_model' => ( |
50
|
|
|
|
|
|
|
is => 'ro', |
51
|
|
|
|
|
|
|
isa => 'Config::Model', |
52
|
|
|
|
|
|
|
lazy_build => 1, |
53
|
|
|
|
|
|
|
) ; |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
sub _build_config_model { |
57
|
0
|
|
|
0
|
|
0
|
my $self = shift; |
58
|
|
|
|
|
|
|
# don't trigger builders below |
59
|
0
|
0
|
|
|
|
0
|
if ($self->{meta_root}) { |
|
|
0
|
|
|
|
|
|
60
|
0
|
|
|
|
|
0
|
return $self->meta_root->instance->config_model; |
61
|
|
|
|
|
|
|
} |
62
|
|
|
|
|
|
|
elsif ($self->{meta_instance}) { |
63
|
0
|
|
|
|
|
0
|
return $self->meta_instance->config_model; |
64
|
|
|
|
|
|
|
} |
65
|
|
|
|
|
|
|
else { |
66
|
0
|
|
|
|
|
0
|
return Config::Model -> new ( ) ; |
67
|
|
|
|
|
|
|
} |
68
|
|
|
|
|
|
|
} |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
has check => (is =>'ro', isa => 'Bool', default => 1) ; |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
has 'meta_instance' => ( |
73
|
|
|
|
|
|
|
is =>'ro', |
74
|
|
|
|
|
|
|
isa =>'Config::Model::Instance', |
75
|
|
|
|
|
|
|
lazy_build => 1, |
76
|
|
|
|
|
|
|
) ; |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
sub _build_meta_instance { |
79
|
0
|
|
|
0
|
|
0
|
my $self = shift; |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
# don't trigger builders below |
82
|
0
|
0
|
|
|
|
0
|
if ($self->{meta_root}) { |
83
|
0
|
|
|
|
|
0
|
return $self->meta_root->instance; |
84
|
|
|
|
|
|
|
} |
85
|
|
|
|
|
|
|
else { |
86
|
|
|
|
|
|
|
# load Config::Model model |
87
|
0
|
|
|
|
|
0
|
return $self->config_model->instance ( |
88
|
|
|
|
|
|
|
root_class_name => 'Itself::Model' , |
89
|
|
|
|
|
|
|
instance_name => 'meta_model' , |
90
|
|
|
|
|
|
|
check => $self->check, |
91
|
|
|
|
|
|
|
); |
92
|
|
|
|
|
|
|
} |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
} |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
has meta_root => ( |
97
|
|
|
|
|
|
|
is =>'ro', |
98
|
|
|
|
|
|
|
isa =>'Config::Model::Node', |
99
|
|
|
|
|
|
|
lazy_build => 1, |
100
|
|
|
|
|
|
|
) ; |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
sub _build_meta_root { |
103
|
0
|
|
|
0
|
|
0
|
my $self = shift; |
104
|
|
|
|
|
|
|
|
105
|
0
|
|
|
|
|
0
|
return $self->meta_instance -> config_root ; |
106
|
|
|
|
|
|
|
} |
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
has cm_lib_dir => ( |
109
|
|
|
|
|
|
|
is =>'ro', |
110
|
|
|
|
|
|
|
isa => 'ModelPathTiny', |
111
|
|
|
|
|
|
|
lazy_build => 1, |
112
|
|
|
|
|
|
|
coerce => 1 |
113
|
|
|
|
|
|
|
) ; |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
sub _build_cm_lib_dir { |
116
|
0
|
|
|
0
|
|
0
|
my $self = shift; |
117
|
0
|
|
|
|
|
0
|
my $p = path('lib/Config/Model'); |
118
|
0
|
0
|
|
|
|
0
|
if (! $p->is_dir) { |
119
|
0
|
0
|
|
|
|
0
|
$p->mkpath(0, 0755) || die "can't create $p:$!"; |
120
|
|
|
|
|
|
|
} |
121
|
0
|
|
|
|
|
0
|
return $p; |
122
|
|
|
|
|
|
|
} |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
has force_write => (is =>'ro', isa => 'Bool', default => 0) ; |
125
|
|
|
|
|
|
|
has root_model => (is =>'ro', isa => 'str'); |
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
has modified_classes => ( |
128
|
|
|
|
|
|
|
is =>'rw', |
129
|
|
|
|
|
|
|
isa =>'HashRef[Bool]', |
130
|
|
|
|
|
|
|
traits => ['Hash'], |
131
|
|
|
|
|
|
|
default => sub { {} } , |
132
|
|
|
|
|
|
|
handles => { |
133
|
|
|
|
|
|
|
clear_classes => 'clear', |
134
|
|
|
|
|
|
|
set_class => 'set', |
135
|
|
|
|
|
|
|
class_was_changed => 'get' , |
136
|
|
|
|
|
|
|
class_known => 'exists', |
137
|
|
|
|
|
|
|
} |
138
|
|
|
|
|
|
|
) ; |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
has model_dir => ( |
141
|
|
|
|
|
|
|
is => 'ro', |
142
|
|
|
|
|
|
|
isa => 'ModelPathTiny', |
143
|
|
|
|
|
|
|
lazy_build => 1, |
144
|
|
|
|
|
|
|
); |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
sub _build_model_dir { |
147
|
9
|
|
|
9
|
|
20
|
my $self = shift; |
148
|
9
|
|
|
|
|
55
|
my $md = $self->cm_lib_dir->child('models'); |
149
|
9
|
|
|
|
|
366
|
$md->mkpath; |
150
|
9
|
|
|
|
|
1273
|
return $md; |
151
|
|
|
|
|
|
|
} |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
sub BUILD { |
154
|
9
|
|
|
9
|
1
|
27
|
my $self = shift; |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
my $cb = sub { |
157
|
3911
|
|
|
3911
|
|
49560106
|
my %args = @_ ; |
158
|
3911
|
|
50
|
|
|
13351
|
my $p = $args{path} || '' ; |
159
|
3911
|
100
|
|
|
|
18234
|
return unless $p =~ /^class/ ; |
160
|
3908
|
50
|
|
|
|
9476
|
return unless $args{index}; # may be empty when class order is changed |
161
|
3908
|
100
|
|
|
|
13370
|
return if $self->class_was_changed($args{index}) ; |
162
|
859
|
|
|
|
|
15266
|
$logger->info("class $args{index} was modified"); |
163
|
|
|
|
|
|
|
|
164
|
859
|
|
|
|
|
8771
|
$self->add_modified_class($args{index}) ; |
165
|
9
|
|
|
|
|
51
|
} ; |
166
|
9
|
|
|
|
|
97
|
$self->meta_instance -> on_change_cb($cb) ; |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
} |
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
sub add_tracked_class { |
171
|
123
|
|
|
123
|
0
|
210
|
my $self = shift; |
172
|
123
|
|
|
|
|
359
|
$self->set_class(shift,0) ; |
173
|
|
|
|
|
|
|
} |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
sub add_modified_class { |
176
|
982
|
|
|
982
|
0
|
7773
|
my $self = shift; |
177
|
982
|
|
|
|
|
3286
|
$self->set_class(shift,1) ; |
178
|
|
|
|
|
|
|
} |
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
sub class_needs_write { |
181
|
65
|
|
|
65
|
0
|
162
|
my $self = shift; |
182
|
65
|
|
|
|
|
151
|
my $name = shift; |
183
|
65
|
|
66
|
|
|
731
|
return ($self->force_write or not $self->class_known($name) or $self->class_was_changed($name)) ; |
184
|
|
|
|
|
|
|
} |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
sub read_app_files { |
187
|
7
|
|
|
7
|
0
|
17
|
my $self = shift; |
188
|
7
|
|
100
|
|
|
30
|
my $force_load = shift || 0; |
189
|
7
|
|
|
|
|
16
|
my $read_from = shift ; |
190
|
7
|
|
|
|
|
31
|
my $application = shift ; |
191
|
|
|
|
|
|
|
|
192
|
7
|
|
33
|
|
|
69
|
my $app_dir = $read_from || $self->model_dir->parent; |
193
|
7
|
|
|
|
|
553
|
my %apps; |
194
|
7
|
|
|
|
|
29
|
$logger->info("reading app files from ".$app_dir); |
195
|
7
|
|
|
|
|
131
|
foreach my $dir ( $app_dir->children(qr/\.d$/) ) { |
196
|
|
|
|
|
|
|
|
197
|
3
|
|
|
|
|
391
|
$logger->info("reading app dir ".$dir); |
198
|
3
|
|
|
|
|
43
|
foreach my $file ( $dir->children() ) { |
199
|
3
|
50
|
|
|
|
252
|
next if $file =~ m!/README!; |
200
|
3
|
50
|
|
|
|
25
|
next if $file =~ /(~|\.bak|\.orig)$/; |
201
|
3
|
50
|
33
|
|
|
29
|
next if $application and $file->basename ne $application; |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
# bad categories are filtered by the model |
204
|
3
|
|
|
|
|
15
|
my %data = ( category => $dir->basename('.d') ); |
205
|
3
|
|
|
|
|
219
|
$logger->info("reading app file ".$file); |
206
|
|
|
|
|
|
|
|
207
|
3
|
|
|
|
|
100
|
foreach ($file->lines({ chomp => 1})) { |
208
|
6
|
|
|
|
|
572
|
s/^\s+//; |
209
|
6
|
|
|
|
|
21
|
s/\s+$//; |
210
|
6
|
|
|
|
|
14
|
s/#.*//; |
211
|
6
|
|
|
|
|
30
|
my ( $k, $v ) = split /\s*=\s*/; |
212
|
6
|
50
|
|
|
|
19
|
next unless $v; |
213
|
6
|
|
|
|
|
19
|
$data{$k} = $v; |
214
|
|
|
|
|
|
|
} |
215
|
|
|
|
|
|
|
|
216
|
3
|
|
|
|
|
16
|
my $appli = $file->basename; |
217
|
3
|
|
|
|
|
77
|
$apps{$appli} = $data{model} ; |
218
|
|
|
|
|
|
|
|
219
|
3
|
50
|
|
|
|
88
|
$self->meta_root->load_data( |
220
|
|
|
|
|
|
|
data => { application => { $appli => \%data } }, |
221
|
|
|
|
|
|
|
check => $force_load ? 'no' : 'yes' |
222
|
|
|
|
|
|
|
) ; |
223
|
|
|
|
|
|
|
} |
224
|
|
|
|
|
|
|
} |
225
|
|
|
|
|
|
|
|
226
|
7
|
|
|
|
|
150801
|
return \%apps; |
227
|
|
|
|
|
|
|
} |
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
sub read_all { |
230
|
7
|
|
|
7
|
0
|
93
|
my $self = shift ; |
231
|
7
|
|
|
|
|
28
|
my %args = @_ ; |
232
|
|
|
|
|
|
|
|
233
|
7
|
|
100
|
|
|
48
|
my $force_load = delete $args{force_load} || 0 ; |
234
|
7
|
|
|
|
|
17
|
my $read_from ; |
235
|
|
|
|
|
|
|
my $model_dir ; |
236
|
7
|
50
|
|
|
|
33
|
if ($args{read_from}) { |
237
|
0
|
|
|
|
|
0
|
$read_from = path (delete $args{read_from}); |
238
|
0
|
0
|
|
|
|
0
|
die "Cannot read from unknown dir ".$read_from unless $read_from->is_dir; |
239
|
0
|
|
|
|
|
0
|
$model_dir = $read_from->child('models'); |
240
|
0
|
0
|
|
|
|
0
|
die "Cannot read from unknown dir ".$model_dir unless $model_dir->is_dir; |
241
|
|
|
|
|
|
|
} |
242
|
|
|
|
|
|
|
|
243
|
7
|
|
|
|
|
34
|
my $apps = $self-> read_app_files($force_load, $read_from, delete $args{application}); |
244
|
|
|
|
|
|
|
|
245
|
7
|
|
50
|
|
|
39
|
my $root_model_arg = delete $args{root_model} || ''; |
246
|
7
|
|
33
|
|
|
45
|
my $model = $apps->{$root_model_arg} || $root_model_arg ; |
247
|
7
|
|
|
|
|
20
|
my $legacy = delete $args{legacy} ; |
248
|
|
|
|
|
|
|
|
249
|
7
|
50
|
|
|
|
68
|
croak "read_all: unexpected parameters ",join(' ', keys %args) if %args ; |
250
|
|
|
|
|
|
|
|
251
|
7
|
|
|
|
|
37
|
my $dir = $self->model_dir; |
252
|
7
|
|
|
|
|
38
|
$dir->mkpath ; |
253
|
|
|
|
|
|
|
|
254
|
7
|
|
|
|
|
522
|
my $root_model_file = $model ; |
255
|
7
|
|
|
|
|
24
|
$root_model_file =~ s!::!/!g ; |
256
|
7
|
|
33
|
|
|
69
|
my $read_dir = $model_dir || $dir; |
257
|
7
|
|
|
|
|
31
|
$logger->info("searching model files in ".$read_dir); |
258
|
|
|
|
|
|
|
|
259
|
7
|
|
|
|
|
109
|
my @files ; |
260
|
|
|
|
|
|
|
my $wanted = sub { |
261
|
103
|
50
|
100
|
103
|
|
10955
|
push @files, $_ if ( $_->is_file and /\.pl$/ |
|
|
|
66
|
|
|
|
|
|
|
|
66
|
|
|
|
|
262
|
|
|
|
|
|
|
and m!$read_dir/$root_model_file\b! |
263
|
|
|
|
|
|
|
and not m!\.d/! |
264
|
|
|
|
|
|
|
) ; |
265
|
7
|
|
|
|
|
41
|
} ; |
266
|
7
|
|
|
|
|
57
|
$read_dir->visit($wanted, { recurse => 1} ) ; |
267
|
|
|
|
|
|
|
|
268
|
7
|
|
|
|
|
398
|
my $i = $self->meta_instance ; |
269
|
|
|
|
|
|
|
|
270
|
7
|
|
|
|
|
44
|
my %read_models ; |
271
|
|
|
|
|
|
|
my %pod_data ; |
272
|
7
|
|
|
|
|
0
|
my %class_file_map ; |
273
|
|
|
|
|
|
|
|
274
|
7
|
|
|
|
|
0
|
my @all_models; |
275
|
7
|
|
|
|
|
22
|
for my $file (@files) { |
276
|
63
|
|
|
|
|
296
|
$logger->info("loading config file $file"); |
277
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
# now apply some translation to read model |
279
|
|
|
|
|
|
|
# - translate legacy warp parameters |
280
|
|
|
|
|
|
|
# - expand elements name |
281
|
63
|
100
|
|
|
|
927
|
my @legacy = $legacy ? ( legacy => $legacy ) : () ; |
282
|
63
|
|
|
|
|
562
|
my $tmp_model = Config::Model -> new( skip_include => 1, @legacy ) ; |
283
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
# @models order is important to write configuration class back in the same |
285
|
|
|
|
|
|
|
# order as the declaration |
286
|
63
|
|
|
|
|
14169
|
my @models = $tmp_model -> load ( 'Tmp' , $file->absolute ) ; |
287
|
63
|
|
|
|
|
254544
|
push @all_models, @models; |
288
|
|
|
|
|
|
|
|
289
|
63
|
|
|
|
|
147
|
my $rel_file = $file ; |
290
|
63
|
|
|
|
|
303
|
$rel_file =~ s/^$read_dir\/?//; |
291
|
63
|
50
|
|
|
|
1079
|
die "wrong reg_exp" if $file eq $rel_file ; |
292
|
63
|
|
|
|
|
426
|
$class_file_map{$rel_file} = \@models ; |
293
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
# - move experience, description and level status into parameter info. |
295
|
63
|
|
|
|
|
147
|
foreach my $model_name (@models) { |
296
|
|
|
|
|
|
|
# no need to dclone model as Config::Model object is temporary |
297
|
123
|
|
|
|
|
482
|
my $raw_model = $tmp_model -> get_raw_model( $model_name ) ; |
298
|
123
|
|
|
|
|
2192
|
my $new_model = $tmp_model -> get_model( $model_name ) ; |
299
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
# track read class to identify later classes added by user |
301
|
123
|
|
|
|
|
26712
|
$self->add_tracked_class($model_name); |
302
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
# some modifications may be done to cope with older model styles. If a modif |
304
|
|
|
|
|
|
|
# was done, mark the class as changed so it will be saved later |
305
|
123
|
50
|
|
|
|
5123
|
$self->add_modified_class($model_name) unless Compare($raw_model, $new_model) ; |
306
|
|
|
|
|
|
|
|
307
|
123
|
|
|
|
|
4565
|
foreach my $item (qw/description summary level experience status/) { |
308
|
615
|
|
|
|
|
846
|
foreach my $elt_name (keys %{$new_model->{element}}) { |
|
615
|
|
|
|
|
1420
|
|
309
|
3825
|
|
|
|
|
5752
|
my $moved_data = delete $new_model->{$item}{$elt_name} ; |
310
|
3825
|
50
|
|
|
|
7633
|
next unless defined $moved_data ; |
311
|
0
|
|
|
|
|
0
|
$new_model->{element}{$elt_name}{$item} = $moved_data ; |
312
|
|
|
|
|
|
|
} |
313
|
615
|
|
|
|
|
1248
|
delete $new_model->{$item} ; |
314
|
|
|
|
|
|
|
} |
315
|
|
|
|
|
|
|
|
316
|
|
|
|
|
|
|
# Since accept specs and elements are stored in a ordered hash, |
317
|
|
|
|
|
|
|
# load_data expects a array ref instead of a hash ref. |
318
|
|
|
|
|
|
|
# Build this array ref taking the order into |
319
|
|
|
|
|
|
|
# account |
320
|
123
|
|
|
|
|
221
|
foreach my $what (qw/element accept/) { |
321
|
246
|
|
|
|
|
508
|
my $list = delete $new_model -> {$what.'_list'} ; |
322
|
246
|
|
|
|
|
419
|
my $h = delete $new_model -> {$what} ; |
323
|
246
|
|
|
|
|
441
|
$new_model -> {$what} = [] ; |
324
|
|
|
|
|
|
|
map { |
325
|
246
|
|
|
|
|
521
|
push @{$new_model->{$what}}, $_, $h->{$_} |
|
771
|
|
|
|
|
1046
|
|
|
771
|
|
|
|
|
1923
|
|
326
|
|
|
|
|
|
|
} @$list ; |
327
|
|
|
|
|
|
|
} |
328
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
# remove hash key with undefined values |
330
|
123
|
|
|
|
|
374
|
map { delete $new_model->{$_} unless defined $new_model->{$_} |
331
|
354
|
50
|
33
|
|
|
1778
|
and $new_model->{$_} ne '' |
332
|
|
|
|
|
|
|
} keys %$new_model ; |
333
|
123
|
|
|
|
|
3261
|
$read_models{$model_name} = $new_model ; |
334
|
|
|
|
|
|
|
} |
335
|
|
|
|
|
|
|
|
336
|
|
|
|
|
|
|
} |
337
|
|
|
|
|
|
|
|
338
|
7
|
|
33
|
|
|
88
|
$self->{root_model} = $model || (sort @all_models)[0]; |
339
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
# Create all classes listed in %read_models to avoid problems with |
341
|
|
|
|
|
|
|
# include statement while calling load_data |
342
|
7
|
|
|
|
|
38
|
my $root_obj = $self->meta_root ; |
343
|
7
|
|
|
|
|
54
|
my $class_element = $root_obj->fetch_element('class') ; |
344
|
7
|
|
|
|
|
100875
|
map { $class_element->fetch_with_id($_) } sort keys %read_models ; |
|
123
|
|
|
|
|
146779
|
|
345
|
|
|
|
|
|
|
|
346
|
|
|
|
|
|
|
#require Tk::ObjScanner; Tk::ObjScanner::scan_object(\%read_models) ; |
347
|
|
|
|
|
|
|
|
348
|
7
|
|
|
|
|
5554
|
$logger->info("loading all extracted data in Config::Model::Itself"); |
349
|
|
|
|
|
|
|
# load with a array ref to avoid warnings about missing order |
350
|
7
|
100
|
|
|
|
172
|
$root_obj->load_data( |
351
|
|
|
|
|
|
|
data => {class => [ %read_models ] }, |
352
|
|
|
|
|
|
|
check => $force_load ? 'no' : 'yes' |
353
|
|
|
|
|
|
|
) ; |
354
|
|
|
|
|
|
|
|
355
|
|
|
|
|
|
|
# load annotations and comment header |
356
|
7
|
|
|
|
|
73688
|
for my $file (@files) { |
357
|
63
|
|
|
|
|
260
|
$logger->info("loading annotations from file $file"); |
358
|
63
|
|
50
|
|
|
1025
|
my $fh = IO::File->new($file) || die "Can't open $file: $!" ; |
359
|
63
|
|
|
|
|
6076
|
my @lines = $fh->getlines ; |
360
|
63
|
|
|
|
|
7872
|
$fh->close; |
361
|
63
|
|
|
|
|
2225
|
$root_obj->load_pod_annotation(join('',@lines)) ; |
362
|
|
|
|
|
|
|
|
363
|
63
|
|
|
|
|
69385
|
my @headers ; |
364
|
63
|
|
|
|
|
155
|
foreach my $l (@lines) { |
365
|
981
|
100
|
100
|
|
|
3319
|
if ($l =~ /^\s*#/ or $l =~ /^\s*$/){ |
366
|
918
|
|
|
|
|
1743
|
push @headers, $l |
367
|
|
|
|
|
|
|
} |
368
|
|
|
|
|
|
|
else { |
369
|
63
|
|
|
|
|
114
|
last; |
370
|
|
|
|
|
|
|
} |
371
|
|
|
|
|
|
|
} |
372
|
63
|
|
|
|
|
123
|
my $rel_file = $file ; |
373
|
63
|
|
|
|
|
296
|
$rel_file =~ s/^$dir\/?//; |
374
|
63
|
|
|
|
|
1663
|
$self->{header}{$rel_file} = \@headers; |
375
|
|
|
|
|
|
|
} |
376
|
|
|
|
|
|
|
|
377
|
7
|
|
|
|
|
1824
|
return $self->{map} = \%class_file_map ; |
378
|
|
|
|
|
|
|
} |
379
|
|
|
|
|
|
|
|
380
|
|
|
|
|
|
|
# internal |
381
|
|
|
|
|
|
|
sub get_perl_data_model{ |
382
|
66
|
|
|
66
|
0
|
2192776
|
my $self = shift ; |
383
|
66
|
|
|
|
|
287
|
my %args = @_ ; |
384
|
66
|
|
|
|
|
202
|
my $root_obj = $self->{meta_root}; |
385
|
|
|
|
|
|
|
my $class_name = $args{class_name} |
386
|
66
|
|
33
|
|
|
285
|
|| croak __PACKAGE__," read: undefined class name"; |
387
|
|
|
|
|
|
|
|
388
|
66
|
|
|
|
|
281
|
my $class_element = $root_obj->fetch_element('class') ; |
389
|
|
|
|
|
|
|
|
390
|
|
|
|
|
|
|
# skip if class was deleted during edition |
391
|
66
|
50
|
|
|
|
4335
|
return unless $class_element->defined($class_name) ; |
392
|
|
|
|
|
|
|
|
393
|
66
|
|
|
|
|
1155
|
my $class_elt = $class_element -> fetch_with_id($class_name) ; |
394
|
|
|
|
|
|
|
|
395
|
66
|
|
|
|
|
3973
|
my $model = $class_elt->dump_as_data ; |
396
|
|
|
|
|
|
|
|
397
|
|
|
|
|
|
|
# now apply some translation to read model |
398
|
|
|
|
|
|
|
# - Do NOT translate legacy warp parameters |
399
|
|
|
|
|
|
|
# - Do not compact elements name |
400
|
|
|
|
|
|
|
|
401
|
|
|
|
|
|
|
# don't forget to add name |
402
|
66
|
50
|
|
|
|
5815678
|
$model->{name} = $class_name if keys %$model; |
403
|
|
|
|
|
|
|
|
404
|
66
|
|
|
|
|
381
|
return $model ; |
405
|
|
|
|
|
|
|
} |
406
|
|
|
|
|
|
|
|
407
|
|
|
|
|
|
|
sub write_app_files { |
408
|
4
|
|
|
4
|
0
|
9
|
my $self = shift; |
409
|
|
|
|
|
|
|
|
410
|
4
|
|
|
|
|
18
|
my $app_dir = $self->cm_lib_dir; |
411
|
4
|
|
|
|
|
20
|
my $app_obj = $self->meta_root->fetch_element('application'); |
412
|
|
|
|
|
|
|
|
413
|
4
|
|
|
|
|
575
|
foreach my $app_name ( $app_obj->fetch_all_indexes ) { |
414
|
2
|
|
|
|
|
56
|
my $app = $app_obj->fetch_with_id($app_name); |
415
|
2
|
|
|
|
|
105
|
my $cat_dir_name = $app->fetch_element_value( name =>'category' ).'.d'; |
416
|
2
|
|
|
|
|
607
|
$app_dir->child($cat_dir_name)->mkpath(); |
417
|
2
|
|
|
|
|
638
|
my $app_file = $app_dir->child($cat_dir_name)->child($app->index_value) ; |
418
|
|
|
|
|
|
|
|
419
|
2
|
|
|
|
|
129
|
my @lines ; |
420
|
2
|
|
|
|
|
11
|
foreach my $name ( $app->children ) { |
421
|
20
|
100
|
|
|
|
439
|
next if $name eq 'category'; # saved as directory above |
422
|
|
|
|
|
|
|
|
423
|
18
|
|
|
|
|
57
|
my $v = $app->fetch_element_value($name); # need to spit out 0 ? |
424
|
18
|
100
|
|
|
|
10172
|
next unless defined $v; |
425
|
4
|
|
|
|
|
18
|
push @lines, "$name = $v\n"; |
426
|
|
|
|
|
|
|
|
427
|
|
|
|
|
|
|
} |
428
|
2
|
|
|
|
|
20
|
$logger->info("writing file ".$app_file); |
429
|
2
|
|
|
|
|
64
|
$app_file->spew(@lines); |
430
|
|
|
|
|
|
|
} |
431
|
|
|
|
|
|
|
|
432
|
|
|
|
|
|
|
} |
433
|
|
|
|
|
|
|
|
434
|
|
|
|
|
|
|
sub write_all { |
435
|
4
|
|
|
4
|
1
|
1991637
|
my $self = shift ; |
436
|
4
|
|
|
|
|
14
|
my %args = @_ ; |
437
|
4
|
|
|
|
|
19
|
my $root_obj = $self->meta_root ; |
438
|
4
|
|
|
|
|
29
|
my $dir = $self->model_dir ; |
439
|
|
|
|
|
|
|
|
440
|
4
|
50
|
|
|
|
23
|
croak "write_all: unexpected parameters ",join(' ', keys %args) if %args ; |
441
|
|
|
|
|
|
|
|
442
|
4
|
|
|
|
|
24
|
$self->write_app_files; |
443
|
|
|
|
|
|
|
|
444
|
4
|
|
|
|
|
1220
|
my $map = $self->{map} ; |
445
|
|
|
|
|
|
|
|
446
|
4
|
|
|
|
|
40
|
$dir->mkpath; |
447
|
|
|
|
|
|
|
|
448
|
|
|
|
|
|
|
# get list of all classes loaded by the editor |
449
|
|
|
|
|
|
|
my %loaded_classes |
450
|
4
|
|
|
|
|
270
|
= map { ($_ => 1); } |
|
65
|
|
|
|
|
438
|
|
451
|
|
|
|
|
|
|
$root_obj->fetch_element('class')->fetch_all_indexes ; |
452
|
|
|
|
|
|
|
|
453
|
|
|
|
|
|
|
# remove classes that are listed in map |
454
|
4
|
|
|
|
|
28
|
foreach my $file (keys %$map) { |
455
|
20
|
|
|
|
|
31
|
foreach my $class_name (@{$map->{$file}}) { |
|
20
|
|
|
|
|
44
|
|
456
|
40
|
|
|
|
|
83
|
delete $loaded_classes{$class_name} ; |
457
|
|
|
|
|
|
|
} |
458
|
|
|
|
|
|
|
} |
459
|
|
|
|
|
|
|
|
460
|
|
|
|
|
|
|
# add remaining classes in map |
461
|
|
|
|
|
|
|
my %new_map = map { |
462
|
4
|
|
|
|
|
15
|
my $f = $_; |
|
25
|
|
|
|
|
38
|
|
463
|
25
|
|
|
|
|
61
|
$f =~ s!::!/!g; |
464
|
25
|
|
|
|
|
81
|
("$f.pl" => [ $_ ]) ; |
465
|
|
|
|
|
|
|
} keys %loaded_classes ; |
466
|
|
|
|
|
|
|
|
467
|
4
|
|
|
|
|
32
|
my %map_to_write = (%$map,%new_map) ; |
468
|
|
|
|
|
|
|
|
469
|
4
|
|
|
|
|
19
|
foreach my $file (keys %map_to_write) { |
470
|
45
|
|
|
|
|
8455
|
$logger->info("checking model file $file"); |
471
|
|
|
|
|
|
|
|
472
|
45
|
|
|
|
|
525
|
my @data ; |
473
|
|
|
|
|
|
|
my @notes ; |
474
|
45
|
|
|
|
|
153
|
my $file_needs_write = 0; |
475
|
|
|
|
|
|
|
|
476
|
|
|
|
|
|
|
# check if any a class of a file was modified |
477
|
45
|
|
|
|
|
113
|
foreach my $class_name (@{$map_to_write{$file}}) { |
|
45
|
|
|
|
|
364
|
|
478
|
65
|
50
|
|
|
|
412
|
$file_needs_write++ if $self->class_needs_write($class_name); |
479
|
65
|
|
|
|
|
1543
|
$logger->info("file $file class $class_name needs write ",$file_needs_write); |
480
|
|
|
|
|
|
|
} |
481
|
|
|
|
|
|
|
|
482
|
45
|
50
|
|
|
|
554
|
next unless $file_needs_write ; |
483
|
|
|
|
|
|
|
|
484
|
45
|
|
|
|
|
105
|
foreach my $class_name (@{$map_to_write{$file}}) { |
|
45
|
|
|
|
|
140
|
|
485
|
65
|
|
|
|
|
356
|
$logger->info("writing class $class_name"); |
486
|
65
|
|
|
|
|
768
|
my $model |
487
|
|
|
|
|
|
|
= $self-> get_perl_data_model(class_name => $class_name) ; |
488
|
65
|
50
|
33
|
|
|
681
|
push @data, $model if defined $model and keys %$model; |
489
|
|
|
|
|
|
|
|
490
|
65
|
|
|
|
|
615
|
my $node = $self->{meta_root}->grab("class:".$class_name) ; |
491
|
65
|
|
|
|
|
27463
|
push @notes, $node->dump_annotations_as_pod ; |
492
|
|
|
|
|
|
|
# remove class name from above list |
493
|
65
|
|
|
|
|
4164496
|
delete $loaded_classes{$class_name} ; |
494
|
|
|
|
|
|
|
} |
495
|
|
|
|
|
|
|
|
496
|
45
|
50
|
|
|
|
265
|
next unless @data ; # don't write empty model |
497
|
|
|
|
|
|
|
|
498
|
45
|
|
|
|
|
376
|
write_model_file ($dir->child($file), $self->{header}{$file}, \@notes, \@data); |
499
|
|
|
|
|
|
|
} |
500
|
|
|
|
|
|
|
|
501
|
4
|
|
|
|
|
538
|
$self->meta_instance->clear_changes ; |
502
|
|
|
|
|
|
|
} |
503
|
|
|
|
|
|
|
|
504
|
|
|
|
|
|
|
sub write_model_plugin { |
505
|
2
|
|
|
2
|
1
|
2398
|
my $self = shift ; |
506
|
2
|
|
|
|
|
8
|
my %args = @_ ; |
507
|
|
|
|
|
|
|
my $plugin_dir = delete $args{plugin_dir} |
508
|
2
|
|
33
|
|
|
9
|
|| croak __PACKAGE__," write_model_plugin: undefined plugin_dir"; |
509
|
|
|
|
|
|
|
my $plugin_name = delete $args{plugin_name} |
510
|
2
|
|
33
|
|
|
8
|
|| croak __PACKAGE__," write_model_plugin: undefined plugin_name"; |
511
|
2
|
50
|
|
|
|
8
|
croak "write_model_plugin: unexpected parameters ",join(' ', keys %args) if %args ; |
512
|
|
|
|
|
|
|
|
513
|
2
|
|
|
|
|
18
|
my $model = $self->meta_root->dump_as_data(mode => 'custom') ; |
514
|
|
|
|
|
|
|
# print (Dumper( $model)) ; |
515
|
|
|
|
|
|
|
|
516
|
2
|
50
|
|
|
|
27829135
|
my @raw_data = @{$model->{class} || []} ; |
|
2
|
|
|
|
|
16
|
|
517
|
2
|
|
|
|
|
8
|
while (@raw_data) { |
518
|
4
|
|
|
|
|
219
|
my ( $class , $data ) = splice @raw_data,0,2 ; |
519
|
4
|
|
|
|
|
12
|
$data ->{name} = $class ; |
520
|
|
|
|
|
|
|
|
521
|
|
|
|
|
|
|
# does not distinguish between notes from underlying model or snipper notes ... |
522
|
4
|
|
|
|
|
43
|
my @notes = $self->meta_root->grab("class:$class")->dump_annotations_as_pod ; |
523
|
4
|
|
|
|
|
752058
|
my $plugin_file = $class.'.pl'; |
524
|
4
|
|
|
|
|
21
|
$plugin_file =~ s!::!/!g; |
525
|
4
|
|
|
|
|
27
|
write_model_file ("$plugin_dir/$plugin_name/$plugin_file", [], \@notes, [ $data ]); |
526
|
|
|
|
|
|
|
} |
527
|
|
|
|
|
|
|
|
528
|
2
|
|
|
|
|
177
|
$self->meta_instance->clear_changes ; |
529
|
|
|
|
|
|
|
} |
530
|
|
|
|
|
|
|
|
531
|
|
|
|
|
|
|
sub read_model_plugin { |
532
|
1
|
|
|
1
|
1
|
710
|
my $self = shift ; |
533
|
1
|
|
|
|
|
6
|
my %args = @_ ; |
534
|
|
|
|
|
|
|
my $plugin_dir = delete $args{plugin_dir} |
535
|
1
|
|
33
|
|
|
5
|
|| croak __PACKAGE__," write_model_plugin: undefined plugin_dir"; |
536
|
|
|
|
|
|
|
my $plugin_name = delete $args{plugin_name} |
537
|
1
|
|
33
|
|
|
4
|
|| croak __PACKAGE__," read_model_plugin: undefined plugin_name"; |
538
|
|
|
|
|
|
|
|
539
|
1
|
50
|
|
|
|
4
|
croak "read_model_plugin: unexpected parameters ",join(' ', keys %args) if %args ; |
540
|
|
|
|
|
|
|
|
541
|
1
|
|
|
|
|
2
|
my @files ; |
542
|
|
|
|
|
|
|
my $wanted = sub { |
543
|
5
|
|
|
5
|
|
16
|
my $n = $File::Find::name ; |
544
|
5
|
50
|
66
|
|
|
353
|
push @files, $n if (-f $_ and not /~$/ |
|
|
|
66
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
|
33
|
|
|
|
|
545
|
|
|
|
|
|
|
and $n !~ /CVS/ |
546
|
|
|
|
|
|
|
and $n !~ m!.(svn|orig|pod)$! |
547
|
|
|
|
|
|
|
and $n =~ m!\.d/$plugin_name! |
548
|
|
|
|
|
|
|
) ; |
549
|
1
|
|
|
|
|
5
|
} ; |
550
|
1
|
|
|
|
|
82
|
find ($wanted, $plugin_dir ) ; |
551
|
|
|
|
|
|
|
|
552
|
1
|
|
|
|
|
9
|
my $class_element = $self->meta_root->fetch_element('class') ; |
553
|
|
|
|
|
|
|
|
554
|
1
|
|
|
|
|
71
|
foreach my $load_file (@files) { |
555
|
2
|
|
|
|
|
275
|
$logger->info("trying to read plugin $load_file"); |
556
|
|
|
|
|
|
|
|
557
|
2
|
50
|
33
|
|
|
46
|
$load_file = "./$load_file" if $load_file !~ m!^/! and -e $load_file; |
558
|
|
|
|
|
|
|
|
559
|
2
|
|
|
|
|
660
|
my $plugin = do $load_file ; |
560
|
|
|
|
|
|
|
|
561
|
2
|
50
|
|
|
|
10
|
unless ($plugin) { |
562
|
0
|
0
|
|
|
|
0
|
if ($@) {die "couldn't parse $load_file: $@"; } |
|
0
|
0
|
|
|
|
0
|
|
563
|
0
|
|
|
|
|
0
|
elsif (not defined $plugin) {die "couldn't do $load_file: $!"} |
564
|
0
|
|
|
|
|
0
|
else { die "couldn't run $load_file" ;} |
565
|
|
|
|
|
|
|
} |
566
|
|
|
|
|
|
|
|
567
|
|
|
|
|
|
|
# there should be only only class in each plugin file |
568
|
2
|
|
|
|
|
6
|
foreach my $model (@$plugin) { |
569
|
2
|
|
|
|
|
5
|
my $class_name = delete $model->{name} ; |
570
|
|
|
|
|
|
|
# load with a array ref to avoid warnings about missing order |
571
|
2
|
|
|
|
|
16
|
$class_element->fetch_with_id($class_name)->load_data( $model ) ; |
572
|
|
|
|
|
|
|
} |
573
|
|
|
|
|
|
|
|
574
|
|
|
|
|
|
|
# load annotations |
575
|
2
|
|
|
|
|
2722
|
$logger->info("loading annotations from plugin file $load_file"); |
576
|
2
|
|
50
|
|
|
22
|
my $fh = IO::File->new($load_file) || die "Can't open $load_file: $!" ; |
577
|
2
|
|
|
|
|
164
|
my @lines = $fh->getlines ; |
578
|
2
|
|
|
|
|
109
|
$fh->close; |
579
|
2
|
|
|
|
|
32
|
$self->meta_root->load_pod_annotation(join('',@lines)) ; |
580
|
|
|
|
|
|
|
} |
581
|
|
|
|
|
|
|
} |
582
|
|
|
|
|
|
|
|
583
|
|
|
|
|
|
|
|
584
|
|
|
|
|
|
|
# |
585
|
|
|
|
|
|
|
# New subroutine "write_model_file" extracted - Mon Mar 12 13:38:29 2012. |
586
|
|
|
|
|
|
|
# |
587
|
|
|
|
|
|
|
sub write_model_file { |
588
|
49
|
|
|
49
|
0
|
3373
|
my $wr_file = shift; |
589
|
49
|
|
|
|
|
128
|
my $comments = shift ; |
590
|
49
|
|
|
|
|
111
|
my $notes = shift; |
591
|
49
|
|
|
|
|
112
|
my $data = shift; |
592
|
|
|
|
|
|
|
|
593
|
49
|
|
|
|
|
1020
|
my $wr_dir = dirname($wr_file); |
594
|
49
|
100
|
|
|
|
4619
|
unless ( -d $wr_dir ) { |
595
|
9
|
50
|
|
|
|
1529
|
mkpath( $wr_dir, 0, 0755 ) || die "Can't mkpath $wr_dir:$!"; |
596
|
|
|
|
|
|
|
} |
597
|
|
|
|
|
|
|
|
598
|
49
|
|
33
|
|
|
551
|
my $wr = IO::File->new( $wr_file, '>' ) |
599
|
|
|
|
|
|
|
|| croak "Cannot open file $wr_file:$!" ; |
600
|
49
|
|
|
|
|
10890
|
$logger->info("in $wr_file"); |
601
|
|
|
|
|
|
|
|
602
|
49
|
|
|
|
|
1230
|
my $dumper = Data::Dumper->new( [ \@$data ] ); |
603
|
49
|
|
|
|
|
2231
|
$dumper->Indent(1); # avoid too deep indentation |
604
|
49
|
|
|
|
|
893
|
$dumper->Terse(1); # allow unnamed variables in dump |
605
|
49
|
|
|
|
|
443
|
$dumper->Sortkeys(1); # sort keys in hash |
606
|
|
|
|
|
|
|
|
607
|
49
|
|
|
|
|
453
|
my $dump = $dumper->Dump; |
608
|
|
|
|
|
|
|
|
609
|
|
|
|
|
|
|
# munge pod text embedded in values to avoid spurious pod formatting |
610
|
49
|
|
|
|
|
15921
|
$dump =~ s/\n=/\n'.'=/g; |
611
|
|
|
|
|
|
|
|
612
|
49
|
|
|
|
|
332
|
$wr->print(@$comments) ; |
613
|
49
|
|
|
|
|
795
|
$wr->print( $dump, ";\n\n" ); |
614
|
|
|
|
|
|
|
|
615
|
49
|
|
|
|
|
1491
|
$wr->print( join( "\n", @$notes ) ); |
616
|
|
|
|
|
|
|
|
617
|
49
|
|
|
|
|
459
|
$wr->close; |
618
|
|
|
|
|
|
|
|
619
|
|
|
|
|
|
|
} |
620
|
|
|
|
|
|
|
|
621
|
|
|
|
|
|
|
|
622
|
|
|
|
|
|
|
|
623
|
|
|
|
|
|
|
sub list_class_element { |
624
|
1
|
|
|
1
|
1
|
688
|
my $self = shift ; |
625
|
1
|
|
50
|
|
|
10
|
my $pad = shift || '' ; |
626
|
|
|
|
|
|
|
|
627
|
1
|
|
|
|
|
2
|
my $res = ''; |
628
|
1
|
|
|
|
|
5
|
my $meta_class = $self->{meta_root}->fetch_element('class') ; |
629
|
1
|
|
|
|
|
62
|
foreach my $class_name ($meta_class->fetch_all_indexes ) { |
630
|
20
|
|
|
|
|
104
|
$res .= $self->list_one_class_element($class_name) ; |
631
|
|
|
|
|
|
|
} |
632
|
1
|
|
|
|
|
27
|
return $res ; |
633
|
|
|
|
|
|
|
} |
634
|
|
|
|
|
|
|
|
635
|
|
|
|
|
|
|
sub list_one_class_element { |
636
|
41
|
|
|
41
|
0
|
78
|
my $self = shift ; |
637
|
41
|
|
50
|
|
|
128
|
my $class_name = shift || return '' ; |
638
|
41
|
|
100
|
|
|
151
|
my $pad = shift || '' ; |
639
|
|
|
|
|
|
|
|
640
|
41
|
|
|
|
|
114
|
my $res = $pad."Class: $class_name\n"; |
641
|
41
|
|
|
|
|
141
|
my $meta_class = $self->{meta_root}->fetch_element('class') |
642
|
|
|
|
|
|
|
-> fetch_with_id($class_name) ; |
643
|
|
|
|
|
|
|
|
644
|
41
|
|
|
|
|
4113
|
my @elts = $meta_class->fetch_element('element')->fetch_all_indexes ; |
645
|
|
|
|
|
|
|
|
646
|
41
|
|
|
|
|
3610
|
my @include = $meta_class->fetch_element('include')->fetch_all_values ; |
647
|
41
|
|
|
|
|
66253
|
my $inc_after = $meta_class->grab_value('include_after') ; |
648
|
|
|
|
|
|
|
|
649
|
41
|
100
|
100
|
|
|
113425
|
if (@include and not defined $inc_after) { |
650
|
10
|
|
|
|
|
31
|
map { $res .= $self->list_one_class_element($_,$pad.' ') ;} @include ; |
|
10
|
|
|
|
|
52
|
|
651
|
|
|
|
|
|
|
} |
652
|
|
|
|
|
|
|
|
653
|
41
|
100
|
|
|
|
140
|
return $res unless @elts ; |
654
|
|
|
|
|
|
|
|
655
|
39
|
|
|
|
|
90
|
foreach my $elt_name ( @elts) { |
656
|
394
|
|
|
|
|
1439
|
my $type = $meta_class->grab_value("element:$elt_name type") ; |
657
|
|
|
|
|
|
|
|
658
|
394
|
|
|
|
|
281125
|
$res .= $pad." - $elt_name ($type)\n"; |
659
|
394
|
100
|
100
|
|
|
2016
|
if (@include and defined $inc_after and $inc_after eq $elt_name) { |
|
|
|
100
|
|
|
|
|
660
|
8
|
|
|
|
|
20
|
map { $res .=$self->list_one_class_element($_,$pad.' ') ;} @include ; |
|
11
|
|
|
|
|
56
|
|
661
|
|
|
|
|
|
|
} |
662
|
|
|
|
|
|
|
} |
663
|
39
|
|
|
|
|
364
|
return $res ; |
664
|
|
|
|
|
|
|
} |
665
|
|
|
|
|
|
|
|
666
|
|
|
|
|
|
|
|
667
|
|
|
|
|
|
|
sub get_dot_diagram { |
668
|
1
|
|
|
1
|
1
|
695
|
my $self = shift ; |
669
|
1
|
|
|
|
|
3
|
my $dot = "digraph model {\n" ; |
670
|
|
|
|
|
|
|
|
671
|
1
|
|
|
|
|
9
|
my $meta_class = $self->{meta_root}->fetch_element('class') ; |
672
|
1
|
|
|
|
|
86
|
foreach my $class_name ($meta_class->fetch_all_indexes ) { |
673
|
20
|
|
|
|
|
97
|
my $d_class = $class_name ; |
674
|
20
|
|
|
|
|
85
|
$d_class =~ s/::/__/g; |
675
|
|
|
|
|
|
|
|
676
|
20
|
|
|
|
|
63
|
my $elt_list = ''; |
677
|
20
|
|
|
|
|
53
|
my $use = ''; |
678
|
|
|
|
|
|
|
|
679
|
20
|
|
|
|
|
137
|
my $class_obj = $self->{meta_root}->grab(qq!class:"$class_name"!); |
680
|
20
|
|
|
|
|
7201
|
my @elts = $class_obj ->grab(qq!element!) ->fetch_all_indexes ; |
681
|
20
|
|
|
|
|
6070
|
foreach my $elt_name ( @elts ) { |
682
|
127
|
|
|
|
|
403
|
my $of = ''; |
683
|
127
|
|
|
|
|
822
|
my $elt_obj = $class_obj->grab(qq!element:"$elt_name"!) ; |
684
|
127
|
|
|
|
|
45976
|
my $type = $elt_obj->grab_value("type") ; |
685
|
127
|
100
|
|
|
|
63669
|
if ($type =~ /^list|hash$/) { |
686
|
30
|
|
|
|
|
129
|
my $cargo = $elt_obj->grab("cargo"); |
687
|
30
|
|
|
|
|
8362
|
my $ct = $cargo->grab_value("type") ; |
688
|
30
|
|
|
|
|
15458
|
$of = " of $ct" ; |
689
|
30
|
|
|
|
|
142
|
$use .= $self->scan_used_class($d_class,$elt_name,$cargo); |
690
|
|
|
|
|
|
|
} |
691
|
|
|
|
|
|
|
else { |
692
|
97
|
|
|
|
|
477
|
$use .= $self->scan_used_class($d_class,$elt_name,$elt_obj); |
693
|
|
|
|
|
|
|
} |
694
|
127
|
|
|
|
|
928
|
$elt_list .= "- $elt_name ($type$of)\\n"; |
695
|
|
|
|
|
|
|
} |
696
|
|
|
|
|
|
|
|
697
|
20
|
|
|
|
|
173
|
$dot .= $d_class |
698
|
|
|
|
|
|
|
. qq! [shape=box label="$class_name\\n$elt_list"];\n! |
699
|
|
|
|
|
|
|
. $use . "\n"; |
700
|
|
|
|
|
|
|
|
701
|
20
|
|
|
|
|
89
|
$dot .= $self->scan_includes($class_name, $class_obj) ; |
702
|
|
|
|
|
|
|
} |
703
|
|
|
|
|
|
|
|
704
|
1
|
|
|
|
|
6
|
$dot .="}\n"; |
705
|
|
|
|
|
|
|
|
706
|
1
|
|
|
|
|
7
|
return $dot ; |
707
|
|
|
|
|
|
|
} |
708
|
|
|
|
|
|
|
|
709
|
|
|
|
|
|
|
sub scan_includes { |
710
|
20
|
|
|
20
|
0
|
79
|
my ($self,$class_name, $class_obj) = @_ ; |
711
|
20
|
|
|
|
|
55
|
my $d_class = $class_name ; |
712
|
20
|
|
|
|
|
127
|
$d_class =~ s/::/__/g; |
713
|
|
|
|
|
|
|
|
714
|
20
|
|
|
|
|
109
|
my @includes = $class_obj->grab('include')->fetch_all_values ; |
715
|
20
|
|
|
|
|
46589
|
my $dot = ''; |
716
|
20
|
|
|
|
|
69
|
foreach my $c (@includes) { |
717
|
13
|
|
|
|
|
2938
|
say "$class_name includes $c"; |
718
|
13
|
|
|
|
|
60
|
my $t = $c; |
719
|
13
|
|
|
|
|
89
|
$t =~ s/::/__/g; |
720
|
13
|
|
|
|
|
64
|
$dot.= qq!$d_class -> $t ;\n!; |
721
|
|
|
|
|
|
|
} |
722
|
20
|
|
|
|
|
151
|
return $dot; |
723
|
|
|
|
|
|
|
} |
724
|
|
|
|
|
|
|
|
725
|
|
|
|
|
|
|
sub scan_used_class { |
726
|
127
|
|
|
127
|
0
|
486
|
my ($self,$d_class,$elt_name, $elt_obj) = @_ ; |
727
|
|
|
|
|
|
|
|
728
|
|
|
|
|
|
|
# define leaf call back |
729
|
|
|
|
|
|
|
my $disp_leaf = sub { |
730
|
2950
|
|
|
2950
|
|
20553842
|
my ($scanner, $data_ref, $node,$element_name,$index, $leaf_object) = @_ ; |
731
|
2950
|
100
|
|
|
|
11034
|
return unless $element_name eq 'config_class_name'; |
732
|
27
|
|
|
|
|
112
|
my $v = $leaf_object->fetch; |
733
|
27
|
100
|
|
|
|
58103
|
return unless $v; |
734
|
20
|
|
|
|
|
128
|
$v =~ s/::/__/g; |
735
|
20
|
|
|
|
|
209
|
$$data_ref .= qq!$d_class -> $v ! |
736
|
|
|
|
|
|
|
. qq![ style=dashed, label="$elt_name" ];\n!; |
737
|
127
|
|
|
|
|
761
|
} ; |
738
|
|
|
|
|
|
|
|
739
|
|
|
|
|
|
|
# simple scanner, (print all values) |
740
|
127
|
|
|
|
|
954
|
my $scan = Config::Model::ObjTreeScanner-> new ( |
741
|
|
|
|
|
|
|
leaf_cb => $disp_leaf, # only mandatory parameter |
742
|
|
|
|
|
|
|
) ; |
743
|
|
|
|
|
|
|
|
744
|
127
|
|
|
|
|
24133
|
my $result = '' ; |
745
|
127
|
|
|
|
|
702
|
$scan->scan_node(\$result, $elt_obj) ; |
746
|
127
|
|
|
|
|
69739
|
return $result ; |
747
|
|
|
|
|
|
|
} |
748
|
|
|
|
|
|
|
|
749
|
|
|
|
|
|
|
__PACKAGE__->meta->make_immutable; |
750
|
|
|
|
|
|
|
|
751
|
|
|
|
|
|
|
1; |
752
|
|
|
|
|
|
|
|
753
|
|
|
|
|
|
|
|
754
|
|
|
|
|
|
|
# ABSTRACT: Model editor for Config::Model |
755
|
|
|
|
|
|
|
|
756
|
|
|
|
|
|
|
__END__ |