line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# This line forces correct deployment by some tools. |
2
|
|
|
|
|
|
|
package UR::Object::Type::Initializer; |
3
|
|
|
|
|
|
|
|
4
|
|
|
|
|
|
|
package UR::Object::Type; |
5
|
|
|
|
|
|
|
|
6
|
273
|
|
|
273
|
|
1247
|
use strict; |
|
270
|
|
|
|
|
416
|
|
|
272
|
|
|
|
|
8071
|
|
7
|
272
|
|
|
272
|
|
1043
|
use warnings; |
|
270
|
|
|
|
|
405
|
|
|
270
|
|
|
|
|
9855
|
|
8
|
|
|
|
|
|
|
require UR; |
9
|
|
|
|
|
|
|
|
10
|
274
|
|
|
270
|
|
1087
|
use UR::Util; |
|
271
|
|
|
|
|
381
|
|
|
269
|
|
|
|
|
1584
|
|
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
BEGIN { |
13
|
|
|
|
|
|
|
# Perl 5.10 did not require mro in order to call get_mro but it looks |
14
|
|
|
|
|
|
|
# like that was "fixed" in newer version. |
15
|
268
|
100
|
|
273
|
|
14032
|
if ($^V ge v5.9.5) { |
16
|
268
|
|
|
|
|
15172
|
eval "require mro"; |
17
|
|
|
|
|
|
|
} |
18
|
|
|
|
|
|
|
}; |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
our $VERSION = "0.46"; # UR $VERSION; |
21
|
|
|
|
|
|
|
|
22
|
268
|
|
|
268
|
|
195098
|
use Carp (); |
|
272
|
|
|
|
|
465
|
|
|
269
|
|
|
|
|
3286
|
|
23
|
269
|
|
|
268
|
|
991
|
use Sub::Name (); |
|
269
|
|
|
|
|
370
|
|
|
269
|
|
|
|
|
2969
|
|
24
|
269
|
|
|
271
|
|
870
|
use Sub::Install (); |
|
268
|
|
|
|
|
370
|
|
|
268
|
|
|
|
|
119531
|
|
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
# keys are class property names (like er_role, is_final, etc) and values are |
27
|
|
|
|
|
|
|
# the default value to use if it's not specified in the class definition |
28
|
|
|
|
|
|
|
# |
29
|
|
|
|
|
|
|
# For most classes, this kind of thing is handled by the default_value attribute on |
30
|
|
|
|
|
|
|
# a class' property. For bootstrapping reasons, the default values for the |
31
|
|
|
|
|
|
|
# properties of UR::Object::Type' class need to be listed here as well. If |
32
|
|
|
|
|
|
|
# any of these change, or new default valued items are added, be sure to also |
33
|
|
|
|
|
|
|
# update the class definition for UR::Object::Type (which really lives in UR.pm |
34
|
|
|
|
|
|
|
# for the moment) |
35
|
|
|
|
|
|
|
%UR::Object::Type::defaults = ( |
36
|
|
|
|
|
|
|
er_role => 'entity', |
37
|
|
|
|
|
|
|
is_final => 0, |
38
|
|
|
|
|
|
|
is_singleton => 0, |
39
|
|
|
|
|
|
|
is_transactional => 1, |
40
|
|
|
|
|
|
|
is_mutable => 1, |
41
|
|
|
|
|
|
|
is_many => 0, |
42
|
|
|
|
|
|
|
is_abstract => 0, |
43
|
|
|
|
|
|
|
subclassify_by_version => 0, |
44
|
|
|
|
|
|
|
); |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
# All those same comments also apply to UR::Object::Property's properties |
47
|
|
|
|
|
|
|
%UR::Object::Property::defaults = ( |
48
|
|
|
|
|
|
|
is_optional => 0, |
49
|
|
|
|
|
|
|
is_transient => 0, |
50
|
|
|
|
|
|
|
is_constant => 0, |
51
|
|
|
|
|
|
|
is_volatile => 0, |
52
|
|
|
|
|
|
|
is_classwide => 0, |
53
|
|
|
|
|
|
|
is_delegated => 0, |
54
|
|
|
|
|
|
|
is_calculated => 0, |
55
|
|
|
|
|
|
|
is_mutable => undef, |
56
|
|
|
|
|
|
|
is_transactional => 1, |
57
|
|
|
|
|
|
|
is_many => 0, |
58
|
|
|
|
|
|
|
is_numeric => 0, |
59
|
|
|
|
|
|
|
is_specified_in_module_header => 0, |
60
|
|
|
|
|
|
|
is_deprecated => 0, |
61
|
|
|
|
|
|
|
position_in_module_header => -1, |
62
|
|
|
|
|
|
|
doc_position => -1, |
63
|
|
|
|
|
|
|
is_undocumented => 0, |
64
|
|
|
|
|
|
|
); |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
@UR::Object::Type::meta_id_ref_shared_properties = ( |
67
|
|
|
|
|
|
|
qw/ |
68
|
|
|
|
|
|
|
is_optional |
69
|
|
|
|
|
|
|
is_transient |
70
|
|
|
|
|
|
|
is_constant |
71
|
|
|
|
|
|
|
is_volatile |
72
|
|
|
|
|
|
|
is_classwide |
73
|
|
|
|
|
|
|
is_transactional |
74
|
|
|
|
|
|
|
is_abstract |
75
|
|
|
|
|
|
|
is_concrete |
76
|
|
|
|
|
|
|
is_final |
77
|
|
|
|
|
|
|
is_many |
78
|
|
|
|
|
|
|
is_deprecated |
79
|
|
|
|
|
|
|
is_undocumented |
80
|
|
|
|
|
|
|
/ |
81
|
|
|
|
|
|
|
); |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
%UR::Object::Type::converse = ( |
84
|
|
|
|
|
|
|
required => 'optional', |
85
|
|
|
|
|
|
|
abstract => 'concrete', |
86
|
|
|
|
|
|
|
one => 'many', |
87
|
|
|
|
|
|
|
); |
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
# These classes are used to define an object class. |
90
|
|
|
|
|
|
|
# As such, they get special handling to bootstrap the system. |
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
our %meta_classes = map { $_ => 1 } |
93
|
|
|
|
|
|
|
qw/ |
94
|
|
|
|
|
|
|
UR::Object |
95
|
|
|
|
|
|
|
UR::Object::Type |
96
|
|
|
|
|
|
|
UR::Object::Property |
97
|
|
|
|
|
|
|
/; |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
our $bootstrapping = 1; |
100
|
|
|
|
|
|
|
our @partially_defined_classes; |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
# When copying the object hash to create its db_committed, these keys should be removed because |
103
|
|
|
|
|
|
|
# they contain things like coderefs |
104
|
|
|
|
|
|
|
our @keys_to_delete_from_db_committed = qw( id db_committed _id_property_sorter get_composite_id_resolver get_composite_id_decomposer ); |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
# Stages of Class Initialization |
107
|
|
|
|
|
|
|
# |
108
|
|
|
|
|
|
|
# define() is called to indicate the class structure (create() may also be called by the db sync command to make new classes) |
109
|
|
|
|
|
|
|
# |
110
|
|
|
|
|
|
|
# the parameters to define()/create() are normalized by _normalize_class_description() |
111
|
|
|
|
|
|
|
# |
112
|
|
|
|
|
|
|
# a basic functional class meta object is created by _define_minimal_class_from_normalized_class_description() |
113
|
|
|
|
|
|
|
# |
114
|
|
|
|
|
|
|
# accessors are created |
115
|
|
|
|
|
|
|
# |
116
|
|
|
|
|
|
|
# if we're still bootstrapping: |
117
|
|
|
|
|
|
|
# |
118
|
|
|
|
|
|
|
# the class is stashed in an array so the post-bootstrapping stages can be done in bulk |
119
|
|
|
|
|
|
|
# |
120
|
|
|
|
|
|
|
# we exit define() |
121
|
|
|
|
|
|
|
# |
122
|
|
|
|
|
|
|
# if we're done bootstrapping: |
123
|
|
|
|
|
|
|
# |
124
|
|
|
|
|
|
|
# _inform_all_parent_classes_of_newly_loaded_subclass() sets up an internal map of known subclasses of each base class |
125
|
|
|
|
|
|
|
# |
126
|
|
|
|
|
|
|
# _complete_class_meta_object_definitions() decomposes the definition into normalized objects |
127
|
|
|
|
|
|
|
# |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
sub __define__ { |
130
|
24730
|
|
|
24735
|
|
34960
|
my $class = shift; |
131
|
24730
|
|
|
|
|
63453
|
my $desc = $class->_normalize_class_description(@_); |
132
|
|
|
|
|
|
|
|
133
|
24694
|
|
66
|
|
|
55959
|
my $class_name = $desc->{class_name} ||= (caller(0))[0]; |
134
|
24694
|
|
|
|
|
27293
|
$desc->{class_name} = $class_name; |
135
|
|
|
|
|
|
|
|
136
|
24694
|
|
|
|
|
20954
|
my $self; |
137
|
|
|
|
|
|
|
|
138
|
24694
|
|
|
|
|
53565
|
my %params = $class->_construction_params_for_desc($desc); |
139
|
24694
|
|
|
|
|
25596
|
my $meta_class_name; |
140
|
24694
|
100
|
|
|
|
36198
|
if (%params) { |
141
|
11836
|
|
|
|
|
36950
|
$self = __PACKAGE__->__define__(%params); |
142
|
11836
|
50
|
|
|
|
26940
|
return unless $self; |
143
|
11836
|
|
|
|
|
18697
|
$meta_class_name = $params{class_name}; |
144
|
|
|
|
|
|
|
} |
145
|
|
|
|
|
|
|
else { |
146
|
12858
|
|
|
|
|
13938
|
$meta_class_name = __PACKAGE__; |
147
|
|
|
|
|
|
|
} |
148
|
|
|
|
|
|
|
|
149
|
24694
|
|
|
|
|
47942
|
$self = $UR::Context::all_objects_loaded->{$meta_class_name}{$class_name}; |
150
|
24694
|
100
|
|
|
|
41540
|
if ($self) { |
151
|
|
|
|
|
|
|
#$DB::single = 1; |
152
|
|
|
|
|
|
|
#Carp::cluck("Re-defining class $class_name? Found $meta_class_name with id '$class_name'"); |
153
|
6
|
|
|
|
|
35
|
return $self; |
154
|
|
|
|
|
|
|
} |
155
|
|
|
|
|
|
|
|
156
|
24688
|
|
|
|
|
58156
|
$self = $class->_make_minimal_class_from_normalized_class_description($desc); |
157
|
24688
|
50
|
|
|
|
117967
|
Carp::confess("Failed to define class $class_name!") unless $self; |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
# we do this for define() but not create() |
160
|
24688
|
|
|
|
|
189927
|
my %db_committed = %$self; |
161
|
24688
|
|
|
|
|
79063
|
delete @db_committed{@keys_to_delete_from_db_committed}; |
162
|
24688
|
|
|
|
|
40198
|
$self->{'db_committed'} = \%db_committed; |
163
|
|
|
|
|
|
|
|
164
|
24688
|
50
|
|
|
|
95096
|
$self->_initialize_accessors_and_inheritance |
165
|
|
|
|
|
|
|
or Carp::confess("Error initializing accessors for $class_name!"); |
166
|
|
|
|
|
|
|
|
167
|
24688
|
100
|
|
|
|
81832
|
if ($bootstrapping) { |
168
|
11966
|
|
|
|
|
17224
|
push @partially_defined_classes, $self; |
169
|
|
|
|
|
|
|
} |
170
|
|
|
|
|
|
|
else { |
171
|
12722
|
100
|
|
|
|
59937
|
unless ($self->_inform_all_parent_classes_of_newly_loaded_subclass()) { |
172
|
0
|
|
|
|
|
0
|
Carp::confess( |
173
|
|
|
|
|
|
|
"Failed to link to parent classes to complete definition of class $class_name!" |
174
|
|
|
|
|
|
|
. $class->error_message |
175
|
|
|
|
|
|
|
); |
176
|
|
|
|
|
|
|
} |
177
|
12722
|
50
|
|
|
|
57173
|
unless ($self->_complete_class_meta_object_definitions()) { |
178
|
|
|
|
|
|
|
#$DB::single = 1; |
179
|
0
|
|
|
|
|
0
|
$self->_complete_class_meta_object_definitions(); |
180
|
0
|
|
|
|
|
0
|
Carp::confess( |
181
|
|
|
|
|
|
|
"Failed to complete definition of class $class_name!" |
182
|
|
|
|
|
|
|
. $class->error_message |
183
|
|
|
|
|
|
|
); |
184
|
|
|
|
|
|
|
} |
185
|
|
|
|
|
|
|
} |
186
|
|
|
|
|
|
|
|
187
|
24686
|
|
|
|
|
107029
|
$self->_inform_roles_of_new_class(); |
188
|
|
|
|
|
|
|
|
189
|
24686
|
|
|
|
|
219668
|
return $self; |
190
|
|
|
|
|
|
|
} |
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
sub create { |
194
|
|
|
|
|
|
|
# this is typically only used by code which intendes to autogenerate source code |
195
|
|
|
|
|
|
|
# it will lead to the writing of a Perl module upon commit. |
196
|
2
|
|
|
3
|
1
|
728
|
my $class = shift; |
197
|
2
|
|
|
|
|
9
|
my $desc = $class->_normalize_class_description(@_); |
198
|
|
|
|
|
|
|
|
199
|
2
|
|
66
|
|
|
6
|
my $class_name = $desc->{class_name} ||= (caller(0))[0]; |
200
|
2
|
|
|
|
|
4
|
my $meta_class_name = $desc->{meta_class_name}; |
201
|
|
|
|
|
|
|
|
202
|
280
|
|
|
268
|
|
1333
|
no strict 'refs'; |
|
267
|
|
|
|
|
422
|
|
|
267
|
|
|
|
|
52694
|
|
203
|
2
|
100
|
66
|
|
|
6
|
unless ( |
|
|
|
66
|
|
|
|
|
204
|
|
|
|
|
|
|
$meta_class_name eq __PACKAGE__ |
205
|
|
|
|
|
|
|
or |
206
|
|
|
|
|
|
|
# in newer Perl interpreters the ->isa() call can return true |
207
|
|
|
|
|
|
|
# even if @ISA has been emptied (OS X) ??? |
208
|
1
|
|
|
|
|
7
|
(scalar(@{$meta_class_name . '::ISA'}) and $meta_class_name->isa(__PACKAGE__)) |
209
|
|
|
|
|
|
|
) { |
210
|
1
|
50
|
|
|
|
5
|
if (__PACKAGE__->get(class_name => $meta_class_name)) { |
211
|
0
|
|
|
|
|
0
|
warn "class $meta_class_name already exists when creating class meta for $class_name?!"; |
212
|
|
|
|
|
|
|
} |
213
|
|
|
|
|
|
|
else { |
214
|
1
|
|
|
|
|
6
|
__PACKAGE__->create( |
215
|
|
|
|
|
|
|
__PACKAGE__->_construction_params_for_desc($desc) |
216
|
|
|
|
|
|
|
); |
217
|
|
|
|
|
|
|
} |
218
|
|
|
|
|
|
|
} |
219
|
|
|
|
|
|
|
|
220
|
2
|
|
|
|
|
7
|
my $self = $class->_make_minimal_class_from_normalized_class_description($desc); |
221
|
2
|
50
|
|
|
|
9
|
Carp::confess("Failed to define class $class_name!") unless $self; |
222
|
|
|
|
|
|
|
|
223
|
2
|
50
|
|
|
|
9
|
$self->_initialize_accessors_and_inheritance |
224
|
|
|
|
|
|
|
or Carp::confess("Failed to define class $class_name!"); |
225
|
|
|
|
|
|
|
|
226
|
2
|
100
|
|
|
|
16
|
$self->_inform_all_parent_classes_of_newly_loaded_subclass() |
227
|
|
|
|
|
|
|
or Carp::confess( |
228
|
|
|
|
|
|
|
"Failed to link to parent classes to complete definition of class $class_name!" |
229
|
|
|
|
|
|
|
. $class->error_message |
230
|
|
|
|
|
|
|
); |
231
|
|
|
|
|
|
|
|
232
|
2
|
|
|
|
|
9
|
$self->generated(0); |
233
|
|
|
|
|
|
|
|
234
|
2
|
|
|
|
|
13
|
$self->__signal_change__("create"); |
235
|
|
|
|
|
|
|
|
236
|
2
|
|
|
|
|
10
|
return $self; |
237
|
|
|
|
|
|
|
} |
238
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
sub _preprocess_subclass_description { |
240
|
|
|
|
|
|
|
# allow a class to modify the description of any subclass before it instantiates |
241
|
|
|
|
|
|
|
# this filtering allows a base class to specify policy, add meta properties, etc. |
242
|
38908
|
|
|
38909
|
|
35953
|
my ($self,$prev_desc) = @_; |
243
|
|
|
|
|
|
|
|
244
|
38908
|
|
|
|
|
31044
|
my $current_desc = $prev_desc; |
245
|
|
|
|
|
|
|
|
246
|
38908
|
100
|
|
|
|
88352
|
if (my $preprocessor = $self->subclass_description_preprocessor) { |
247
|
|
|
|
|
|
|
# the preprocessor must me a method name in the class being adjusted |
248
|
267
|
|
|
268
|
|
1194
|
no strict 'refs'; |
|
267
|
|
|
|
|
430
|
|
|
267
|
|
|
|
|
296665
|
|
249
|
29
|
100
|
|
|
|
139
|
unless ($self->class_name->can($preprocessor)) { |
250
|
0
|
|
|
|
|
0
|
die "Class " . $self->class_name |
251
|
|
|
|
|
|
|
. " specifies a pre-processor for subclass descriptions " |
252
|
|
|
|
|
|
|
. $preprocessor . " which is not defined in the " |
253
|
|
|
|
|
|
|
. $self->class_name . " package!"; |
254
|
|
|
|
|
|
|
} |
255
|
29
|
|
|
|
|
289
|
$current_desc = $self->class_name->$preprocessor($current_desc); |
256
|
29
|
|
|
|
|
833
|
$current_desc = $self->_normalize_class_description_impl(%$current_desc); |
257
|
|
|
|
|
|
|
} |
258
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
# only call it on the direct parent classes, let recursion walk the tree |
260
|
|
|
|
|
|
|
my @parent_class_names = |
261
|
38907
|
|
|
|
|
78911
|
grep { $_->can('__meta__') } |
|
24604
|
|
|
|
|
70141
|
|
262
|
|
|
|
|
|
|
$self->parent_class_names(); |
263
|
|
|
|
|
|
|
|
264
|
38907
|
|
|
|
|
147847
|
for my $parent_class_name (@parent_class_names) { |
265
|
24604
|
|
|
|
|
41839
|
my $parent_class = $parent_class_name->__meta__; |
266
|
24604
|
|
|
|
|
44796
|
$current_desc = $parent_class->_preprocess_subclass_description($current_desc); |
267
|
|
|
|
|
|
|
} |
268
|
|
|
|
|
|
|
|
269
|
38907
|
|
|
|
|
50030
|
return $current_desc; |
270
|
|
|
|
|
|
|
} |
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
sub _construction_params_for_desc { |
273
|
24695
|
|
|
24697
|
|
24679
|
my $class = shift; |
274
|
24695
|
|
|
|
|
22311
|
my $desc = shift; |
275
|
|
|
|
|
|
|
|
276
|
24695
|
|
|
|
|
26579
|
my $class_name = $desc->{class_name}; |
277
|
24695
|
|
|
|
|
25418
|
my $meta_class_name = $desc->{meta_class_name}; |
278
|
24695
|
|
|
|
|
21333
|
my @extended_metadata; |
279
|
24695
|
100
|
|
|
|
44195
|
if ($desc->{type_has}) { |
280
|
118
|
|
|
|
|
265
|
@extended_metadata = ( has => [ @{ $desc->{type_has} } ] ); |
|
118
|
|
|
|
|
438
|
|
281
|
|
|
|
|
|
|
} |
282
|
|
|
|
|
|
|
|
283
|
24695
|
100
|
|
|
|
43581
|
if ( |
284
|
|
|
|
|
|
|
$meta_class_name eq __PACKAGE__ |
285
|
|
|
|
|
|
|
) { |
286
|
12858
|
50
|
|
|
|
25409
|
if (@extended_metadata) { |
287
|
0
|
|
|
|
|
0
|
die "Cannot extend class metadata of $class_name because it is a class involved in UR bootstrapping."; |
288
|
|
|
|
|
|
|
} |
289
|
12858
|
|
|
|
|
27179
|
return(); |
290
|
|
|
|
|
|
|
} |
291
|
|
|
|
|
|
|
else { |
292
|
11837
|
100
|
|
|
|
20168
|
if ($bootstrapping) { |
293
|
|
|
|
|
|
|
return ( |
294
|
5584
|
|
|
|
|
18034
|
class_name => $meta_class_name, |
295
|
|
|
|
|
|
|
is => __PACKAGE__, |
296
|
|
|
|
|
|
|
@extended_metadata, |
297
|
|
|
|
|
|
|
); |
298
|
|
|
|
|
|
|
} |
299
|
|
|
|
|
|
|
else { |
300
|
6253
|
|
|
|
|
9962
|
my $parent_classes = $desc->{is}; |
301
|
6253
|
|
|
|
|
11428
|
my @meta_parent_classes = map { $_ . '::Type' } @$parent_classes; |
|
7036
|
|
|
|
|
26732
|
|
302
|
6253
|
|
|
|
|
13645
|
for (@$parent_classes) { |
303
|
7036
|
|
|
|
|
27139
|
__PACKAGE__->use_module_with_namespace_constraints($_); |
304
|
7036
|
|
|
|
|
8721
|
eval {$_->class}; |
|
7036
|
|
|
|
|
38007
|
|
305
|
7036
|
50
|
|
|
|
18364
|
if ($@) { |
306
|
0
|
|
|
|
|
0
|
die "Error with parent class $_ when defining $class_name! $@"; |
307
|
|
|
|
|
|
|
} |
308
|
|
|
|
|
|
|
} |
309
|
|
|
|
|
|
|
return ( |
310
|
6253
|
|
|
|
|
29621
|
class_name => $meta_class_name, |
311
|
|
|
|
|
|
|
is => \@meta_parent_classes, |
312
|
|
|
|
|
|
|
@extended_metadata, |
313
|
|
|
|
|
|
|
); |
314
|
|
|
|
|
|
|
} |
315
|
|
|
|
|
|
|
} |
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
} |
318
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
sub initialize_bootstrap_classes |
322
|
|
|
|
|
|
|
{ |
323
|
|
|
|
|
|
|
# This is called once at the end of compiling the UR module set to handle |
324
|
|
|
|
|
|
|
# classes which did incomplete initialization while bootstrapping. |
325
|
|
|
|
|
|
|
# Until bootstrapping occurs is done, |
326
|
266
|
|
|
273
|
1
|
508
|
my $class = shift; |
327
|
|
|
|
|
|
|
|
328
|
266
|
|
|
|
|
903
|
for my $class_meta (@partially_defined_classes) { |
329
|
11966
|
50
|
|
|
|
34469
|
unless ($class_meta->_inform_all_parent_classes_of_newly_loaded_subclass) { |
330
|
0
|
|
|
|
|
0
|
my $class_name = $class_meta->{class_name}; |
331
|
0
|
|
|
|
|
0
|
Carp::confess ( |
332
|
|
|
|
|
|
|
"Failed to complete inheritance linkage definition of class $class_name!" |
333
|
|
|
|
|
|
|
. $class_meta->error_message |
334
|
|
|
|
|
|
|
); |
335
|
|
|
|
|
|
|
} |
336
|
|
|
|
|
|
|
|
337
|
|
|
|
|
|
|
} |
338
|
266
|
|
|
|
|
1248
|
while (my $class_meta = shift @partially_defined_classes) { |
339
|
11966
|
50
|
|
|
|
39535
|
unless ($class_meta->_complete_class_meta_object_definitions()) { |
340
|
0
|
|
|
|
|
0
|
my $class_name = $class_meta->{class_name}; |
341
|
0
|
|
|
|
|
0
|
Carp::confess( |
342
|
|
|
|
|
|
|
"Failed to complete definition of class $class_name!" |
343
|
|
|
|
|
|
|
. $class_meta->error_message |
344
|
|
|
|
|
|
|
); |
345
|
|
|
|
|
|
|
} |
346
|
|
|
|
|
|
|
} |
347
|
266
|
|
|
|
|
609
|
$bootstrapping = 0; |
348
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
# It should be safe to set up callbacks now. register_callback() instead |
350
|
|
|
|
|
|
|
# of create() so a subsequent rollback won't remove the observer. |
351
|
266
|
|
|
|
|
2711
|
UR::Observer->register_callback( |
352
|
|
|
|
|
|
|
subject_class_name => 'UR::Object::Property', |
353
|
|
|
|
|
|
|
subject_id => '', |
354
|
|
|
|
|
|
|
aspect => '', |
355
|
|
|
|
|
|
|
priority => 1, |
356
|
|
|
|
|
|
|
note => '', |
357
|
|
|
|
|
|
|
once => 0, |
358
|
|
|
|
|
|
|
callback => \&UR::Object::Type::_property_change_callback, |
359
|
|
|
|
|
|
|
); |
360
|
|
|
|
|
|
|
} |
361
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
sub _normalize_class_description { |
363
|
24739
|
|
|
24762
|
|
35260
|
my $class = shift; |
364
|
24739
|
|
|
|
|
64509
|
my $desc = $class->_normalize_class_description_impl(@_); |
365
|
|
|
|
|
|
|
|
366
|
24729
|
100
|
|
|
|
63778
|
$class->compose_roles($desc) unless $bootstrapping; |
367
|
|
|
|
|
|
|
|
368
|
24704
|
100
|
|
|
|
41569
|
unless ($bootstrapping) { |
369
|
12738
|
|
|
|
|
14220
|
for my $parent_class_name (@{ $desc->{is} }) { |
|
12738
|
|
|
|
|
24487
|
|
370
|
14304
|
|
|
|
|
35249
|
my $parent_class = $parent_class_name->__meta__; |
371
|
14304
|
|
|
|
|
53206
|
$desc = $parent_class->_preprocess_subclass_description($desc); |
372
|
|
|
|
|
|
|
} |
373
|
|
|
|
|
|
|
} |
374
|
|
|
|
|
|
|
|
375
|
|
|
|
|
|
|
# we previously handled property meta extensions when normalizing the property |
376
|
|
|
|
|
|
|
# now we merely save unrecognized things |
377
|
|
|
|
|
|
|
# this is now done afterward so that parent classes can preprocess their subclasses descriptions before extending |
378
|
|
|
|
|
|
|
# normalize the data behind the property descriptions |
379
|
24703
|
|
|
|
|
23059
|
my @property_names = keys %{$desc->{has}}; |
|
24703
|
|
|
|
|
59577
|
|
380
|
24703
|
|
|
|
|
34757
|
for my $property_name (@property_names) { |
381
|
95415
|
100
|
|
|
|
127062
|
Carp::croak("Invalid property name in class ".$desc->{class_name}.": '$property_name'") |
382
|
|
|
|
|
|
|
unless UR::Util::is_valid_property_name($property_name); |
383
|
|
|
|
|
|
|
|
384
|
95410
|
|
|
|
|
86891
|
my $pdesc = $desc->{has}->{$property_name}; |
385
|
95410
|
|
|
|
|
69885
|
my $unknown_ma = delete $pdesc->{unrecognized_meta_attributes}; |
386
|
95410
|
100
|
|
|
|
126471
|
next unless $unknown_ma; |
387
|
114
|
|
|
|
|
242
|
for my $name (keys %$unknown_ma) { |
388
|
131
|
100
|
|
|
|
278
|
if (exists $desc->{attributes_have}->{$name}) { |
389
|
131
|
|
|
|
|
210
|
$pdesc->{$name} = delete $unknown_ma->{$name}; |
390
|
|
|
|
|
|
|
} |
391
|
|
|
|
|
|
|
} |
392
|
114
|
50
|
|
|
|
344
|
if (%$unknown_ma) { |
393
|
0
|
|
|
|
|
0
|
my $class_name = $desc->{class_name}; |
394
|
0
|
|
|
|
|
0
|
my @unknown_ma = sort keys %$unknown_ma; |
395
|
0
|
|
|
|
|
0
|
Carp::confess("unknown meta-attributes present for $class_name $property_name: @unknown_ma\n"); |
396
|
|
|
|
|
|
|
} |
397
|
|
|
|
|
|
|
} |
398
|
|
|
|
|
|
|
|
399
|
24698
|
|
|
|
|
36697
|
return $desc; |
400
|
|
|
|
|
|
|
} |
401
|
|
|
|
|
|
|
|
402
|
|
|
|
|
|
|
sub _canonicalize_class_params { |
403
|
24810
|
|
|
24811
|
|
28850
|
my($params, $mappings) = @_; |
404
|
|
|
|
|
|
|
|
405
|
24810
|
|
|
|
|
23311
|
my %canon_params; |
406
|
|
|
|
|
|
|
|
407
|
24810
|
|
|
|
|
41109
|
for my $mapping ( @$mappings ) { |
408
|
843540
|
|
|
|
|
819760
|
my ($primary_field_name, @alternate_field_names) = @$mapping; |
409
|
843540
|
|
|
|
|
680112
|
my @all_fields = ($primary_field_name, @alternate_field_names); |
410
|
843540
|
|
|
|
|
736399
|
my @values = grep { defined($_) } delete @$params{@all_fields}; |
|
1314636
|
|
|
|
|
1244712
|
|
411
|
843540
|
50
|
|
|
|
1656320
|
if (@values > 1) { |
|
|
100
|
|
|
|
|
|
412
|
0
|
|
|
|
|
0
|
Carp::confess( |
413
|
|
|
|
|
|
|
"Multiple values in for field " |
414
|
|
|
|
|
|
|
. join("/", @all_fields) |
415
|
|
|
|
|
|
|
); |
416
|
|
|
|
|
|
|
} |
417
|
|
|
|
|
|
|
elsif (@values == 1) { |
418
|
45786
|
|
|
|
|
86035
|
$canon_params{$primary_field_name} = $values[0]; |
419
|
|
|
|
|
|
|
} |
420
|
|
|
|
|
|
|
} |
421
|
|
|
|
|
|
|
|
422
|
24810
|
|
|
|
|
120051
|
return %canon_params; |
423
|
|
|
|
|
|
|
} |
424
|
|
|
|
|
|
|
|
425
|
|
|
|
|
|
|
our @CLASS_DESCRIPTION_KEY_MAPPINGS_COMMON_TO_CLASSES_AND_ROLES = ( |
426
|
|
|
|
|
|
|
[ roles => qw//], |
427
|
|
|
|
|
|
|
[ is_abstract => qw/abstract/], |
428
|
|
|
|
|
|
|
[ is_final => qw/final/], |
429
|
|
|
|
|
|
|
[ is_singleton => qw//], |
430
|
|
|
|
|
|
|
[ is_transactional => qw//], |
431
|
|
|
|
|
|
|
[ id_by => qw/id_properties/], |
432
|
|
|
|
|
|
|
[ has => qw/properties/], |
433
|
|
|
|
|
|
|
[ type_has => qw//], |
434
|
|
|
|
|
|
|
[ attributes_have => qw//], |
435
|
|
|
|
|
|
|
[ er_role => qw/er_type/], |
436
|
|
|
|
|
|
|
[ doc => qw/description/], |
437
|
|
|
|
|
|
|
[ relationships => qw//], |
438
|
|
|
|
|
|
|
[ constraints => qw/unique_constraints/], |
439
|
|
|
|
|
|
|
[ namespace => qw//], |
440
|
|
|
|
|
|
|
[ schema_name => qw//], |
441
|
|
|
|
|
|
|
[ data_source_id => qw/data_source instance/], |
442
|
|
|
|
|
|
|
[ select_hint => qw/query_hint/], |
443
|
|
|
|
|
|
|
[ join_hint => qw//], |
444
|
|
|
|
|
|
|
[ subclassify_by => qw/sub_classification_property_name/], |
445
|
|
|
|
|
|
|
[ sub_classification_meta_class_name => qw//], |
446
|
|
|
|
|
|
|
[ sub_classification_method_name => qw//], |
447
|
|
|
|
|
|
|
[ first_sub_classification_method_name => qw//], |
448
|
|
|
|
|
|
|
[ composite_id_separator => qw//], |
449
|
|
|
|
|
|
|
[ generate => qw//], |
450
|
|
|
|
|
|
|
[ generated => qw//], |
451
|
|
|
|
|
|
|
[ subclass_description_preprocessor => qw//], |
452
|
|
|
|
|
|
|
[ id_generator => qw/id_sequence_generator_name/], |
453
|
|
|
|
|
|
|
[ subclassify_by_version => qw//], |
454
|
|
|
|
|
|
|
[ meta_class_name => qw//], |
455
|
|
|
|
|
|
|
[ valid_signals => qw//], |
456
|
|
|
|
|
|
|
); |
457
|
|
|
|
|
|
|
|
458
|
|
|
|
|
|
|
my @CLASS_DESCRIPTION_KEY_MAPPINGS = ( |
459
|
|
|
|
|
|
|
@CLASS_DESCRIPTION_KEY_MAPPINGS_COMMON_TO_CLASSES_AND_ROLES, |
460
|
|
|
|
|
|
|
[ class_name => qw//], |
461
|
|
|
|
|
|
|
[ type_name => qw/english_name/], |
462
|
|
|
|
|
|
|
[ is => qw/inheritance extends isa is_a/], |
463
|
|
|
|
|
|
|
[ table_name => qw/sql dsmap/], |
464
|
|
|
|
|
|
|
); |
465
|
|
|
|
|
|
|
|
466
|
|
|
|
|
|
|
sub _normalize_class_description_impl { |
467
|
24768
|
|
|
24778
|
|
25889
|
my $class = shift; |
468
|
24768
|
|
|
|
|
64122
|
my %old_class = @_; |
469
|
|
|
|
|
|
|
|
470
|
24768
|
50
|
|
|
|
61222
|
if (exists $old_class{extra}) { |
471
|
0
|
|
|
|
|
0
|
%old_class = (%{delete $old_class{extra}}, %old_class); |
|
0
|
|
|
|
|
0
|
|
472
|
|
|
|
|
|
|
} |
473
|
|
|
|
|
|
|
|
474
|
24768
|
|
|
|
|
38068
|
my $class_name = delete $old_class{class_name}; |
475
|
|
|
|
|
|
|
|
476
|
|
|
|
|
|
|
my %new_class = ( |
477
|
|
|
|
|
|
|
class_name => $class_name, |
478
|
|
|
|
|
|
|
is_singleton => $UR::Object::Type::defaults{'is_singleton'}, |
479
|
|
|
|
|
|
|
is_final => $UR::Object::Type::defaults{'is_final'}, |
480
|
24768
|
|
|
|
|
83330
|
is_abstract => $UR::Object::Type::defaults{'is_abstract'}, |
481
|
|
|
|
|
|
|
_canonicalize_class_params(\%old_class, \@CLASS_DESCRIPTION_KEY_MAPPINGS), |
482
|
|
|
|
|
|
|
); |
483
|
|
|
|
|
|
|
|
484
|
24768
|
100
|
|
|
|
60996
|
if (my $pp = $new_class{subclass_description_preprocessor}) { |
485
|
11
|
50
|
|
|
|
47
|
if (!ref($pp)) { |
|
|
0
|
|
|
|
|
|
486
|
11
|
50
|
|
|
|
70
|
unless ($pp =~ /::/) { |
487
|
|
|
|
|
|
|
# a method name, not fully qualified |
488
|
|
|
|
|
|
|
$new_class{subclass_description_preprocessor} = |
489
|
|
|
|
|
|
|
$new_class{class_name} |
490
|
|
|
|
|
|
|
. '::' |
491
|
0
|
|
|
|
|
0
|
. $new_class{subclass_description_preprocessor}; |
492
|
|
|
|
|
|
|
} else { |
493
|
11
|
|
|
|
|
27
|
$new_class{subclass_description_preprocessor} = $pp; |
494
|
|
|
|
|
|
|
} |
495
|
|
|
|
|
|
|
} |
496
|
|
|
|
|
|
|
elsif (ref($pp) ne 'CODE') { |
497
|
0
|
|
|
|
|
0
|
die "unexpected " . ref($pp) . " reference for subclass_description_preprocessor for $class_name!"; |
498
|
|
|
|
|
|
|
} |
499
|
|
|
|
|
|
|
} |
500
|
|
|
|
|
|
|
|
501
|
24768
|
100
|
|
|
|
47099
|
unless ($new_class{er_role}) { |
502
|
24469
|
|
|
|
|
43313
|
$new_class{er_role} = $UR::Object::Type::defaults{'er_role'}; |
503
|
|
|
|
|
|
|
} |
504
|
|
|
|
|
|
|
|
505
|
24768
|
|
|
|
|
36292
|
my @crap = qw/source/; |
506
|
24768
|
|
|
|
|
27344
|
delete @old_class{@crap}; |
507
|
|
|
|
|
|
|
|
508
|
24768
|
100
|
|
|
|
122070
|
if ($class_name =~ /^(.*?)::/) { |
509
|
23872
|
|
|
|
|
66040
|
$new_class{namespace} = $1; |
510
|
|
|
|
|
|
|
} |
511
|
|
|
|
|
|
|
else { |
512
|
896
|
|
|
|
|
2068
|
$new_class{namespace} = $new_class{class_name}; |
513
|
|
|
|
|
|
|
} |
514
|
|
|
|
|
|
|
|
515
|
24768
|
100
|
66
|
|
|
89273
|
if (not exists $new_class{is_transactional} |
516
|
|
|
|
|
|
|
and not $meta_classes{$class_name} |
517
|
|
|
|
|
|
|
) { |
518
|
21234
|
|
|
|
|
45402
|
$new_class{is_transactional} = $UR::Object::Type::defaults{'is_transactional'}; |
519
|
|
|
|
|
|
|
} |
520
|
|
|
|
|
|
|
|
521
|
24768
|
100
|
|
|
|
47405
|
unless ($new_class{is}) { |
522
|
271
|
|
|
268
|
|
1489
|
no warnings; |
|
268
|
|
|
|
|
397
|
|
|
270
|
|
|
|
|
11749
|
|
523
|
267
|
|
|
280
|
|
1078
|
no strict 'refs'; |
|
270
|
|
|
|
|
391
|
|
|
267
|
|
|
|
|
116755
|
|
524
|
4814
|
100
|
|
|
|
8501
|
if (my @isa = @{ $class_name . "::ISA" }) { |
|
4814
|
|
|
|
|
40806
|
|
525
|
538
|
|
|
|
|
1125
|
$new_class{is} = \@isa; |
526
|
|
|
|
|
|
|
} |
527
|
|
|
|
|
|
|
} |
528
|
|
|
|
|
|
|
|
529
|
24768
|
100
|
|
|
|
46490
|
unless ($new_class{is}) { |
530
|
4276
|
100
|
|
|
|
9178
|
if ($new_class{table_name}) { |
531
|
273
|
|
|
|
|
882
|
$new_class{is} = ['UR::Entity'] |
532
|
|
|
|
|
|
|
} |
533
|
|
|
|
|
|
|
else { |
534
|
4003
|
|
|
|
|
9780
|
$new_class{is} = ['UR::Object'] |
535
|
|
|
|
|
|
|
} |
536
|
|
|
|
|
|
|
} |
537
|
|
|
|
|
|
|
|
538
|
24768
|
100
|
|
|
|
44252
|
unless ($new_class{'doc'}) { |
539
|
20848
|
|
|
|
|
27133
|
$new_class{'doc'} = undef; |
540
|
|
|
|
|
|
|
} |
541
|
|
|
|
|
|
|
|
542
|
24768
|
|
|
|
|
36678
|
foreach my $key ( qw(valid_signals roles) ) { |
543
|
49536
|
50
|
|
|
|
109844
|
unless (UR::Util::ensure_arrayref(\%new_class, $key)) { |
544
|
0
|
|
|
|
|
0
|
Carp::croak("The '$key' metadata for class $class_name must be an arrayref"); |
545
|
|
|
|
|
|
|
} |
546
|
|
|
|
|
|
|
} |
547
|
|
|
|
|
|
|
|
548
|
|
|
|
|
|
|
# Later code expects these to be listrefs |
549
|
24768
|
|
|
|
|
35614
|
for my $field (qw/is id_by has relationships constraints/) { |
550
|
123840
|
|
|
|
|
134262
|
_massage_field_into_arrayref(\%new_class, $field); |
551
|
|
|
|
|
|
|
} |
552
|
|
|
|
|
|
|
|
553
|
|
|
|
|
|
|
|
554
|
|
|
|
|
|
|
# These may have been found and moved over. Restore. |
555
|
24768
|
|
|
|
|
38053
|
$old_class{has} = delete $new_class{has}; |
556
|
24768
|
|
|
|
|
34067
|
$old_class{attributes_have} = delete $new_class{attributes_have}; |
557
|
|
|
|
|
|
|
|
558
|
|
|
|
|
|
|
# Install structures to track fully formatted property data. |
559
|
24768
|
|
|
|
|
36419
|
my $instance_properties = $new_class{has} = {}; |
560
|
24768
|
|
|
|
|
54004
|
my $meta_properties = $new_class{attributes_have} = {}; |
561
|
|
|
|
|
|
|
|
562
|
|
|
|
|
|
|
# The id might be a single value, or not specified at all. |
563
|
24768
|
|
|
|
|
22725
|
my $id_properties; |
564
|
24768
|
50
|
33
|
|
|
130548
|
if (not exists $new_class{id_by}) { |
|
|
50
|
|
|
|
|
|
565
|
0
|
0
|
|
|
|
0
|
if ($new_class{is}) { |
566
|
0
|
|
|
|
|
0
|
$id_properties = $new_class{id_by} = []; |
567
|
|
|
|
|
|
|
} |
568
|
|
|
|
|
|
|
else { |
569
|
0
|
|
|
|
|
0
|
$id_properties = $new_class{id_by} = [ id => { is_optional => 0 } ]; |
570
|
|
|
|
|
|
|
} |
571
|
|
|
|
|
|
|
} |
572
|
|
|
|
|
|
|
elsif ( (not ref($new_class{id_by})) or (ref($new_class{id_by}) ne 'ARRAY') ) { |
573
|
0
|
|
|
|
|
0
|
$id_properties = $new_class{id_by} = [ $new_class{id_by} ]; |
574
|
|
|
|
|
|
|
} |
575
|
|
|
|
|
|
|
else { |
576
|
24768
|
|
|
|
|
28451
|
$id_properties = $new_class{id_by}; |
577
|
|
|
|
|
|
|
} |
578
|
|
|
|
|
|
|
|
579
|
24768
|
|
|
|
|
49637
|
_normalize_id_property_data(\%old_class, \%new_class); |
580
|
|
|
|
|
|
|
|
581
|
24768
|
50
|
100
|
|
|
64177
|
if (@$id_properties > 1 |
582
|
5200
|
|
|
|
|
11747
|
and grep {$_ eq 'id'} @$id_properties) |
583
|
|
|
|
|
|
|
{ |
584
|
|
|
|
|
|
|
Carp::croak("Cannot initialize class $class_name: " |
585
|
|
|
|
|
|
|
. "Cannot have an ID property named 'id' when the class has multiple ID properties (" |
586
|
0
|
|
|
|
|
0
|
. join(', ', map { "'$_'" } @$id_properties) |
|
0
|
|
|
|
|
0
|
|
587
|
|
|
|
|
|
|
. ")"); |
588
|
|
|
|
|
|
|
} |
589
|
|
|
|
|
|
|
|
590
|
24768
|
|
|
|
|
54639
|
_process_class_definition_property_keys(\%old_class, \%new_class); |
591
|
|
|
|
|
|
|
|
592
|
|
|
|
|
|
|
# NOT ENABLED YET |
593
|
24768
|
|
|
|
|
23937
|
if (0) { |
594
|
|
|
|
|
|
|
# done processing direct properties of this process |
595
|
|
|
|
|
|
|
# extend %$instance_properties with properties of the parent classes |
596
|
|
|
|
|
|
|
my @parent_class_names = @{ $new_class{is} }; |
597
|
|
|
|
|
|
|
for my $parent_class_name (@parent_class_names) { |
598
|
|
|
|
|
|
|
my $parent_class_meta = $parent_class_name->__meta__; |
599
|
|
|
|
|
|
|
die "no meta for $parent_class_name while initializing $class_name?" unless $parent_class_meta; |
600
|
|
|
|
|
|
|
my $parent_normalized_properties = $parent_class_meta->{has}; |
601
|
|
|
|
|
|
|
for my $parent_property_name (keys %$parent_normalized_properties) { |
602
|
|
|
|
|
|
|
my $parent_property_data = $parent_normalized_properties->{$parent_property_name}; |
603
|
|
|
|
|
|
|
my $inherited_copy = $instance_properties->{$parent_property_name}; |
604
|
|
|
|
|
|
|
unless ($inherited_copy) { |
605
|
|
|
|
|
|
|
$inherited_copy = UR::Util::deep_copy($parent_property_data); |
606
|
|
|
|
|
|
|
} |
607
|
|
|
|
|
|
|
$inherited_copy->{class_name} = $class_name; |
608
|
|
|
|
|
|
|
my $override = $inherited_copy->{overrides_class_names} ||= []; |
609
|
|
|
|
|
|
|
push @$override, $parent_property_data->{class_name}; |
610
|
|
|
|
|
|
|
} |
611
|
|
|
|
|
|
|
} |
612
|
|
|
|
|
|
|
} |
613
|
|
|
|
|
|
|
|
614
|
24768
|
100
|
100
|
|
|
67417
|
if (($new_class{data_source_id} and not ref($new_class{data_source_id})) and not $new_class{schema_name}) { |
|
|
|
100
|
|
|
|
|
615
|
658
|
|
|
|
|
1251
|
my $s = $new_class{data_source_id}; |
616
|
658
|
|
|
|
|
3451
|
$s =~ s/^.*::DataSource:://; |
617
|
658
|
|
|
|
|
1602
|
$new_class{schema_name} = $s; |
618
|
|
|
|
|
|
|
} |
619
|
|
|
|
|
|
|
|
620
|
24768
|
100
|
|
|
|
48050
|
if (%old_class) { |
621
|
|
|
|
|
|
|
# this should have all been deleted above |
622
|
|
|
|
|
|
|
# we actually process it later, since these may be related to parent classes extending |
623
|
|
|
|
|
|
|
# the class definition |
624
|
263
|
|
|
|
|
786
|
$new_class{extra} = \%old_class; |
625
|
|
|
|
|
|
|
}; |
626
|
|
|
|
|
|
|
|
627
|
|
|
|
|
|
|
# ensure parent classes are loaded |
628
|
24768
|
100
|
|
|
|
45069
|
unless ($bootstrapping) { |
629
|
12802
|
50
|
|
|
|
25831
|
my @base_classes = map { ref($_) ? @$_ : $_ } $new_class{is}; |
|
12802
|
|
|
|
|
49634
|
|
630
|
12802
|
|
|
|
|
20437
|
for my $parent_class_name (@base_classes) { |
631
|
|
|
|
|
|
|
# ensure the parent classes are fully processed |
632
|
267
|
|
|
267
|
|
1290
|
no warnings; |
|
267
|
|
|
|
|
425
|
|
|
267
|
|
|
|
|
527786
|
|
633
|
14383
|
100
|
|
|
|
94843
|
unless ($parent_class_name->can("__meta__")) { |
634
|
43
|
|
|
|
|
2901
|
__PACKAGE__->use_module_with_namespace_constraints($parent_class_name); |
635
|
43
|
50
|
|
|
|
144
|
Carp::croak("Class $class_name cannot initialize because of errors using parent class $parent_class_name: $@") if $@; |
636
|
|
|
|
|
|
|
} |
637
|
14383
|
100
|
|
|
|
234717
|
unless ($parent_class_name->can("__meta__")) { |
638
|
3
|
50
|
|
|
|
99
|
if ($ENV{'HARNESS_ACTIVE'}) { |
639
|
3
|
|
|
|
|
963
|
Carp::confess("Class $class_name cannot initialize because of errors using parent class $parent_class_name. Failed to find static method '__meta__' on $parent_class_name. Does class $parent_class_name exist, and is it loaded?\n The entire list of base classes was ".join(', ', @base_classes)); |
640
|
|
|
|
|
|
|
} |
641
|
0
|
|
|
|
|
0
|
Carp::croak("Class $class_name cannot initialize because of errors using parent class $parent_class_name. Failed to find static method '__meta__' on $parent_class_name. Does class $parent_class_name exist, and is it loaded?"); |
642
|
|
|
|
|
|
|
} |
643
|
14380
|
|
|
|
|
80361
|
my $parent_class = $parent_class_name->__meta__; |
644
|
14380
|
50
|
|
|
|
32829
|
unless ($parent_class) { |
645
|
0
|
|
|
|
|
0
|
Carp::carp("No class metadata object for $parent_class_name"); |
646
|
0
|
|
|
|
|
0
|
next; |
647
|
|
|
|
|
|
|
} |
648
|
|
|
|
|
|
|
|
649
|
|
|
|
|
|
|
# the the parent classes indicate version, if needed |
650
|
14380
|
100
|
66
|
|
|
44770
|
if ($parent_class->{'subclassify_by_version'} and not $parent_class_name =~ /::Ghost/) { |
651
|
39
|
100
|
|
|
|
537
|
unless ($class_name =~ /^${parent_class_name}::V\d+/) { |
652
|
15
|
|
|
|
|
23
|
my $ns = $parent_class_name; |
653
|
15
|
|
|
|
|
25
|
$ns =~ s/::.*//; |
654
|
15
|
|
|
|
|
15
|
my $version; |
655
|
15
|
50
|
66
|
|
|
68
|
if ($ns and $ns->can("component_version")) { |
656
|
0
|
|
|
|
|
0
|
$version = $ns->component_version($class); |
657
|
|
|
|
|
|
|
} |
658
|
15
|
50
|
|
|
|
656
|
unless ($version) { |
659
|
15
|
|
|
|
|
22
|
$version = '1'; |
660
|
|
|
|
|
|
|
} |
661
|
15
|
|
|
|
|
29
|
$parent_class_name = $parent_class_name . '::V' . $version; |
662
|
15
|
|
|
|
|
1789
|
eval "use $parent_class_name"; |
663
|
15
|
50
|
|
|
|
236
|
Carp::confess("Error using versioned module $parent_class_name!:\n$@") if $@; |
664
|
15
|
|
|
|
|
40
|
redo; |
665
|
|
|
|
|
|
|
} |
666
|
|
|
|
|
|
|
} |
667
|
|
|
|
|
|
|
} |
668
|
12799
|
|
|
|
|
23802
|
$new_class{is} = \@base_classes; |
669
|
|
|
|
|
|
|
} |
670
|
|
|
|
|
|
|
|
671
|
|
|
|
|
|
|
# allow parent classes to adjust the description in systematic ways |
672
|
24765
|
|
|
|
|
24709
|
my @additional_property_meta_attributes; |
673
|
24765
|
100
|
|
|
|
40770
|
unless ($bootstrapping) { |
674
|
12799
|
|
|
|
|
12220
|
for my $parent_class_name (@{ $new_class{is} }) { |
|
12799
|
|
|
|
|
22543
|
|
675
|
14365
|
|
|
|
|
23155
|
my $parent_class = $parent_class_name->__meta__; |
676
|
14365
|
50
|
|
|
|
35729
|
if (my $parent_meta_properties = $parent_class->{attributes_have}) { |
677
|
14365
|
|
|
|
|
26978
|
push @additional_property_meta_attributes, %$parent_meta_properties; |
678
|
|
|
|
|
|
|
} |
679
|
|
|
|
|
|
|
} |
680
|
|
|
|
|
|
|
} |
681
|
|
|
|
|
|
|
|
682
|
24765
|
|
|
|
|
62389
|
__PACKAGE__->_normalize_property_descriptions_during_normalize_class_description(\%new_class); |
683
|
|
|
|
|
|
|
|
684
|
24757
|
100
|
|
|
|
47691
|
unless ($bootstrapping) { |
685
|
12791
|
|
|
|
|
26128
|
%$meta_properties = (%$meta_properties, @additional_property_meta_attributes); |
686
|
|
|
|
|
|
|
|
687
|
|
|
|
|
|
|
# Inheriting from an abstract class that subclasses with a subclassify_by means that |
688
|
|
|
|
|
|
|
# this class' property named by that subclassify_by is actually a constant equal to this |
689
|
|
|
|
|
|
|
# class' class name |
690
|
|
|
|
|
|
|
PARENT_CLASS: |
691
|
12791
|
|
|
|
|
13967
|
foreach my $parent_class_name ( @{ $new_class{'is'} }) { |
|
12791
|
|
|
|
|
23063
|
|
692
|
14356
|
|
|
|
|
30173
|
my $parent_class_meta = $parent_class_name->__meta__(); |
693
|
14356
|
|
|
|
|
396315
|
foreach my $ancestor_class_meta ( $parent_class_meta->all_class_metas ) { |
694
|
37998
|
100
|
|
|
|
78880
|
if (my $subclassify_by = $ancestor_class_meta->subclassify_by) { |
695
|
155
|
50
|
|
|
|
847
|
if (not $instance_properties->{$subclassify_by}) { |
696
|
155
|
|
|
|
|
724
|
my %old_property = ( |
697
|
|
|
|
|
|
|
property_name => $subclassify_by, |
698
|
|
|
|
|
|
|
default_value => $class_name, |
699
|
|
|
|
|
|
|
is_constant => 1, |
700
|
|
|
|
|
|
|
is_classwide => 1, |
701
|
|
|
|
|
|
|
is_specified_in_module_header => 0, |
702
|
|
|
|
|
|
|
column_name => '', |
703
|
|
|
|
|
|
|
implied_by => $parent_class_meta->class_name . '::subclassify_by', |
704
|
|
|
|
|
|
|
); |
705
|
155
|
|
|
|
|
745
|
my %new_property = $class->_normalize_property_description1($subclassify_by, \%old_property, \%new_class); |
706
|
155
|
|
|
|
|
893
|
my %new_property2 = $class->_normalize_property_description2(\%new_property, \%new_class); |
707
|
155
|
|
|
|
|
534
|
$instance_properties->{$subclassify_by} = \%new_property2; |
708
|
155
|
|
|
|
|
725
|
last PARENT_CLASS; |
709
|
|
|
|
|
|
|
} |
710
|
|
|
|
|
|
|
} |
711
|
|
|
|
|
|
|
} |
712
|
|
|
|
|
|
|
} |
713
|
|
|
|
|
|
|
} |
714
|
|
|
|
|
|
|
|
715
|
24757
|
|
|
|
|
76931
|
my $meta_class_name = __PACKAGE__->_resolve_meta_class_name_for_class_name($class_name); |
716
|
24757
|
|
100
|
|
|
92287
|
$new_class{meta_class_name} ||= $meta_class_name; |
717
|
24757
|
|
|
|
|
69381
|
return \%new_class; |
718
|
|
|
|
|
|
|
} |
719
|
|
|
|
|
|
|
|
720
|
|
|
|
|
|
|
# Transform the id properties into a list of raw ids, |
721
|
|
|
|
|
|
|
# and move the property definitions into "id_implied" |
722
|
|
|
|
|
|
|
# where present so they can be processed below. |
723
|
|
|
|
|
|
|
sub _normalize_id_property_data { |
724
|
24810
|
|
|
24810
|
|
26300
|
my($old_class_desc, $new_class_desc) = @_; |
725
|
|
|
|
|
|
|
|
726
|
24810
|
|
|
|
|
30153
|
my $id_properties = $new_class_desc->{id_by}; |
727
|
24810
|
|
|
|
|
24234
|
my $property_rank = 0; |
728
|
24810
|
|
|
|
|
21167
|
my @replacement; |
729
|
24810
|
|
|
|
|
31342
|
my $pos = 0; |
730
|
|
|
|
|
|
|
|
731
|
24810
|
|
|
|
|
60482
|
for(my $n = 0; $n < @$id_properties; $n++) { |
732
|
6470
|
|
|
|
|
9163
|
my $name = $id_properties->[$n]; |
733
|
|
|
|
|
|
|
|
734
|
6470
|
|
|
|
|
9810
|
my $data = $id_properties->[$n+1]; |
735
|
6470
|
100
|
|
|
|
10609
|
if (ref($data)) { |
736
|
3237
|
|
66
|
|
|
15346
|
$old_class_desc->{id_implied}->{$name} ||= $data; |
737
|
3237
|
100
|
|
|
|
5502
|
if (my $obj_ids = $data->{id_by}) { |
738
|
301
|
100
|
|
|
|
1250
|
push @replacement, (ref($obj_ids) ? @$obj_ids : ($obj_ids)); |
739
|
|
|
|
|
|
|
} |
740
|
|
|
|
|
|
|
else { |
741
|
2936
|
|
|
|
|
3600
|
push @replacement, $name; |
742
|
|
|
|
|
|
|
} |
743
|
3237
|
|
|
|
|
3254
|
$n++; |
744
|
|
|
|
|
|
|
} |
745
|
|
|
|
|
|
|
else { |
746
|
3233
|
|
66
|
|
|
15927
|
$old_class_desc->{id_implied}->{$name} ||= {}; |
747
|
3233
|
|
|
|
|
4941
|
push @replacement, $name; |
748
|
|
|
|
|
|
|
} |
749
|
6470
|
|
|
|
|
18305
|
$old_class_desc->{id_implied}->{$name}->{'position_in_module_header'} = $pos++; |
750
|
|
|
|
|
|
|
} |
751
|
24810
|
|
|
|
|
44516
|
@$id_properties = @replacement; |
752
|
|
|
|
|
|
|
} |
753
|
|
|
|
|
|
|
|
754
|
|
|
|
|
|
|
# Given several different kinds of input, convert it into an arrayref |
755
|
|
|
|
|
|
|
sub _massage_field_into_arrayref { |
756
|
123882
|
|
|
123882
|
|
97593
|
my($class_desc, $field_name) = @_; |
757
|
|
|
|
|
|
|
|
758
|
123882
|
|
|
|
|
106337
|
my $value = $class_desc->{$field_name}; |
759
|
123882
|
|
|
|
|
98755
|
my $reftype = ref $value; |
760
|
123882
|
100
|
|
|
|
217742
|
if (! exists $class_desc->{$field_name}) { |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
761
|
89944
|
|
|
|
|
133297
|
$class_desc->{$field_name} = []; |
762
|
|
|
|
|
|
|
|
763
|
|
|
|
|
|
|
} elsif (! $reftype) { |
764
|
|
|
|
|
|
|
# It's a plain string, wrap it in an arrayref |
765
|
7017
|
|
|
|
|
16169
|
$class_desc->{$field_name} = [ $value ]; |
766
|
|
|
|
|
|
|
|
767
|
|
|
|
|
|
|
} elsif ($reftype eq 'HASH') { |
768
|
|
|
|
|
|
|
# Later code expects it to be a listref - convert it |
769
|
38
|
|
|
|
|
147
|
$class_desc->{$field_name} = [ %$value ]; |
770
|
|
|
|
|
|
|
|
771
|
|
|
|
|
|
|
} elsif ($reftype ne 'ARRAY') { |
772
|
0
|
|
|
|
|
0
|
my $class_name = $class_desc->{class_name}; |
773
|
0
|
|
|
|
|
0
|
Carp::croak "$class_name cannot initialize because its $field_name section is not a string, arrayref or hashref"; |
774
|
|
|
|
|
|
|
|
775
|
|
|
|
|
|
|
} |
776
|
|
|
|
|
|
|
} |
777
|
|
|
|
|
|
|
|
778
|
|
|
|
|
|
|
sub _normalize_property_descriptions_during_normalize_class_description { |
779
|
37503
|
|
|
37503
|
|
43606
|
my($class, $new_class) = @_; |
780
|
|
|
|
|
|
|
|
781
|
37503
|
|
|
|
|
40986
|
my $instance_properties = $new_class->{has}; |
782
|
|
|
|
|
|
|
|
783
|
|
|
|
|
|
|
# normalize the data behind the property descriptions |
784
|
37503
|
|
|
|
|
81456
|
my @property_names = keys %$instance_properties; |
785
|
37503
|
|
|
|
|
48067
|
for my $property_name (@property_names) { |
786
|
142339
|
|
|
|
|
107709
|
my %old_property = %{ $instance_properties->{$property_name} }; |
|
142339
|
|
|
|
|
633372
|
|
787
|
142339
|
|
|
|
|
294214
|
my %new_property = $class->_normalize_property_description1($property_name, \%old_property, $new_class); |
788
|
142335
|
|
|
|
|
419128
|
%new_property = $class->_normalize_property_description2(\%new_property, $new_class); |
789
|
142331
|
|
|
|
|
629908
|
$instance_properties->{$property_name} = \%new_property; |
790
|
|
|
|
|
|
|
} |
791
|
|
|
|
|
|
|
|
792
|
|
|
|
|
|
|
# Find 'via' properties where the to is '-filter' and rewrite them to |
793
|
|
|
|
|
|
|
# copy some attributes from the source property |
794
|
|
|
|
|
|
|
# This feels like a hack, but it makes other parts of the system easier by |
795
|
|
|
|
|
|
|
# not having to deal with -filter |
796
|
37495
|
|
|
|
|
47027
|
foreach my $property_name ( @property_names ) { |
797
|
142330
|
|
|
|
|
112464
|
my $property_data = $instance_properties->{$property_name}; |
798
|
142330
|
100
|
100
|
|
|
275002
|
if ($property_data->{'to'} && $property_data->{'to'} eq '-filter') { |
799
|
36
|
|
|
|
|
43
|
my $via = $property_data->{'via'}; |
800
|
36
|
|
|
|
|
34
|
my $via_property_data = $instance_properties->{$via}; |
801
|
36
|
50
|
|
|
|
65
|
unless ($via_property_data) { |
802
|
0
|
|
|
|
|
0
|
my $class_name = $new_class->{class_name}; |
803
|
0
|
|
|
|
|
0
|
Carp::croak "Cannot initialize class $class_name: Property '$property_name' filters '$via', but there is no property '$via'."; |
804
|
|
|
|
|
|
|
} |
805
|
|
|
|
|
|
|
|
806
|
36
|
|
|
|
|
41
|
$property_data->{'data_type'} = $via_property_data->{'data_type'}; |
807
|
36
|
|
|
|
|
40
|
$property_data->{'reverse_as'} = $via_property_data->{'reverse_as'}; |
808
|
36
|
50
|
|
|
|
67
|
if ($via_property_data->{'where'}) { |
809
|
0
|
|
|
|
|
0
|
unshift @{$property_data->{'where'}}, @{$via_property_data->{'where'}}; |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
810
|
|
|
|
|
|
|
} |
811
|
|
|
|
|
|
|
} |
812
|
|
|
|
|
|
|
} |
813
|
|
|
|
|
|
|
|
814
|
|
|
|
|
|
|
# Catch a mistake in the class definition where a property is 'via' |
815
|
|
|
|
|
|
|
# something, and its 'to' is the same as the via's reverse_as. This |
816
|
|
|
|
|
|
|
# ends up being a circular definition and generates junk SQL |
817
|
37495
|
|
|
|
|
54283
|
foreach my $property_name ( @property_names ) { |
818
|
142330
|
|
|
|
|
100127
|
my $property_data = $instance_properties->{$property_name}; |
819
|
142330
|
|
|
|
|
104875
|
my $via = $property_data->{'via'}; |
820
|
142330
|
|
|
|
|
95470
|
my $to = $property_data->{'to'}; |
821
|
142330
|
100
|
66
|
|
|
254295
|
if (defined($via) and defined($to)) { |
822
|
25947
|
|
|
|
|
21827
|
my $via_property_data = $instance_properties->{$via}; |
823
|
25947
|
100
|
100
|
|
|
60566
|
next unless ($via_property_data and $via_property_data->{'reverse_as'}); |
824
|
5788
|
50
|
|
|
|
11875
|
if ($via_property_data->{'reverse_as'} eq $to) { |
825
|
0
|
|
|
|
|
0
|
my $class_name = $new_class->{class_name}; |
826
|
0
|
|
|
|
|
0
|
Carp::croak("Cannot initialize class $class_name: Property '$property_name' defines " |
827
|
|
|
|
|
|
|
. "an incompatible relationship. Its 'to' is the same as reverse_as for property '$via'"); |
828
|
|
|
|
|
|
|
} |
829
|
|
|
|
|
|
|
} |
830
|
|
|
|
|
|
|
} |
831
|
|
|
|
|
|
|
} |
832
|
|
|
|
|
|
|
|
833
|
|
|
|
|
|
|
sub _process_class_definition_property_keys { |
834
|
24810
|
|
|
24810
|
|
27069
|
my($old_class, $new_class) = @_; |
835
|
|
|
|
|
|
|
|
836
|
24810
|
|
|
|
|
52807
|
my($class_name, $instance_properties, $meta_properties) = @$new_class{'class_name', 'has','attributes_have'}; |
837
|
24810
|
|
100
|
|
|
46309
|
$class_name ||= $new_class->{role_name}; # This is used by role construction, too |
838
|
|
|
|
|
|
|
|
839
|
|
|
|
|
|
|
# Flatten and format the property list(s) in the class description. |
840
|
|
|
|
|
|
|
# NOTE: we normalize the details at the end of normalizing the class description. |
841
|
24810
|
|
|
|
|
45910
|
my @keys = _class_definition_property_keys_in_processing_order($old_class); |
842
|
24810
|
|
|
|
|
40680
|
foreach my $key ( @keys ) { |
843
|
|
|
|
|
|
|
# parse the key to see if we're looking at instance or meta attributes, |
844
|
|
|
|
|
|
|
# and take the extra words as additional attribute meta-data. |
845
|
55891
|
|
|
|
|
47191
|
my @added_property_meta; |
846
|
|
|
|
|
|
|
my $properties; |
847
|
55891
|
100
|
|
|
|
149477
|
if ($key =~ /has/) { |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
848
|
|
|
|
|
|
|
@added_property_meta = |
849
|
27468
|
|
|
|
|
76341
|
grep { $_ ne 'has' } split(/[_-]/,$key); |
|
31316
|
|
|
|
|
57416
|
|
850
|
27468
|
|
|
|
|
29715
|
$properties = $instance_properties; |
851
|
|
|
|
|
|
|
} |
852
|
|
|
|
|
|
|
elsif ($key =~ /attributes_have/) { |
853
|
|
|
|
|
|
|
@added_property_meta = |
854
|
24810
|
100
|
|
|
|
74528
|
grep { $_ ne 'attributes' and $_ ne 'have' } split(/[_-]/,$key); |
|
49620
|
|
|
|
|
147923
|
|
855
|
24810
|
|
|
|
|
28222
|
$properties = $meta_properties; |
856
|
|
|
|
|
|
|
} |
857
|
|
|
|
|
|
|
elsif ($key eq 'id_implied') { |
858
|
|
|
|
|
|
|
# these are additions to the regular "has" list from complex identity properties |
859
|
3613
|
|
|
|
|
6582
|
$properties = $instance_properties; |
860
|
|
|
|
|
|
|
} |
861
|
|
|
|
|
|
|
else { |
862
|
0
|
|
|
|
|
0
|
die "Odd key $key?"; |
863
|
|
|
|
|
|
|
} |
864
|
55891
|
|
|
|
|
58515
|
@added_property_meta = map { 'is_' . $_ => 1 } @added_property_meta; |
|
3848
|
|
|
|
|
9845
|
|
865
|
|
|
|
|
|
|
|
866
|
|
|
|
|
|
|
# the property data can be a string, array, or hash as they come in |
867
|
|
|
|
|
|
|
# convert string, hash and () into an array |
868
|
55891
|
|
|
|
|
67606
|
my $property_data = delete $old_class->{$key}; |
869
|
|
|
|
|
|
|
|
870
|
55891
|
|
|
|
|
44172
|
my @tmp; |
871
|
55891
|
100
|
|
|
|
128805
|
if (!ref($property_data)) { |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
872
|
24449
|
50
|
|
|
|
35629
|
if (defined($property_data)) { |
873
|
0
|
|
|
|
|
0
|
@tmp = split(/\s+/, $property_data); |
874
|
|
|
|
|
|
|
} |
875
|
|
|
|
|
|
|
else { |
876
|
24449
|
|
|
|
|
26167
|
@tmp = (); |
877
|
|
|
|
|
|
|
} |
878
|
|
|
|
|
|
|
} |
879
|
|
|
|
|
|
|
elsif (ref($property_data) eq 'HASH') { |
880
|
|
|
|
|
|
|
@tmp = map { |
881
|
3978
|
|
|
|
|
15144
|
($_ => $property_data->{$_}) |
|
6635
|
|
|
|
|
14768
|
|
882
|
|
|
|
|
|
|
} sort keys %$property_data; |
883
|
|
|
|
|
|
|
} |
884
|
|
|
|
|
|
|
elsif (ref($property_data) eq 'ARRAY') { |
885
|
27464
|
|
|
|
|
50449
|
@tmp = @$property_data; |
886
|
|
|
|
|
|
|
} |
887
|
|
|
|
|
|
|
else { |
888
|
0
|
|
|
|
|
0
|
die "Unrecognized data $property_data appearing as property list!"; |
889
|
|
|
|
|
|
|
} |
890
|
|
|
|
|
|
|
|
891
|
|
|
|
|
|
|
# process the array of property specs |
892
|
55891
|
|
|
|
|
49427
|
my $pos = 0; |
893
|
55891
|
|
|
|
|
101615
|
while (my $name = shift @tmp) { |
894
|
101775
|
|
|
|
|
62198
|
my $params; |
895
|
101775
|
100
|
|
|
|
105730
|
if (ref($tmp[0])) { |
896
|
100903
|
|
|
|
|
67593
|
$params = shift @tmp; |
897
|
100903
|
50
|
|
|
|
132967
|
unless (ref($params) eq 'HASH') { |
898
|
0
|
|
|
|
|
0
|
my $seen_type = ref($params); |
899
|
0
|
|
|
|
|
0
|
Carp::confess("class $class_name property $name has a $seen_type reference instead of a hashref describing its meta-attributes!"); |
900
|
|
|
|
|
|
|
} |
901
|
100903
|
100
|
|
|
|
167032
|
%$params = (@added_property_meta, %$params) if @added_property_meta; |
902
|
|
|
|
|
|
|
} |
903
|
|
|
|
|
|
|
else { |
904
|
872
|
|
|
|
|
1458
|
$params = { @added_property_meta }; |
905
|
|
|
|
|
|
|
} |
906
|
|
|
|
|
|
|
|
907
|
101775
|
100
|
|
|
|
138235
|
unless (exists $params->{'position_in_module_header'}) { |
908
|
79744
|
|
|
|
|
65189
|
$params->{'position_in_module_header'} = $pos++; |
909
|
|
|
|
|
|
|
} |
910
|
101775
|
100
|
|
|
|
123069
|
unless (exists $params->{is_specified_in_module_header}) { |
911
|
80537
|
|
|
|
|
116846
|
$params->{is_specified_in_module_header} = $class_name . '::' . $key; |
912
|
|
|
|
|
|
|
} |
913
|
|
|
|
|
|
|
|
914
|
|
|
|
|
|
|
# Indirect properties can mention the same property name more than once. To |
915
|
|
|
|
|
|
|
# avoid stomping over existing property data with this other property data, |
916
|
|
|
|
|
|
|
# merge the new info into the existing hash. Otherwise, the new property name |
917
|
|
|
|
|
|
|
# gets an empty hash of info |
918
|
101775
|
100
|
|
|
|
109542
|
if ($properties->{$name}) { |
919
|
|
|
|
|
|
|
# this property already exists, but is also implied by some other property which added it to the end of the listed |
920
|
|
|
|
|
|
|
# extend the existing definition |
921
|
6131
|
|
|
|
|
14824
|
foreach my $key ( keys %$params ) { |
922
|
32890
|
100
|
100
|
|
|
81934
|
next if ($key eq 'is_specified_in_module_header' || $key eq 'position_in_module_header'); |
923
|
|
|
|
|
|
|
# once a property gets set to is_optional => 0, it stays there, even if it's later set to 1 |
924
|
|
|
|
|
|
|
next if ($key eq 'is_optional' |
925
|
|
|
|
|
|
|
and |
926
|
|
|
|
|
|
|
exists($properties->{$name}->{'is_optional'}) |
927
|
|
|
|
|
|
|
and |
928
|
|
|
|
|
|
|
defined($properties->{$name}->{'is_optional'}) |
929
|
|
|
|
|
|
|
and |
930
|
20628
|
100
|
100
|
|
|
34006
|
$properties->{$name}->{'is_optional'} == 0); |
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
931
|
20498
|
|
|
|
|
22978
|
$properties->{$name}->{$key} = $params->{$key}; |
932
|
|
|
|
|
|
|
} |
933
|
6131
|
|
|
|
|
8234
|
$params = $properties->{$name}; |
934
|
|
|
|
|
|
|
} else { |
935
|
95644
|
|
|
|
|
111918
|
$properties->{$name} = $params; |
936
|
|
|
|
|
|
|
} |
937
|
|
|
|
|
|
|
|
938
|
|
|
|
|
|
|
# a single calculate_from can be a simple string, convert to a listref |
939
|
101775
|
100
|
|
|
|
135131
|
if (my $calculate_from = $params->{'calculate_from'}) { |
940
|
669
|
100
|
|
|
|
2349
|
$params->{'calculate_from'} = [ $calculate_from ] unless (ref($calculate_from) eq 'ARRAY'); |
941
|
|
|
|
|
|
|
} |
942
|
|
|
|
|
|
|
|
943
|
101775
|
100
|
|
|
|
124885
|
if (my $id_by = $params->{id_by}) { |
944
|
4690
|
100
|
|
|
|
12742
|
$id_by = [ $id_by ] unless ref($id_by) eq 'ARRAY'; |
945
|
4690
|
|
|
|
|
6702
|
my @id_by_names; |
946
|
4690
|
|
|
|
|
11139
|
while (@$id_by) { |
947
|
5131
|
|
|
|
|
6164
|
my $id_name = shift @$id_by; |
948
|
5131
|
|
|
|
|
5084
|
my $params2; |
949
|
5131
|
50
|
|
|
|
8707
|
if (ref($id_by->[0])) { |
950
|
0
|
|
|
|
|
0
|
$params2 = shift @$id_by; |
951
|
|
|
|
|
|
|
} |
952
|
|
|
|
|
|
|
else { |
953
|
5131
|
|
|
|
|
5881
|
$params2 = {}; |
954
|
|
|
|
|
|
|
} |
955
|
5131
|
|
|
|
|
8480
|
for my $p (@UR::Object::Type::meta_id_ref_shared_properties) { |
956
|
61572
|
100
|
|
|
|
83208
|
if (exists $params->{$p}) { |
957
|
8368
|
|
|
|
|
10324
|
$params2->{$p} = $params->{$p}; |
958
|
|
|
|
|
|
|
} |
959
|
|
|
|
|
|
|
} |
960
|
5131
|
|
|
|
|
7608
|
$params2->{implied_by} = $name; |
961
|
5131
|
|
|
|
|
6042
|
$params2->{is_specified_in_module_header} = 0; |
962
|
|
|
|
|
|
|
|
963
|
5131
|
|
|
|
|
6905
|
push @id_by_names, $id_name; |
964
|
5131
|
|
|
|
|
10832
|
push @tmp, $id_name, $params2; |
965
|
|
|
|
|
|
|
} |
966
|
4690
|
|
|
|
|
6661
|
$params->{id_by} = \@id_by_names; |
967
|
|
|
|
|
|
|
} |
968
|
|
|
|
|
|
|
|
969
|
101775
|
100
|
|
|
|
212327
|
if (my $id_class_by = $params->{'id_class_by'}) { |
970
|
546
|
50
|
|
|
|
1392
|
if (ref $id_class_by) { |
971
|
0
|
|
|
|
|
0
|
Carp::croak("Cannot initialize class $class_name: " |
972
|
|
|
|
|
|
|
. "Property $name has an 'id_class_by' that is not a plain string"); |
973
|
|
|
|
|
|
|
} |
974
|
546
|
|
|
|
|
2560
|
push @tmp, $id_class_by, { implied_by => $name, is_specified_in_module_header => 0 }; |
975
|
|
|
|
|
|
|
} |
976
|
|
|
|
|
|
|
|
977
|
|
|
|
|
|
|
} # next property in group |
978
|
|
|
|
|
|
|
|
979
|
|
|
|
|
|
|
# id-by properties' metadata can influence the id-ed-by property metadata |
980
|
55891
|
|
|
|
|
130093
|
for my $pdata (values %$properties) { |
981
|
116162
|
100
|
|
|
|
155412
|
next unless $pdata->{id_by}; |
982
|
6079
|
|
|
|
|
5848
|
for my $id_property (@{ $pdata->{id_by} }) { |
|
6079
|
|
|
|
|
9558
|
|
983
|
7382
|
|
|
|
|
7772
|
my $id_pdata = $properties->{$id_property}; |
984
|
7382
|
|
|
|
|
8154
|
for my $p (@UR::Object::Type::meta_id_ref_shared_properties) { |
985
|
88584
|
100
|
100
|
|
|
424312
|
if (exists $id_pdata->{$p} xor exists $pdata->{$p}) { |
|
|
100
|
66
|
|
|
|
|
|
|
|
100
|
|
|
|
|
986
|
|
|
|
|
|
|
# if one or the other specifies a value, copy it to the one that's missing |
987
|
6918
|
|
66
|
|
|
17001
|
$id_pdata->{$p} = $pdata->{$p} = $id_pdata->{$p} || $pdata->{$p}; |
988
|
|
|
|
|
|
|
} elsif (!exists $id_pdata->{$p} and !exists $pdata->{$p} and exists $UR::Object::Property::defaults{$p}) { |
989
|
|
|
|
|
|
|
# if neither has a value, use the default for both |
990
|
31593
|
|
|
|
|
52238
|
$id_pdata->{$p} = $pdata->{$p} = $UR::Object::Property::defaults{$p}; |
991
|
|
|
|
|
|
|
} |
992
|
|
|
|
|
|
|
} |
993
|
|
|
|
|
|
|
} |
994
|
|
|
|
|
|
|
} |
995
|
|
|
|
|
|
|
|
996
|
|
|
|
|
|
|
} |
997
|
|
|
|
|
|
|
} |
998
|
|
|
|
|
|
|
|
999
|
|
|
|
|
|
|
sub compose_roles { |
1000
|
12763
|
|
|
12763
|
1
|
18596
|
my($class, $desc) = @_; |
1001
|
|
|
|
|
|
|
|
1002
|
12763
|
|
|
|
|
64888
|
UR::Role::Prototype->_apply_roles_to_class_desc($desc); |
1003
|
12738
|
|
|
|
|
27919
|
$class->_normalize_property_descriptions_during_normalize_class_description($desc); |
1004
|
|
|
|
|
|
|
} |
1005
|
|
|
|
|
|
|
|
1006
|
|
|
|
|
|
|
# Return the order to process the has, has_optional, has_constant, etc keys |
1007
|
|
|
|
|
|
|
sub _class_definition_property_keys_in_processing_order { |
1008
|
24810
|
|
|
24810
|
|
27289
|
my $class_hashref = shift; |
1009
|
|
|
|
|
|
|
|
1010
|
24810
|
|
|
|
|
23261
|
my @order; |
1011
|
|
|
|
|
|
|
|
1012
|
|
|
|
|
|
|
# we want to hit 'id_implied' first to preserve position_ and is_specified_ keys |
1013
|
24810
|
100
|
|
|
|
52296
|
push(@order, 'id_implied') if exists $class_hashref->{id_implied}; |
1014
|
|
|
|
|
|
|
|
1015
|
|
|
|
|
|
|
# 'has' next so is_optional can get set to 0 in case the same property also appears in has_optional |
1016
|
24810
|
50
|
|
|
|
56762
|
push(@order, 'has') if exists $class_hashref->{has}; |
1017
|
|
|
|
|
|
|
|
1018
|
|
|
|
|
|
|
# everything else |
1019
|
24810
|
|
|
|
|
50105
|
push @order, grep { /has_|attributes_have/ } keys %$class_hashref; |
|
56155
|
|
|
|
|
201844
|
|
1020
|
|
|
|
|
|
|
|
1021
|
24810
|
|
|
|
|
57591
|
return @order; |
1022
|
|
|
|
|
|
|
} |
1023
|
|
|
|
|
|
|
|
1024
|
|
|
|
|
|
|
|
1025
|
|
|
|
|
|
|
|
1026
|
|
|
|
|
|
|
sub _normalize_property_description1 { |
1027
|
142511
|
|
|
142511
|
|
124031
|
my $class = shift; |
1028
|
142511
|
|
|
|
|
103322
|
my $property_name = shift; |
1029
|
142511
|
|
|
|
|
102309
|
my $property_data = shift; |
1030
|
142511
|
|
66
|
|
|
206529
|
my $class_data = shift || $class; |
1031
|
142511
|
|
|
|
|
123699
|
my $class_name = $class_data->{class_name}; |
1032
|
142511
|
|
|
|
|
442169
|
my %old_property = %$property_data; |
1033
|
142511
|
|
|
|
|
616655
|
my %new_class = %$class_data; |
1034
|
|
|
|
|
|
|
|
1035
|
142511
|
100
|
|
|
|
290981
|
if (exists $old_property{unrecognized_meta_attributes}) { |
1036
|
113
|
|
|
|
|
135
|
%old_property = (%{delete $old_property{unrecognized_meta_attributes}}, %old_property); |
|
113
|
|
|
|
|
941
|
|
1037
|
|
|
|
|
|
|
} |
1038
|
|
|
|
|
|
|
|
1039
|
142511
|
|
|
|
|
124347
|
delete $old_property{source}; |
1040
|
|
|
|
|
|
|
|
1041
|
142511
|
50
|
100
|
|
|
252579
|
if ($old_property{implied_by} and $old_property{implied_by} eq $property_name) { |
1042
|
0
|
|
|
|
|
0
|
$class->warning_message("Cleaning up odd self-referential 'implied_by' on $class_name $property_name"); |
1043
|
0
|
|
|
|
|
0
|
delete $old_property{implied_by}; |
1044
|
|
|
|
|
|
|
} |
1045
|
|
|
|
|
|
|
|
1046
|
|
|
|
|
|
|
# Only 1 of is_abstract, is_concrete or is_final may be set |
1047
|
|
|
|
|
|
|
{ |
1048
|
267
|
|
|
267
|
|
1530
|
no warnings 'uninitialized'; |
|
267
|
|
|
|
|
440
|
|
|
267
|
|
|
|
|
392982
|
|
|
142511
|
|
|
|
|
104154
|
|
1049
|
|
|
|
|
|
|
my $modifier_sum = $old_property{is_abstract} |
1050
|
|
|
|
|
|
|
+ $old_property{is_concrete} |
1051
|
142511
|
|
|
|
|
199454
|
+ $old_property{is_final}; |
1052
|
|
|
|
|
|
|
|
1053
|
142511
|
50
|
|
|
|
312701
|
if ($modifier_sum > 1) { |
|
|
100
|
|
|
|
|
|
1054
|
0
|
|
|
|
|
0
|
Carp::confess("abstract/concrete/final are mutually exclusive. Error in class definition for $class_name property $property_name!"); |
1055
|
|
|
|
|
|
|
} elsif ($modifier_sum == 0) { |
1056
|
79036
|
|
|
|
|
81846
|
$old_property{is_concrete} = 1; |
1057
|
|
|
|
|
|
|
} |
1058
|
|
|
|
|
|
|
} |
1059
|
|
|
|
|
|
|
|
1060
|
142511
|
|
|
|
|
216913
|
my %new_property = ( |
1061
|
|
|
|
|
|
|
class_name => $class_name, |
1062
|
|
|
|
|
|
|
property_name => $property_name, |
1063
|
|
|
|
|
|
|
); |
1064
|
|
|
|
|
|
|
|
1065
|
142511
|
|
|
|
|
1892567
|
for my $mapping ( |
1066
|
|
|
|
|
|
|
[ property_type => qw/resolution/], |
1067
|
|
|
|
|
|
|
[ class_name => qw//], |
1068
|
|
|
|
|
|
|
[ property_name => qw//], |
1069
|
|
|
|
|
|
|
[ column_name => qw/sql/], |
1070
|
|
|
|
|
|
|
[ constraint_name => qw//], |
1071
|
|
|
|
|
|
|
[ data_length => qw/len/], |
1072
|
|
|
|
|
|
|
[ data_type => qw/type is isa is_a/], |
1073
|
|
|
|
|
|
|
[ calculated_default => qw//], |
1074
|
|
|
|
|
|
|
[ default_value => qw/default value/], |
1075
|
|
|
|
|
|
|
[ valid_values => qw//], |
1076
|
|
|
|
|
|
|
[ example_values => qw//], |
1077
|
|
|
|
|
|
|
[ doc => qw/description/], |
1078
|
|
|
|
|
|
|
[ is_optional => qw/is_nullable nullable optional/], |
1079
|
|
|
|
|
|
|
[ is_transient => qw//], |
1080
|
|
|
|
|
|
|
[ is_volatile => qw//], |
1081
|
|
|
|
|
|
|
[ is_constant => qw//], |
1082
|
|
|
|
|
|
|
[ is_classwide => qw/is_class_wide/], |
1083
|
|
|
|
|
|
|
[ is_delegated => qw//], |
1084
|
|
|
|
|
|
|
[ is_calculated => qw//], |
1085
|
|
|
|
|
|
|
[ is_mutable => qw//], |
1086
|
|
|
|
|
|
|
[ is_transactional => qw//], |
1087
|
|
|
|
|
|
|
[ is_abstract => qw//], |
1088
|
|
|
|
|
|
|
[ is_concrete => qw//], |
1089
|
|
|
|
|
|
|
[ is_final => qw//], |
1090
|
|
|
|
|
|
|
[ is_many => qw//], |
1091
|
|
|
|
|
|
|
[ is_deprecated => qw//], |
1092
|
|
|
|
|
|
|
[ is_undocumented => qw//], |
1093
|
|
|
|
|
|
|
[ is_numeric => qw//], |
1094
|
|
|
|
|
|
|
[ is_id => qw//], |
1095
|
|
|
|
|
|
|
[ id_by => qw//], |
1096
|
|
|
|
|
|
|
[ id_class_by => qw//], |
1097
|
|
|
|
|
|
|
[ specify_by => qw//], |
1098
|
|
|
|
|
|
|
[ order_by => qw//], |
1099
|
|
|
|
|
|
|
[ access_as => qw//], |
1100
|
|
|
|
|
|
|
[ via => qw//], |
1101
|
|
|
|
|
|
|
[ to => qw//], |
1102
|
|
|
|
|
|
|
[ where => qw/restrict filter/], |
1103
|
|
|
|
|
|
|
[ implied_by => qw//], |
1104
|
|
|
|
|
|
|
[ calculate => qw//], |
1105
|
|
|
|
|
|
|
[ calculate_from => qw//], |
1106
|
|
|
|
|
|
|
[ calculate_perl => qw/calc_perl/], |
1107
|
|
|
|
|
|
|
[ calculate_sql => qw/calc_sql/], |
1108
|
|
|
|
|
|
|
[ calculate_js => qw//], |
1109
|
|
|
|
|
|
|
[ reverse_as => qw/reverse_id_by im_its/], |
1110
|
|
|
|
|
|
|
[ is_legacy_eav => qw//], |
1111
|
|
|
|
|
|
|
[ is_dimension => qw//], |
1112
|
|
|
|
|
|
|
[ is_specified_in_module_header => qw//], |
1113
|
|
|
|
|
|
|
[ position_in_module_header => qw//], |
1114
|
|
|
|
|
|
|
[ singular_name => qw//], |
1115
|
|
|
|
|
|
|
[ plural_name => qw//], |
1116
|
|
|
|
|
|
|
) { |
1117
|
7125507
|
|
|
|
|
4568369
|
my $primary_field_name = $mapping->[0]; |
1118
|
|
|
|
|
|
|
|
1119
|
7125507
|
|
|
|
|
3859064
|
my $found_key; |
1120
|
7125507
|
|
|
|
|
4772131
|
foreach my $key ( @$mapping ) { |
1121
|
9975712
|
100
|
|
|
|
12065808
|
if (exists $old_property{$key}) { |
1122
|
1826068
|
100
|
|
|
|
1925409
|
if ($found_key) { |
1123
|
1
|
|
|
|
|
2
|
my @keys = grep { exists $old_property{$_} } @$mapping; |
|
5
|
|
|
|
|
6
|
|
1124
|
1
|
|
|
|
|
27
|
Carp::croak("Invalid class definition for $class_name in property '$property_name'. The keys " |
1125
|
|
|
|
|
|
|
. join(', ',$found_key,@keys) . " are all synonyms for $primary_field_name"); |
1126
|
|
|
|
|
|
|
} |
1127
|
1826067
|
|
|
|
|
1343520
|
$found_key = $key; |
1128
|
|
|
|
|
|
|
} |
1129
|
|
|
|
|
|
|
} |
1130
|
|
|
|
|
|
|
|
1131
|
7125506
|
100
|
|
|
|
9708783
|
if ($found_key) { |
|
|
100
|
|
|
|
|
|
1132
|
1826066
|
|
|
|
|
2104046
|
$new_property{$primary_field_name} = delete $old_property{$found_key}; |
1133
|
|
|
|
|
|
|
} elsif (exists $UR::Object::Property::defaults{$primary_field_name}) { |
1134
|
896935
|
|
|
|
|
949613
|
$new_property{$primary_field_name} = $UR::Object::Property::defaults{$primary_field_name}; |
1135
|
|
|
|
|
|
|
} |
1136
|
|
|
|
|
|
|
} |
1137
|
|
|
|
|
|
|
|
1138
|
142510
|
50
|
|
|
|
779753
|
if (my $data = delete $old_property{delegate}) { |
1139
|
0
|
0
|
0
|
|
|
0
|
if ($data->{via} =~ /^eav_/ and $data->{to} eq 'value') { |
1140
|
0
|
|
|
|
|
0
|
$new_property{is_legacy_eav} = 1; |
1141
|
|
|
|
|
|
|
} |
1142
|
|
|
|
|
|
|
else { |
1143
|
0
|
|
|
|
|
0
|
die "Odd delegation for $property_name: " |
1144
|
|
|
|
|
|
|
. Data::Dumper::Dumper($data); |
1145
|
|
|
|
|
|
|
} |
1146
|
|
|
|
|
|
|
} |
1147
|
|
|
|
|
|
|
|
1148
|
142510
|
100
|
66
|
|
|
216333
|
if ($new_property{default_value} && $new_property{calculated_default}) { |
1149
|
1
|
|
|
|
|
17
|
die qq(Can't initialize class $class_name: Property '$new_property{property_name}' has both default_value and calculated_default specified.); |
1150
|
|
|
|
|
|
|
} |
1151
|
|
|
|
|
|
|
|
1152
|
142509
|
100
|
|
|
|
189317
|
if ($new_property{calculated_default}) { |
1153
|
18
|
100
|
|
|
|
44
|
if ($new_property{calculated_default} eq 1) { |
1154
|
4
|
|
|
|
|
10
|
$new_property{calculated_default} = '__default_' . $new_property{property_name} . '__'; |
1155
|
|
|
|
|
|
|
} |
1156
|
|
|
|
|
|
|
|
1157
|
18
|
|
|
|
|
25
|
my $ref = ref $new_property{calculated_default}; |
1158
|
18
|
50
|
66
|
|
|
57
|
if ($ref and $ref ne 'CODE') { |
1159
|
0
|
|
|
|
|
0
|
die qq(Can't initialize class $class_name: Property '$new_property{property_name}' has calculated_default specified as a $ref ref but it must be a method name or coderef.); |
1160
|
|
|
|
|
|
|
} |
1161
|
|
|
|
|
|
|
|
1162
|
18
|
100
|
|
|
|
26
|
unless ($ref) { |
1163
|
6
|
|
|
|
|
30
|
my $method = $class_name->can($new_property{calculated_default}); |
1164
|
6
|
100
|
|
|
|
262
|
unless ($method) { |
1165
|
2
|
|
|
|
|
26
|
die qq(Can't initialize class $class_name: Property '$new_property{property_name}' has calculated_default specified as '$new_property{calculated_default}' but method does not exist.); |
1166
|
|
|
|
|
|
|
} |
1167
|
4
|
|
|
|
|
6
|
$new_property{calculated_default} = $method; |
1168
|
|
|
|
|
|
|
} |
1169
|
|
|
|
|
|
|
} |
1170
|
|
|
|
|
|
|
|
1171
|
142507
|
50
|
66
|
|
|
208686
|
if ($new_property{id_by} && $new_property{reverse_as}) { |
1172
|
0
|
|
|
|
|
0
|
die qq(Can't initialize class $class_name: Property '$new_property{property_name}' has both id_by and reverse_as specified.); |
1173
|
|
|
|
|
|
|
} |
1174
|
|
|
|
|
|
|
|
1175
|
142507
|
100
|
|
|
|
196419
|
if ($new_property{data_type}) { |
1176
|
85778
|
50
|
|
|
|
197084
|
if (my (undef, $length) = $new_property{data_type} =~ m/(\s*)\((\d+)\)$/) { |
1177
|
0
|
|
|
|
|
0
|
$new_property{data_length} = $length; |
1178
|
|
|
|
|
|
|
} |
1179
|
85778
|
50
|
33
|
|
|
226731
|
if ($new_property{data_type} =~ m/[^\w:]/ |
|
|
|
66
|
|
|
|
|
1180
|
|
|
|
|
|
|
and |
1181
|
|
|
|
|
|
|
(!ref($new_property{data_type}) or !$new_property{data_type}->isa('UR::Role::Param')) |
1182
|
|
|
|
|
|
|
) { |
1183
|
|
|
|
|
|
|
Carp::croak("Can't initialize class $class_name: Property '" . $new_property{property_name} |
1184
|
0
|
|
|
|
|
0
|
. "' has metadata for is/data_type that does not look like a class name ($new_property{data_type})"); |
1185
|
|
|
|
|
|
|
} |
1186
|
|
|
|
|
|
|
} |
1187
|
|
|
|
|
|
|
|
1188
|
142507
|
100
|
|
|
|
195091
|
if (%old_property) { |
1189
|
227
|
|
|
|
|
313
|
$new_property{unrecognized_meta_attributes} = \%old_property; |
1190
|
227
|
|
|
|
|
1896
|
%new_property = (%old_property, %new_property); |
1191
|
|
|
|
|
|
|
} |
1192
|
|
|
|
|
|
|
|
1193
|
142507
|
|
|
|
|
1400974
|
return %new_property; |
1194
|
|
|
|
|
|
|
} |
1195
|
|
|
|
|
|
|
|
1196
|
|
|
|
|
|
|
sub _normalize_property_description2 { |
1197
|
142490
|
|
|
142490
|
|
127802
|
my $class = shift; |
1198
|
142490
|
|
|
|
|
101233
|
my $property_data = shift; |
1199
|
142490
|
|
33
|
|
|
209312
|
my $class_data = shift || $class; |
1200
|
|
|
|
|
|
|
|
1201
|
142490
|
|
|
|
|
129943
|
my $property_name = $property_data->{property_name}; |
1202
|
142490
|
|
|
|
|
111403
|
my $class_name = $property_data->{class_name}; |
1203
|
|
|
|
|
|
|
|
1204
|
142490
|
|
|
|
|
686413
|
my %new_property = %$property_data; |
1205
|
142490
|
|
|
|
|
697635
|
my %new_class = %$class_data; |
1206
|
|
|
|
|
|
|
|
1207
|
142490
|
100
|
100
|
|
|
419563
|
if (grep { $_ ne 'is_calculated' && $_ ne 'calculated_default' && /calc/ } keys %new_property) { |
|
2913813
|
100
|
|
|
|
9908530
|
|
1208
|
3700
|
|
|
|
|
5045
|
$new_property{is_calculated} = 1; |
1209
|
|
|
|
|
|
|
} |
1210
|
|
|
|
|
|
|
|
1211
|
142490
|
100
|
66
|
|
|
587129
|
if ($new_property{via} |
|
|
|
33
|
|
|
|
|
|
|
|
66
|
|
|
|
|
1212
|
|
|
|
|
|
|
|| $new_property{to} |
1213
|
|
|
|
|
|
|
|| $new_property{id_by} |
1214
|
|
|
|
|
|
|
|| $new_property{reverse_as} |
1215
|
|
|
|
|
|
|
) { |
1216
|
36707
|
|
|
|
|
35690
|
$new_property{is_delegated} = 1; |
1217
|
36707
|
100
|
100
|
|
|
111448
|
if (defined $new_property{via} and not defined $new_property{to}) { |
1218
|
1902
|
|
|
|
|
2355
|
$new_property{to} = $property_name; |
1219
|
|
|
|
|
|
|
} |
1220
|
|
|
|
|
|
|
} |
1221
|
|
|
|
|
|
|
|
1222
|
142490
|
100
|
|
|
|
209801
|
if (!defined($new_property{is_mutable})) { |
1223
|
75280
|
100
|
100
|
|
|
208769
|
if ($new_property{is_delegated} |
|
|
|
66
|
|
|
|
|
1224
|
|
|
|
|
|
|
or |
1225
|
|
|
|
|
|
|
(defined $class_data->{'subclassify_by'} and $class_data->{'subclassify_by'} eq $property_name) |
1226
|
|
|
|
|
|
|
) { |
1227
|
16565
|
|
|
|
|
15265
|
$new_property{is_mutable} = 0; |
1228
|
|
|
|
|
|
|
} |
1229
|
|
|
|
|
|
|
else { |
1230
|
58715
|
|
|
|
|
51393
|
$new_property{is_mutable} = 1; |
1231
|
|
|
|
|
|
|
} |
1232
|
|
|
|
|
|
|
} |
1233
|
|
|
|
|
|
|
|
1234
|
|
|
|
|
|
|
# For classes that have (or pretend to have) tables, the Property objects |
1235
|
|
|
|
|
|
|
# should get their column_name property automatically filled in |
1236
|
142490
|
|
|
|
|
103294
|
my $the_data_source; |
1237
|
142490
|
100
|
|
|
|
282247
|
if (ref($new_class{'data_source_id'}) eq 'HASH') { |
|
|
100
|
|
|
|
|
|
1238
|
|
|
|
|
|
|
# This is an inline-defined data source |
1239
|
96
|
|
|
|
|
131
|
$the_data_source = $new_class{'data_source_id'}->{'is'}; |
1240
|
|
|
|
|
|
|
} elsif ($new_class{'data_source_id'}) { |
1241
|
5785
|
|
|
|
|
6674
|
$the_data_source = $new_class{'data_source_id'}; |
1242
|
|
|
|
|
|
|
# using local() here to save $@ doesn't work. You end up with the |
1243
|
|
|
|
|
|
|
# error "Unknown error" if one of the parent classes of the data source has |
1244
|
|
|
|
|
|
|
# some kind of problem |
1245
|
5785
|
|
|
|
|
5843
|
my $dollarat = $@; |
1246
|
5785
|
|
|
|
|
5303
|
$@ = ''; |
1247
|
5785
|
|
100
|
|
|
19547
|
$the_data_source = UR::DataSource->get($the_data_source) || eval { $the_data_source->get() }; |
1248
|
5785
|
100
|
|
|
|
10533
|
unless ($the_data_source) { |
1249
|
|
|
|
|
|
|
my $error = "Can't resolve data source from value '" |
1250
|
4
|
|
|
|
|
14
|
. $new_class{'data_source_id'} |
1251
|
|
|
|
|
|
|
. "' in class definition for $class_name"; |
1252
|
4
|
50
|
|
|
|
8
|
if ($@) { |
1253
|
4
|
|
|
|
|
9
|
$error .= "\n$@"; |
1254
|
|
|
|
|
|
|
} |
1255
|
4
|
|
|
|
|
741
|
Carp::croak($error); |
1256
|
|
|
|
|
|
|
} |
1257
|
5781
|
|
|
|
|
6397
|
$@ = $dollarat; |
1258
|
|
|
|
|
|
|
} |
1259
|
|
|
|
|
|
|
# UR::DataSource::File-backed classes don't have table_names, but for querying/saving to |
1260
|
|
|
|
|
|
|
# work property, their properties still have to have column_name filled in |
1261
|
142486
|
100
|
66
|
|
|
372767
|
if (($new_class{table_name} or ($the_data_source and ($the_data_source->initializer_should_create_column_name_for_class_properties()))) |
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
66
|
|
|
|
|
1262
|
|
|
|
|
|
|
and not exists($new_property{column_name}) # They didn't supply a column_name |
1263
|
|
|
|
|
|
|
and not $new_property{is_transient} |
1264
|
|
|
|
|
|
|
and not $new_property{is_delegated} |
1265
|
|
|
|
|
|
|
and not $new_property{is_calculated} |
1266
|
|
|
|
|
|
|
and not $new_property{is_legacy_eav} |
1267
|
|
|
|
|
|
|
) { |
1268
|
920
|
|
|
|
|
1392
|
$new_property{column_name} = $new_property{property_name}; |
1269
|
920
|
50
|
66
|
|
|
4288
|
if ($the_data_source and $the_data_source->table_and_column_names_are_upper_case) { |
1270
|
0
|
|
|
|
|
0
|
$new_property{column_name} = uc($new_property{column_name}); |
1271
|
|
|
|
|
|
|
} |
1272
|
|
|
|
|
|
|
} |
1273
|
|
|
|
|
|
|
|
1274
|
142486
|
50
|
66
|
|
|
232063
|
if ($new_property{order_by} and not $new_property{is_many}) { |
1275
|
0
|
|
|
|
|
0
|
die "Cannot use order_by except on is_many properties!"; |
1276
|
|
|
|
|
|
|
} |
1277
|
|
|
|
|
|
|
|
1278
|
142486
|
50
|
66
|
|
|
228320
|
if ($new_property{specify_by} and not $new_property{is_many}) { |
1279
|
0
|
|
|
|
|
0
|
die "Cannot use specify_by except on is_many properties!"; |
1280
|
|
|
|
|
|
|
} |
1281
|
|
|
|
|
|
|
|
1282
|
142486
|
50
|
66
|
|
|
246867
|
if ($new_property{implied_by} and $new_property{implied_by} eq $property_name) { |
1283
|
0
|
|
|
|
|
0
|
$class->warnings_message("New data has odd self-referential 'implied_by' on $class_name $property_name!"); |
1284
|
0
|
|
|
|
|
0
|
delete $new_property{implied_by}; |
1285
|
|
|
|
|
|
|
} |
1286
|
|
|
|
|
|
|
|
1287
|
142486
|
|
|
|
|
1412612
|
return %new_property; |
1288
|
|
|
|
|
|
|
} |
1289
|
|
|
|
|
|
|
|
1290
|
|
|
|
|
|
|
|
1291
|
|
|
|
|
|
|
sub _make_minimal_class_from_normalized_class_description { |
1292
|
24690
|
|
|
24690
|
|
25456
|
my $class = shift; |
1293
|
24690
|
|
|
|
|
24558
|
my $desc = shift; |
1294
|
|
|
|
|
|
|
|
1295
|
24690
|
|
|
|
|
30801
|
my $class_name = $desc->{class_name}; |
1296
|
24690
|
50
|
|
|
|
42094
|
unless ($class_name) { |
1297
|
0
|
|
|
|
|
0
|
Carp::confess("No class name specified?"); |
1298
|
|
|
|
|
|
|
} |
1299
|
|
|
|
|
|
|
|
1300
|
24690
|
|
|
|
|
27719
|
my $meta_class_name = $desc->{meta_class_name}; |
1301
|
24690
|
50
|
|
|
|
39088
|
die unless $meta_class_name; |
1302
|
24690
|
100
|
|
|
|
47251
|
if ($meta_class_name ne __PACKAGE__) { |
1303
|
11834
|
50
|
|
|
|
64041
|
unless ( |
1304
|
|
|
|
|
|
|
$meta_class_name->isa(__PACKAGE__) |
1305
|
|
|
|
|
|
|
) { |
1306
|
0
|
|
|
|
|
0
|
warn "Bogus meta class $meta_class_name doesn't inherit from UR::Object::Type?" |
1307
|
|
|
|
|
|
|
} |
1308
|
|
|
|
|
|
|
} |
1309
|
|
|
|
|
|
|
|
1310
|
|
|
|
|
|
|
# only do this when the classes match |
1311
|
|
|
|
|
|
|
# when they do not match, the super-class has already called this by delegating to the correct subclass |
1312
|
24690
|
|
|
|
|
27086
|
$class_name::VERSION = 2.0; # No BumpVersion |
1313
|
|
|
|
|
|
|
|
1314
|
24690
|
|
|
|
|
237816
|
my $self = bless { id => $class_name, %$desc }, $meta_class_name; |
1315
|
|
|
|
|
|
|
|
1316
|
24690
|
|
|
|
|
61439
|
$UR::Context::all_objects_loaded->{$meta_class_name}{$class_name} = $self; |
1317
|
24690
|
|
|
|
|
52593
|
my $full_name = join( '::', $class_name, '__meta__' ); |
1318
|
|
|
|
|
|
|
Sub::Install::reinstall_sub({ |
1319
|
|
|
|
|
|
|
into => $class_name, |
1320
|
|
|
|
|
|
|
as => '__meta__', |
1321
|
419401
|
|
|
419401
|
|
661073
|
code => Sub::Name::subname $full_name => sub {$self}, |
|
|
|
|
1443549
|
|
|
|
|
|
|
|
1417140
|
|
|
|
1322
|
24690
|
|
|
|
|
330710
|
}); |
1323
|
|
|
|
|
|
|
|
1324
|
24690
|
|
|
|
|
1221978
|
return $self; |
1325
|
|
|
|
|
|
|
} |
1326
|
|
|
|
|
|
|
|
1327
|
|
|
|
|
|
|
sub _initialize_accessors_and_inheritance { |
1328
|
24690
|
|
|
24690
|
|
27004
|
my $self = shift; |
1329
|
|
|
|
|
|
|
|
1330
|
24690
|
|
|
|
|
105788
|
$self->initialize_direct_accessors; |
1331
|
|
|
|
|
|
|
|
1332
|
24690
|
|
|
|
|
31225
|
my $class_name = $self->{class_name}; |
1333
|
|
|
|
|
|
|
|
1334
|
24690
|
|
|
|
|
22915
|
my @is = @{ $self->{is} }; |
|
24690
|
|
|
|
|
46676
|
|
1335
|
24690
|
100
|
|
|
|
47695
|
unless (@is) { |
1336
|
266
|
|
|
|
|
755
|
@is = ('UR::ModuleBase') |
1337
|
|
|
|
|
|
|
} |
1338
|
24690
|
|
|
|
|
54580
|
eval "\@${class_name}::ISA = (" . join(',', map { "'$_'" } @is) . ")\n"; |
|
26256
|
|
|
|
|
1507840
|
|
1339
|
24690
|
50
|
|
|
|
96344
|
Carp::croak("Can't initialize \@ISA for class_name '$class_name': $@\nMaybe the class_name or one of the parent classes are not valid class names") if $@; |
1340
|
|
|
|
|
|
|
|
1341
|
24690
|
|
|
|
|
24831
|
my $namespace_mro; |
1342
|
24690
|
|
|
|
|
39378
|
my $namespace_name = $self->{namespace}; |
1343
|
24690
|
50
|
100
|
|
|
298121
|
if ( |
|
|
|
66
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
66
|
|
|
|
|
1344
|
|
|
|
|
|
|
!$bootstrapping |
1345
|
|
|
|
|
|
|
&& !$class_name->isa('UR::Namespace') |
1346
|
|
|
|
|
|
|
&& $namespace_name |
1347
|
|
|
|
|
|
|
&& $namespace_name->isa('UR::Namespace') |
1348
|
|
|
|
|
|
|
&& $namespace_name->can('get') |
1349
|
|
|
|
|
|
|
&& (my $namespace = $namespace_name->get()) |
1350
|
|
|
|
|
|
|
) { |
1351
|
11210
|
|
|
|
|
35462
|
$namespace_mro = $namespace->method_resolution_order; |
1352
|
|
|
|
|
|
|
} |
1353
|
|
|
|
|
|
|
|
1354
|
24690
|
0
|
33
|
|
|
335358
|
if ($^V lt v5.9.5 && $namespace_mro && $namespace_mro eq 'c3') { |
|
|
|
33
|
|
|
|
|
1355
|
0
|
|
|
|
|
0
|
warn "C3 method resolution order is not supported on Perl < 5.9.5. Reverting $namespace_name namespace to DFS."; |
1356
|
0
|
|
|
|
|
0
|
my $namespace = $namespace_name->get(); |
1357
|
0
|
|
|
|
|
0
|
$namespace_mro = $namespace->method_resolution_order('dfs'); |
1358
|
|
|
|
|
|
|
} |
1359
|
|
|
|
|
|
|
|
1360
|
24690
|
100
|
66
|
|
|
148513
|
if ($^V ge v5.9.5 && $namespace_mro && mro::get_mro($class_name) ne $namespace_mro) { |
|
|
|
100
|
|
|
|
|
1361
|
11202
|
|
|
|
|
161289
|
mro::set_mro($class_name, $namespace_mro); |
1362
|
|
|
|
|
|
|
} |
1363
|
|
|
|
|
|
|
|
1364
|
24690
|
|
|
|
|
75298
|
return $self; |
1365
|
|
|
|
|
|
|
} |
1366
|
|
|
|
|
|
|
|
1367
|
|
|
|
|
|
|
our %_init_subclasses_loaded; |
1368
|
|
|
|
|
|
|
sub subclasses_loaded { |
1369
|
170082
|
|
|
170082
|
1
|
126018
|
return @{ $_init_subclasses_loaded{shift->class_name}}; |
|
170082
|
|
|
|
|
383904
|
|
1370
|
|
|
|
|
|
|
} |
1371
|
|
|
|
|
|
|
|
1372
|
|
|
|
|
|
|
our %_inform_all_parent_classes_of_newly_loaded_subclass; |
1373
|
|
|
|
|
|
|
sub _inform_all_parent_classes_of_newly_loaded_subclass { |
1374
|
24690
|
|
|
24690
|
|
27570
|
my $self = shift; |
1375
|
24690
|
|
|
|
|
75741
|
my $class_name = $self->class_name; |
1376
|
|
|
|
|
|
|
|
1377
|
24690
|
50
|
|
|
|
53005
|
Carp::confess("re-initializing class $class_name") if $_inform_all_parent_classes_of_newly_loaded_subclass{$class_name}; |
1378
|
24690
|
|
|
|
|
37746
|
$_inform_all_parent_classes_of_newly_loaded_subclass{$class_name} = 1; |
1379
|
|
|
|
|
|
|
|
1380
|
268
|
|
|
271
|
|
1467
|
no strict 'refs'; |
|
268
|
|
|
|
|
432
|
|
|
271
|
|
|
|
|
7273
|
|
1381
|
268
|
|
|
270
|
|
1007
|
no warnings; |
|
267
|
|
|
|
|
397
|
|
|
267
|
|
|
|
|
97941
|
|
1382
|
24690
|
|
|
|
|
21817
|
my @parent_classes = @{ $class_name . "::ISA" }; |
|
24690
|
|
|
|
|
94152
|
|
1383
|
24690
|
|
|
|
|
32060
|
for my $parent_class (@parent_classes) { |
1384
|
26256
|
100
|
|
|
|
78368
|
unless ($parent_class->can("id")) { |
1385
|
266
|
|
|
|
|
11583
|
__PACKAGE__->use_module_with_namespace_constraints($parent_class); |
1386
|
266
|
50
|
|
|
|
808
|
if ($@) { |
1387
|
0
|
|
|
|
|
0
|
die "Failed to find parent_class $parent_class for $class_name!"; |
1388
|
|
|
|
|
|
|
} |
1389
|
|
|
|
|
|
|
} |
1390
|
|
|
|
|
|
|
} |
1391
|
|
|
|
|
|
|
|
1392
|
24690
|
|
|
|
|
496847
|
my @i = sort $class_name->inheritance; |
1393
|
24690
|
|
100
|
|
|
96640
|
$_init_subclasses_loaded{$class_name} ||= []; |
1394
|
24690
|
|
|
|
|
26906
|
my $last_parent_class = ""; |
1395
|
24690
|
|
|
|
|
29677
|
for my $parent_class (@i) { |
1396
|
88996
|
100
|
|
|
|
116881
|
next if $parent_class eq $last_parent_class; |
1397
|
|
|
|
|
|
|
|
1398
|
81014
|
|
|
|
|
57521
|
$last_parent_class = $parent_class; |
1399
|
81014
|
|
100
|
|
|
122873
|
$_init_subclasses_loaded{$parent_class} ||= []; |
1400
|
81014
|
|
|
|
|
53397
|
push @{ $_init_subclasses_loaded{$parent_class} }, $class_name; |
|
81014
|
|
|
|
|
104288
|
|
1401
|
81014
|
|
|
|
|
54154
|
push @{ $parent_class . "::_init_subclasses_loaded" }, $class_name; |
|
81014
|
|
|
|
|
160711
|
|
1402
|
|
|
|
|
|
|
|
1403
|
|
|
|
|
|
|
# any index on a parent class must move to the child class |
1404
|
|
|
|
|
|
|
# if the child class were loaded before the index is made, it is pushed down at index creation time |
1405
|
81014
|
100
|
|
|
|
142731
|
if (my $parent_index_hashrefs = $UR::Object::Index::all_by_class_name_and_property_name{$parent_class}) { |
1406
|
|
|
|
|
|
|
#print "PUSHING INDEXES FOR $parent_class to $class_name\n"; |
1407
|
13554
|
|
|
|
|
28941
|
for my $parent_property (keys %$parent_index_hashrefs) { |
1408
|
8740
|
|
|
|
|
7457
|
my $parent_indexes = $parent_index_hashrefs->{$parent_property}; |
1409
|
8740
|
|
100
|
|
|
19442
|
my $indexes = $UR::Object::Index::all_by_class_name_and_property_name{$class_name}{$parent_property} ||= []; |
1410
|
8740
|
|
|
|
|
11352
|
push @$indexes, @$parent_indexes; |
1411
|
|
|
|
|
|
|
} |
1412
|
|
|
|
|
|
|
} |
1413
|
|
|
|
|
|
|
} |
1414
|
|
|
|
|
|
|
|
1415
|
24690
|
|
|
|
|
62803
|
return 1; |
1416
|
|
|
|
|
|
|
} |
1417
|
|
|
|
|
|
|
|
1418
|
|
|
|
|
|
|
sub _inform_roles_of_new_class { |
1419
|
24686
|
|
|
24686
|
|
29687
|
my $self = shift; |
1420
|
|
|
|
|
|
|
|
1421
|
24686
|
|
|
|
|
23764
|
foreach my $role_obj ( @{ $self->{roles} } ) { |
|
24686
|
|
|
|
|
58034
|
|
1422
|
47
|
|
|
|
|
640
|
my $package = $role_obj->role_name; |
1423
|
47
|
100
|
|
|
|
238
|
next unless my $import = $package->can('__import__'); |
1424
|
2
|
|
|
|
|
42
|
$import->($package, $self); |
1425
|
|
|
|
|
|
|
} |
1426
|
|
|
|
|
|
|
} |
1427
|
|
|
|
|
|
|
|
1428
|
|
|
|
|
|
|
sub _complete_class_meta_object_definitions { |
1429
|
24688
|
|
|
24688
|
|
29883
|
my $self = shift; |
1430
|
|
|
|
|
|
|
|
1431
|
|
|
|
|
|
|
# track related objects |
1432
|
24688
|
|
|
|
|
24011
|
my @subordinate_objects; |
1433
|
|
|
|
|
|
|
|
1434
|
|
|
|
|
|
|
# grab some data from the object |
1435
|
24688
|
|
|
|
|
37898
|
my $class_name = $self->{class_name}; |
1436
|
24688
|
|
|
|
|
30062
|
my $table_name = $self->{table_name}; |
1437
|
|
|
|
|
|
|
|
1438
|
|
|
|
|
|
|
# decompose the embedded complex data structures into normalized objects |
1439
|
24688
|
|
|
|
|
31676
|
my $inheritance = $self->{is}; |
1440
|
24688
|
|
|
|
|
28983
|
my $properties = $self->{has}; |
1441
|
24688
|
|
50
|
|
|
51671
|
my $relationships = $self->{relationships} || []; |
1442
|
24688
|
|
|
|
|
29429
|
my $constraints = $self->{constraints}; |
1443
|
24688
|
|
|
|
|
27884
|
my $data_source = $self->{'data_source_id'}; |
1444
|
|
|
|
|
|
|
|
1445
|
24688
|
|
|
|
|
28339
|
my $id_properties = $self->{id_by}; |
1446
|
24688
|
|
|
|
|
23431
|
my %id_property_rank; |
1447
|
24688
|
|
|
|
|
97676
|
for (my $i = '0 but true'; $i < @$id_properties; $i++) { |
1448
|
6895
|
|
|
|
|
21330
|
$id_property_rank{$id_properties->[$i]} = $i; |
1449
|
|
|
|
|
|
|
} |
1450
|
|
|
|
|
|
|
|
1451
|
|
|
|
|
|
|
# mark id/non-id properites |
1452
|
24688
|
|
|
|
|
55608
|
foreach my $pinfo ( values %$properties ) { |
1453
|
95383
|
|
|
|
|
143254
|
$pinfo->{'is_id'} = $id_property_rank{$pinfo->{'property_name'}}; |
1454
|
|
|
|
|
|
|
} |
1455
|
|
|
|
|
|
|
|
1456
|
|
|
|
|
|
|
# handle inheritance |
1457
|
24688
|
100
|
|
|
|
51936
|
unless ($class_name eq "UR::Object") { |
1458
|
267
|
|
|
270
|
|
1377
|
no strict 'refs'; |
|
267
|
|
|
|
|
443
|
|
|
268
|
|
|
|
|
247858
|
|
1459
|
|
|
|
|
|
|
|
1460
|
|
|
|
|
|
|
# sanity check |
1461
|
24422
|
|
|
|
|
46247
|
my @expected = @$inheritance; |
1462
|
24422
|
|
|
|
|
22844
|
my @actual = @{ $class_name . "::ISA" }; |
|
24422
|
|
|
|
|
89032
|
|
1463
|
|
|
|
|
|
|
|
1464
|
24422
|
50
|
33
|
|
|
130899
|
if (@actual and "@actual" ne "@expected") { |
1465
|
0
|
|
|
|
|
0
|
Carp::confess("for $class_name: expected '@expected' actual '@actual'\n"); |
1466
|
|
|
|
|
|
|
} |
1467
|
|
|
|
|
|
|
|
1468
|
|
|
|
|
|
|
# set |
1469
|
24422
|
|
|
|
|
31939
|
@{ $class_name . "::ISA" } = @$inheritance; |
|
24422
|
|
|
|
|
421062
|
|
1470
|
|
|
|
|
|
|
} |
1471
|
|
|
|
|
|
|
|
1472
|
24688
|
100
|
100
|
|
|
204109
|
if (not $data_source and $class_name->can("__load__")) { |
1473
|
|
|
|
|
|
|
# $data_source = UR::DataSource::Default->__define__; |
1474
|
1334
|
|
|
|
|
15339
|
$data_source = $self->{data_source_id} = $self->{db_committed}->{data_source_id} = 'UR::DataSource::Default'; |
1475
|
|
|
|
|
|
|
} |
1476
|
|
|
|
|
|
|
|
1477
|
|
|
|
|
|
|
# Create inline data source |
1478
|
24688
|
100
|
100
|
|
|
1256619
|
if ($data_source and ref($data_source) eq 'HASH') { |
1479
|
11
|
|
|
|
|
28
|
$self->{'__inline_data_source_data'} = $data_source; |
1480
|
11
|
|
|
|
|
22
|
my $ds_class = $data_source->{'is'}; |
1481
|
11
|
|
|
|
|
55
|
my $inline_ds = $ds_class->create_from_inline_class_data($self, $data_source); |
1482
|
10
|
|
|
|
|
27
|
$self->{'data_source_id'} = $self->{'db_committed'}->{'data_source_id'} = $inline_ds->id; |
1483
|
|
|
|
|
|
|
} |
1484
|
|
|
|
|
|
|
|
1485
|
|
|
|
|
|
|
|
1486
|
24687
|
100
|
100
|
|
|
70048
|
if ($self->{'data_source_id'} and !defined($self->{table_name})) { |
1487
|
1612
|
|
66
|
|
|
8383
|
my $data_source_obj = UR::DataSource->get($self->{'data_source_id'}) || eval { $self->{'data_source_id'}->get() }; |
1488
|
1612
|
100
|
66
|
|
|
10354
|
if ($data_source_obj and $data_source_obj->initializer_should_create_column_name_for_class_properties() ) { |
1489
|
17
|
|
|
|
|
40
|
$self->{table_name} = '__default__'; |
1490
|
|
|
|
|
|
|
} |
1491
|
|
|
|
|
|
|
} |
1492
|
|
|
|
|
|
|
|
1493
|
24687
|
|
|
|
|
42482
|
for my $parent_class_name (@$inheritance) { |
1494
|
25987
|
|
|
|
|
60550
|
my $parent_class = $parent_class_name->__meta__; |
1495
|
25987
|
50
|
|
|
|
52969
|
unless ($parent_class) { |
1496
|
|
|
|
|
|
|
#$DB::single = 1; |
1497
|
0
|
|
|
|
|
0
|
$parent_class = $parent_class_name->__meta__; |
1498
|
0
|
|
|
|
|
0
|
$self->error_message("Failed to find parent class $parent_class_name\n"); |
1499
|
0
|
|
|
|
|
0
|
return; |
1500
|
|
|
|
|
|
|
} |
1501
|
|
|
|
|
|
|
|
1502
|
|
|
|
|
|
|
# These class meta values get propogated from parent to child |
1503
|
25987
|
|
|
|
|
36813
|
foreach my $inh_property ( qw(schema_name data_source_id) ) { |
1504
|
51974
|
100
|
|
|
|
192897
|
if (not defined ($self->$inh_property)) { |
1505
|
49173
|
100
|
|
|
|
91040
|
if (my $inh_value = $parent_class->$inh_property) { |
1506
|
1386
|
|
|
|
|
4335
|
$self->{$inh_property} = $self->{'db_committed'}->{$inh_property} = $inh_value; |
1507
|
|
|
|
|
|
|
} |
1508
|
|
|
|
|
|
|
} |
1509
|
|
|
|
|
|
|
} |
1510
|
|
|
|
|
|
|
|
1511
|
|
|
|
|
|
|
# For classes with no data source, the default for id_generator is -urinternal |
1512
|
|
|
|
|
|
|
# For classes with a data source, autogenerate_new_object_id_for_class_name_and_rule gets called |
1513
|
|
|
|
|
|
|
# on that data source which can use id_generator as it sees fit |
1514
|
25987
|
100
|
|
|
|
55337
|
if (! defined $self->{id_generator}) { |
1515
|
24390
|
|
|
|
|
23871
|
my $id_generator; |
1516
|
24390
|
100
|
|
|
|
40970
|
if ($self->{data_source_id}) { |
1517
|
2076
|
100
|
66
|
|
|
6470
|
if ($parent_class->data_source_id |
1518
|
|
|
|
|
|
|
and |
1519
|
|
|
|
|
|
|
$parent_class->data_source_id eq $self->data_source_id |
1520
|
|
|
|
|
|
|
) { |
1521
|
1517
|
|
|
|
|
6628
|
$id_generator = $parent_class->id_generator; |
1522
|
|
|
|
|
|
|
} |
1523
|
|
|
|
|
|
|
} else { |
1524
|
22314
|
|
|
|
|
66462
|
$id_generator = $parent_class->id_generator; |
1525
|
|
|
|
|
|
|
} |
1526
|
24390
|
|
|
|
|
60152
|
$self->{id_generator} = $self->{'db_committed'}->{id_generator} = $id_generator; |
1527
|
|
|
|
|
|
|
} |
1528
|
|
|
|
|
|
|
|
1529
|
|
|
|
|
|
|
|
1530
|
|
|
|
|
|
|
# If a parent is declared as a singleton, we are too. |
1531
|
|
|
|
|
|
|
# This only works for abstract singletons. |
1532
|
25987
|
50
|
33
|
|
|
72220
|
if ($parent_class->is_singleton and not $self->is_singleton) { |
1533
|
0
|
|
|
|
|
0
|
$self->is_singleton($parent_class->is_singleton); |
1534
|
|
|
|
|
|
|
} |
1535
|
|
|
|
|
|
|
} |
1536
|
|
|
|
|
|
|
|
1537
|
|
|
|
|
|
|
# when we "have" an object reference, add it to the list of old-style references |
1538
|
|
|
|
|
|
|
# also ensure the old-style property definition is complete |
1539
|
24687
|
|
|
|
|
52223
|
for my $pinfo (grep { $_->{id_by} } values %$properties) { |
|
95381
|
|
|
|
|
83099
|
|
1540
|
4683
|
|
|
|
|
9847
|
push @$relationships, $pinfo->{property_name}, $pinfo; |
1541
|
|
|
|
|
|
|
|
1542
|
4683
|
|
|
|
|
6568
|
my $id_properties = $pinfo->{id_by}; |
1543
|
4683
|
|
|
|
|
6824
|
my $r_class_name = $pinfo->{data_type}; |
1544
|
4683
|
50
|
|
|
|
9001
|
unless($r_class_name) { |
1545
|
|
|
|
|
|
|
die sprintf("Object accessor property definition for %s::%s has an 'id_by' but no 'data_type'", |
1546
|
0
|
|
|
|
|
0
|
$pinfo->{'class_name'}, $pinfo->{'property_name'}); |
1547
|
|
|
|
|
|
|
} |
1548
|
4683
|
|
|
|
|
4708
|
my $r_class; |
1549
|
|
|
|
|
|
|
my @r_id_properties; |
1550
|
|
|
|
|
|
|
|
1551
|
4683
|
|
|
|
|
12062
|
for (my $n=0; $n<@$id_properties; $n++) { |
1552
|
5124
|
|
|
|
|
6988
|
my $id_property_name = $id_properties->[$n]; |
1553
|
5124
|
|
|
|
|
6471
|
my $id_property_detail = $properties->{$id_property_name}; |
1554
|
5124
|
50
|
|
|
|
9028
|
unless ($id_property_detail) { |
1555
|
|
|
|
|
|
|
#$DB::single = 1; |
1556
|
0
|
|
|
|
|
0
|
1; |
1557
|
|
|
|
|
|
|
} |
1558
|
|
|
|
|
|
|
|
1559
|
|
|
|
|
|
|
# No data_type specified, first try parent classes for the same property name |
1560
|
|
|
|
|
|
|
# and use their type |
1561
|
5124
|
100
|
66
|
|
|
16407
|
if (!$bootstrapping and !exists($id_property_detail->{data_type})) { |
1562
|
1569
|
100
|
|
|
|
7308
|
if (my $inh_prop = ($self->ancestry_property_metas(property_name => $id_property_name))[0]) { |
1563
|
128
|
|
|
|
|
570
|
$id_property_detail->{data_type} = $inh_prop->data_type; |
1564
|
|
|
|
|
|
|
} |
1565
|
|
|
|
|
|
|
} |
1566
|
|
|
|
|
|
|
|
1567
|
|
|
|
|
|
|
# Didn't find one - use the data type of the ID property(s) in the class we point to |
1568
|
5124
|
100
|
|
|
|
14296
|
unless ($id_property_detail->{data_type}) { |
1569
|
1829
|
100
|
|
|
|
4502
|
unless ($r_class) { |
1570
|
|
|
|
|
|
|
# FIXME - it'd be nice if we didn't have to load the remote class here, and |
1571
|
|
|
|
|
|
|
# instead put off loading until it's necessary |
1572
|
1389
|
|
66
|
|
|
7770
|
$r_class ||= UR::Object::Type->get($r_class_name); |
1573
|
1389
|
100
|
|
|
|
3448
|
unless ($r_class) { |
1574
|
1
|
|
|
|
|
119
|
Carp::confess("Unable to load $r_class_name while defining relationship ".$pinfo->{'property_name'}. " in class $class_name"); |
1575
|
|
|
|
|
|
|
} |
1576
|
1388
|
|
|
|
|
8461
|
@r_id_properties = $r_class->id_property_names; |
1577
|
|
|
|
|
|
|
} |
1578
|
|
|
|
|
|
|
my ($r_property) = |
1579
|
|
|
|
|
|
|
map { |
1580
|
1828
|
|
|
|
|
5959
|
my $r_class_ancestor = UR::Object::Type->get($_); |
|
3520
|
|
|
|
|
7684
|
|
1581
|
3520
|
|
|
|
|
6731
|
my $data = $r_class_ancestor->{has}{$r_id_properties[$n]}; |
1582
|
3520
|
100
|
|
|
|
7564
|
($data ? ($data) : ()); |
1583
|
|
|
|
|
|
|
} |
1584
|
|
|
|
|
|
|
($r_class_name, $r_class_name->__meta__->ancestry_class_names); |
1585
|
1828
|
50
|
|
|
|
4043
|
unless ($r_property) { |
1586
|
|
|
|
|
|
|
#$DB::single = 1; |
1587
|
0
|
|
|
|
|
0
|
my $property_name = $pinfo->{'property_name'}; |
1588
|
0
|
0
|
|
|
|
0
|
if (@$id_properties != @r_id_properties) { |
1589
|
0
|
|
|
|
|
0
|
Carp::croak("Can't resolve relationship for class $class_name property '$property_name': " |
1590
|
|
|
|
|
|
|
. "id_by metadata has " . scalar(@$id_properties) . " items, but remote class " |
1591
|
|
|
|
|
|
|
. "$r_class_name only has " . scalar(@r_id_properties) . " ID properties\n"); |
1592
|
|
|
|
|
|
|
} else { |
1593
|
0
|
0
|
|
|
|
0
|
my $r_id_property = $r_id_properties[$n] ? "'$r_id_properties[$n]'" : '(undef)'; |
1594
|
0
|
|
|
|
|
0
|
Carp::croak("Can't resolve relationship for class $class_name property '$property_name': " |
1595
|
|
|
|
|
|
|
. "Class $r_class_name does not have an ID property named $r_id_property, " |
1596
|
|
|
|
|
|
|
. "which would be linked to the local property '".$id_properties->[$n]."'\n"); |
1597
|
|
|
|
|
|
|
} |
1598
|
|
|
|
|
|
|
} |
1599
|
1828
|
|
|
|
|
7329
|
$id_property_detail->{data_type} = $r_property->{data_type}; |
1600
|
|
|
|
|
|
|
} |
1601
|
|
|
|
|
|
|
} |
1602
|
4682
|
|
|
|
|
6657
|
next; |
1603
|
|
|
|
|
|
|
} |
1604
|
|
|
|
|
|
|
|
1605
|
|
|
|
|
|
|
# make old-style (bc4nf) property objects in the default way |
1606
|
24686
|
|
|
|
|
24756
|
my %property_objects; |
1607
|
|
|
|
|
|
|
|
1608
|
24686
|
|
|
|
|
41104
|
for my $pinfo (values %$properties) { |
1609
|
95379
|
|
|
|
|
122664
|
my $property_name = $pinfo->{property_name}; |
1610
|
95379
|
|
|
|
|
86185
|
my $property_subclass = $pinfo->{property_subclass}; |
1611
|
|
|
|
|
|
|
|
1612
|
|
|
|
|
|
|
# Acme::Employee::Attribute::Name is a bc6nf attribute |
1613
|
|
|
|
|
|
|
# extends Acme::Employee::Attribute |
1614
|
|
|
|
|
|
|
# extends UR::Object::Attribute |
1615
|
|
|
|
|
|
|
# extends UR::Object |
1616
|
95379
|
|
|
|
|
192516
|
my @words = map { ucfirst($_) } split(/_/,$property_name); |
|
237876
|
|
|
|
|
348230
|
|
1617
|
|
|
|
|
|
|
#@words = $self->namespace->get_vocabulary->convert_to_title_case(@words); |
1618
|
95379
|
|
|
|
|
201825
|
my $bridge_class_name = |
1619
|
|
|
|
|
|
|
$class_name |
1620
|
|
|
|
|
|
|
. "::Attribute::" |
1621
|
|
|
|
|
|
|
. join('', @words); |
1622
|
|
|
|
|
|
|
|
1623
|
|
|
|
|
|
|
# Acme::Employee::Attribute::Name::Type is both the class definition for the bridge, |
1624
|
|
|
|
|
|
|
# and also the attribute/property metadata for |
1625
|
95379
|
|
|
|
|
90125
|
my $property_meta_class_name = $bridge_class_name . "::Type"; |
1626
|
|
|
|
|
|
|
|
1627
|
|
|
|
|
|
|
# define a new class for the above, inheriting from UR::Object::Property |
1628
|
|
|
|
|
|
|
# all of the "attributes_have" get put into the class definition |
1629
|
|
|
|
|
|
|
# call the constructor below on that new class |
1630
|
|
|
|
|
|
|
#UR::Object::Type->__define__( |
1631
|
|
|
|
|
|
|
## class_name => $property_meta_class_name, |
1632
|
|
|
|
|
|
|
# is => 'UR::Object::Property', # TODO: go through the inheritance |
1633
|
|
|
|
|
|
|
# has => [ |
1634
|
|
|
|
|
|
|
# @{ $class_name->__meta__->{attributes_have} } |
1635
|
|
|
|
|
|
|
# ] |
1636
|
|
|
|
|
|
|
#) |
1637
|
|
|
|
|
|
|
|
1638
|
95379
|
|
|
|
|
68696
|
my ($singular_name,$plural_name); |
1639
|
95379
|
100
|
66
|
|
|
202816
|
unless ($pinfo->{plural_name} and $pinfo->{singular_name}) { |
1640
|
80063
|
|
|
|
|
320423
|
require Lingua::EN::Inflect; |
1641
|
80063
|
100
|
|
|
|
116981
|
if ($pinfo->{is_many}) { |
1642
|
11179
|
|
33
|
|
|
39539
|
$plural_name = $pinfo->{plural_name} ||= $pinfo->{property_name}; |
1643
|
11179
|
|
|
|
|
25381
|
$pinfo->{singular_name} = Lingua::EN::Inflect::PL_V($plural_name); |
1644
|
|
|
|
|
|
|
} |
1645
|
|
|
|
|
|
|
else { |
1646
|
68884
|
|
33
|
|
|
217877
|
$singular_name = $pinfo->{singular_name} ||= $pinfo->{property_name}; |
1647
|
68884
|
|
|
|
|
154569
|
$pinfo->{plural_name} = Lingua::EN::Inflect::PL($singular_name); |
1648
|
|
|
|
|
|
|
} |
1649
|
|
|
|
|
|
|
} |
1650
|
|
|
|
|
|
|
|
1651
|
95379
|
|
|
|
|
14052347
|
my $property_object = UR::Object::Property->__define__(%$pinfo, id => $class_name . "\t" . $property_name); |
1652
|
|
|
|
|
|
|
|
1653
|
95379
|
50
|
|
|
|
238517
|
unless ($property_object) { |
1654
|
0
|
|
|
|
|
0
|
$self->error_message("Error creating property $property_name for class " . $self->class_name . ": " . $class_name->error_message); |
1655
|
0
|
|
|
|
|
0
|
for $property_object (@subordinate_objects) { $property_object->unload } |
|
0
|
|
|
|
|
0
|
|
1656
|
0
|
|
|
|
|
0
|
$self->unload; |
1657
|
0
|
|
|
|
|
0
|
return; |
1658
|
|
|
|
|
|
|
} |
1659
|
|
|
|
|
|
|
|
1660
|
95379
|
|
|
|
|
118277
|
$property_objects{$property_name} = $property_object; |
1661
|
95379
|
|
|
|
|
182344
|
push @subordinate_objects, $property_object; |
1662
|
|
|
|
|
|
|
} |
1663
|
|
|
|
|
|
|
|
1664
|
24686
|
50
|
|
|
|
47247
|
if ($constraints) { |
1665
|
24686
|
|
|
|
|
86755
|
my $property_rule_template = UR::BoolExpr::Template->resolve('UR::Object::Property','class_name','property_name'); |
1666
|
|
|
|
|
|
|
|
1667
|
24686
|
|
|
|
|
32556
|
my $n = 1; |
1668
|
24686
|
|
|
|
|
57574
|
for my $unique_set (sort { $a->{sql} cmp $b->{sql} } @$constraints) { |
|
0
|
|
|
|
|
0
|
|
1669
|
271
|
|
|
|
|
641
|
my ($name,$properties,$group,$sql); |
1670
|
271
|
50
|
|
|
|
1413
|
if (ref($unique_set) eq "HASH") { |
1671
|
271
|
|
|
|
|
714
|
$name = $unique_set->{name}; |
1672
|
271
|
|
|
|
|
557
|
$properties = $unique_set->{properties}; |
1673
|
271
|
|
|
|
|
586
|
$sql = $unique_set->{sql}; |
1674
|
271
|
|
33
|
|
|
2551
|
$name ||= $sql; |
1675
|
|
|
|
|
|
|
} |
1676
|
|
|
|
|
|
|
else { |
1677
|
0
|
|
|
|
|
0
|
$properties = @$unique_set; |
1678
|
0
|
|
|
|
|
0
|
$name = '(unnamed)'; |
1679
|
0
|
|
|
|
|
0
|
$n++; |
1680
|
|
|
|
|
|
|
} |
1681
|
271
|
|
|
|
|
1431
|
for my $property_name (sort @$properties) { |
1682
|
537
|
|
|
|
|
2130
|
my $prop_rule = $property_rule_template->get_rule_for_values($class_name,$property_name); |
1683
|
537
|
|
|
|
|
2224
|
my $property = $UR::Context::current->get_objects_for_class_and_rule('UR::Object::Property', $prop_rule); |
1684
|
537
|
50
|
|
|
|
2031
|
unless ($property) { |
1685
|
0
|
|
|
|
|
0
|
Carp::croak("Constraint '$name' on class $class_name requires unknown property '$property_name'"); |
1686
|
|
|
|
|
|
|
} |
1687
|
|
|
|
|
|
|
} |
1688
|
|
|
|
|
|
|
} |
1689
|
|
|
|
|
|
|
} |
1690
|
|
|
|
|
|
|
|
1691
|
24686
|
|
|
|
|
36242
|
for my $obj ($self,@subordinate_objects) { |
1692
|
|
|
|
|
|
|
#use Data::Dumper; |
1693
|
268
|
|
|
267
|
|
1474
|
no strict; |
|
273
|
|
|
|
|
456
|
|
|
267
|
|
|
|
|
154384
|
|
1694
|
120065
|
|
|
|
|
856515
|
my %db_committed = %$obj; |
1695
|
120065
|
|
|
|
|
259907
|
delete @db_committed{@keys_to_delete_from_db_committed}; |
1696
|
120065
|
|
|
|
|
285257
|
$obj->{'db_committed'} = \%db_committed; |
1697
|
|
|
|
|
|
|
|
1698
|
|
|
|
|
|
|
}; |
1699
|
|
|
|
|
|
|
|
1700
|
24686
|
50
|
|
|
|
106873
|
unless ($self->generate) { |
1701
|
0
|
|
|
|
|
0
|
$self->error_message("Error generating class " . $self->class_name . " as part of creation : " . $self->error_message); |
1702
|
0
|
|
|
|
|
0
|
for my $property_object (@subordinate_objects) { $property_object->unload } |
|
0
|
|
|
|
|
0
|
|
1703
|
0
|
|
|
|
|
0
|
$self->unload; |
1704
|
0
|
|
|
|
|
0
|
return; |
1705
|
|
|
|
|
|
|
} |
1706
|
|
|
|
|
|
|
|
1707
|
24686
|
100
|
|
|
|
66612
|
if (my $extra = $self->{extra}) { |
1708
|
263
|
|
|
|
|
1346
|
$self->_apply_extra_attrs_to_class_or_role($extra); |
1709
|
|
|
|
|
|
|
} |
1710
|
|
|
|
|
|
|
|
1711
|
24686
|
|
|
|
|
105747
|
$self->__signal_change__("load"); |
1712
|
|
|
|
|
|
|
|
1713
|
|
|
|
|
|
|
|
1714
|
24686
|
|
|
|
|
325963
|
my @i = $class_name->inheritance; |
1715
|
|
|
|
|
|
|
|
1716
|
24686
|
|
|
|
|
35904
|
for my $parent_class_name (@i) { |
1717
|
88985
|
100
|
|
|
|
248350
|
if ($parent_class_name->can('__signal_observers__')) { |
1718
|
61219
|
|
|
|
|
387527
|
$parent_class_name->__signal_observers__('subclass_loaded', $class_name); |
1719
|
|
|
|
|
|
|
} |
1720
|
|
|
|
|
|
|
} |
1721
|
|
|
|
|
|
|
|
1722
|
|
|
|
|
|
|
# The inheritance method is high overhead because of the number of times it is called. |
1723
|
|
|
|
|
|
|
# Cache on a per-class basis. |
1724
|
24686
|
50
|
|
|
|
652924
|
if (grep { $_ eq '' } @i) { |
|
88985
|
|
|
|
|
122752
|
|
1725
|
0
|
|
|
|
|
0
|
print "$class_name! @{ $self->{is} }"; |
|
0
|
|
|
|
|
0
|
|
1726
|
0
|
|
|
|
|
0
|
$class_name->inheritance; |
1727
|
|
|
|
|
|
|
} |
1728
|
24686
|
50
|
|
|
|
84873
|
Carp::confess("Odd inheritance @i for $class_name") unless $class_name->isa('UR::Object'); |
1729
|
24686
|
|
|
|
|
53525
|
my $src1 = " return shift->SUPER::inheritance(\@_) if ( (ref(\$_[0])||\$_[0]) ne '$class_name'); return (" . join(", ", map { "'$_'" } (@i)) . ")"; |
|
88985
|
|
|
|
|
166268
|
|
1730
|
24686
|
|
|
|
|
57197
|
my $src2 = qq|sub ${class_name}::inheritance { $src1 }|; |
1731
|
24686
|
100
|
66
|
647
|
1
|
2521275
|
eval $src2 unless $class_name eq 'UR::Object'; |
|
647
|
100
|
66
|
946
|
1
|
4583
|
|
|
222
|
100
|
66
|
620
|
1
|
706
|
|
|
946
|
100
|
66
|
768
|
1
|
5576
|
|
|
459
|
100
|
66
|
584
|
1
|
1343
|
|
|
620
|
100
|
66
|
617
|
1
|
4884
|
|
|
262
|
100
|
66
|
990
|
1
|
991
|
|
|
768
|
100
|
66
|
645
|
1
|
5331
|
|
|
263
|
100
|
66
|
531
|
1
|
878
|
|
|
584
|
100
|
66
|
728
|
1
|
4311
|
|
|
205
|
100
|
66
|
668
|
1
|
683
|
|
|
617
|
100
|
33
|
740
|
1
|
4256
|
|
|
230
|
100
|
66
|
897
|
1
|
745
|
|
|
990
|
100
|
66
|
517
|
1
|
5819
|
|
|
500
|
100
|
66
|
729
|
1
|
1431
|
|
|
645
|
100
|
66
|
603
|
1
|
4756
|
|
|
197
|
100
|
33
|
787
|
1
|
629
|
|
|
531
|
100
|
33
|
642
|
1
|
3785
|
|
|
236
|
100
|
66
|
652
|
1
|
849
|
|
|
728
|
100
|
66
|
533
|
1
|
5546
|
|
|
189
|
100
|
66
|
644
|
1
|
641
|
|
|
668
|
100
|
33
|
552
|
1
|
4856
|
|
|
190
|
100
|
66
|
511
|
1
|
598
|
|
|
740
|
100
|
66
|
593
|
1
|
5591
|
|
|
200
|
100
|
66
|
923
|
1
|
608
|
|
|
897
|
100
|
33
|
535
|
1
|
5078
|
|
|
478
|
100
|
66
|
517
|
1
|
1219
|
|
|
517
|
100
|
66
|
595
|
1
|
3605
|
|
|
196
|
100
|
66
|
560
|
1
|
647
|
|
|
729
|
100
|
66
|
516
|
1
|
5147
|
|
|
221
|
100
|
66
|
611
|
1
|
697
|
|
|
603
|
100
|
66
|
904
|
1
|
4524
|
|
|
188
|
100
|
33
|
668
|
1
|
624
|
|
|
787
|
100
|
33
|
699
|
1
|
5479
|
|
|
281
|
100
|
66
|
686
|
1
|
841
|
|
|
642
|
100
|
66
|
665
|
1
|
4788
|
|
|
183
|
100
|
66
|
597
|
1
|
651
|
|
|
652
|
100
|
66
|
748
|
1
|
4666
|
|
|
210
|
100
|
66
|
578
|
1
|
707
|
|
|
533
|
100
|
66
|
590
|
1
|
3914
|
|
|
233
|
100
|
66
|
771
|
1
|
794
|
|
|
644
|
100
|
33
|
580
|
1
|
4741
|
|
|
214
|
100
|
33
|
831
|
1
|
727
|
|
|
552
|
100
|
66
|
482
|
1
|
3996
|
|
|
200
|
100
|
66
|
777
|
1
|
632
|
|
|
511
|
100
|
66
|
667
|
1
|
3435
|
|
|
250
|
100
|
33
|
537
|
1
|
765
|
|
|
593
|
100
|
66
|
605
|
1
|
4102
|
|
|
238
|
100
|
33
|
695
|
1
|
867
|
|
|
923
|
100
|
66
|
709
|
1
|
5437
|
|
|
526
|
100
|
66
|
589
|
1
|
1357
|
|
|
535
|
100
|
33
|
552
|
1
|
3912
|
|
|
201
|
100
|
33
|
612
|
1
|
697
|
|
|
517
|
100
|
33
|
629
|
1
|
3727
|
|
|
199
|
100
|
66
|
582
|
1
|
686
|
|
|
595
|
100
|
33
|
769
|
1
|
3946
|
|
|
236
|
100
|
66
|
652
|
1
|
802
|
|
|
560
|
100
|
66
|
594
|
1
|
4238
|
|
|
211
|
100
|
66
|
582
|
1
|
685
|
|
|
516
|
100
|
66
|
744
|
1
|
3742
|
|
|
211
|
100
|
66
|
580
|
1
|
693
|
|
|
611
|
100
|
66
|
706
|
1
|
4451
|
|
|
212
|
100
|
66
|
703
|
1
|
704
|
|
|
904
|
100
|
33
|
565
|
1
|
5647
|
|
|
496
|
100
|
33
|
556
|
1
|
1799
|
|
|
668
|
100
|
33
|
624
|
1
|
5059
|
|
|
206
|
100
|
66
|
768
|
1
|
692
|
|
|
699
|
100
|
66
|
652
|
1
|
5050
|
|
|
196
|
100
|
66
|
618
|
1
|
676
|
|
|
686
|
100
|
66
|
648
|
1
|
4702
|
|
|
262
|
100
|
66
|
620
|
1
|
847
|
|
|
665
|
100
|
66
|
772
|
1
|
4792
|
|
|
207
|
100
|
66
|
649
|
|
663
|
|
|
597
|
100
|
33
|
577
|
|
4182
|
|
|
223
|
100
|
33
|
569
|
|
778
|
|
|
748
|
100
|
66
|
593
|
|
5535
|
|
|
230
|
100
|
66
|
492
|
|
727
|
|
|
578
|
100
|
33
|
429
|
|
4185
|
|
|
224
|
100
|
66
|
692
|
|
734
|
|
|
590
|
100
|
66
|
485
|
|
4347
|
|
|
203
|
100
|
66
|
1417140
|
|
683
|
|
|
771
|
100
|
66
|
1389022
|
|
5206
|
|
|
286
|
100
|
66
|
1385096
|
|
849
|
|
|
580
|
100
|
66
|
1352399
|
|
4297
|
|
|
216
|
100
|
66
|
1352399
|
|
679
|
|
|
831
|
100
|
66
|
1322637
|
|
6191
|
|
|
220
|
100
|
66
|
1322637
|
|
705
|
|
|
482
|
100
|
33
|
1264281
|
|
3492
|
|
|
222
|
100
|
66
|
1264281
|
|
717
|
|
|
777
|
100
|
66
|
1200024
|
|
5236
|
|
|
280
|
100
|
66
|
1200024
|
|
880
|
|
|
667
|
100
|
66
|
1114183
|
|
4852
|
|
|
230
|
100
|
66
|
1114183
|
|
847
|
|
|
537
|
100
|
66
|
1040228
|
|
3890
|
|
|
192
|
100
|
66
|
1040228
|
|
626
|
|
|
605
|
100
|
66
|
970121
|
|
4543
|
|
|
205
|
100
|
66
|
970121
|
|
703
|
|
|
695
|
100
|
66
|
868294
|
|
4974
|
|
|
223
|
100
|
66
|
868294
|
|
709
|
|
|
709
|
100
|
33
|
791465
|
|
4940
|
|
|
289
|
100
|
66
|
785534
|
|
1034
|
|
|
589
|
100
|
33
|
726525
|
|
4268
|
|
|
215
|
100
|
66
|
726525
|
|
708
|
|
|
552
|
100
|
66
|
684568
|
|
4240
|
|
|
182
|
100
|
33
|
684568
|
|
570
|
|
|
612
|
100
|
66
|
630998
|
|
4588
|
|
|
205
|
100
|
66
|
630998
|
|
653
|
|
|
629
|
50
|
66
|
567725
|
|
4604
|
|
|
200
|
100
|
66
|
567725
|
|
676
|
|
|
582
|
100
|
66
|
435200
|
|
4344
|
|
|
191
|
50
|
66
|
435200
|
|
651
|
|
|
769
|
100
|
33
|
411730
|
|
5263
|
|
|
222
|
100
|
66
|
411730
|
|
677
|
|
|
652
|
100
|
66
|
347913
|
|
4562
|
|
|
231
|
100
|
33
|
347913
|
|
780
|
|
|
594
|
100
|
33
|
338684
|
|
4202
|
|
|
220
|
100
|
33
|
338684
|
|
747
|
|
|
582
|
50
|
66
|
298112
|
|
4467
|
|
|
259
|
100
|
33
|
288693
|
|
860
|
|
|
744
|
100
|
33
|
288693
|
|
5225
|
|
|
248
|
100
|
66
|
288693
|
|
888
|
|
|
580
|
100
|
33
|
288693
|
|
4064
|
|
|
235
|
100
|
33
|
288693
|
|
751
|
|
|
706
|
100
|
66
|
288693
|
|
5048
|
|
|
235
|
100
|
33
|
288693
|
|
822
|
|
|
703
|
100
|
33
|
280227
|
|
5120
|
|
|
238
|
50
|
33
|
280227
|
|
807
|
|
|
565
|
100
|
33
|
174099
|
|
4125
|
|
|
184
|
100
|
66
|
174099
|
|
638
|
|
|
556
|
100
|
33
|
165583
|
|
3863
|
|
|
232
|
50
|
33
|
165583
|
|
730
|
|
|
624
|
100
|
33
|
139849
|
|
4608
|
|
|
214
|
100
|
33
|
139849
|
|
694
|
|
|
768
|
100
|
33
|
139849
|
|
4471
|
|
|
446
|
100
|
33
|
139849
|
|
1485
|
|
|
652
|
100
|
33
|
56296
|
|
4568
|
|
|
347
|
50
|
33
|
56296
|
|
1221
|
|
|
618
|
50
|
33
|
56296
|
|
4408
|
|
|
182
|
100
|
33
|
56296
|
|
608
|
|
|
648
|
100
|
33
|
56296
|
|
4717
|
|
|
203
|
100
|
33
|
56296
|
|
671
|
|
|
620
|
100
|
33
|
56296
|
|
4561
|
|
|
191
|
100
|
33
|
56296
|
|
633
|
|
|
772
|
100
|
33
|
56296
|
|
5862
|
|
|
188
|
50
|
33
|
56296
|
|
614
|
|
|
649
|
|
33
|
39925
|
|
4497
|
|
|
278
|
|
33
|
39925
|
|
1050
|
|
|
577
|
|
33
|
39925
|
|
4039
|
|
|
200
|
|
33
|
39925
|
|
622
|
|
|
569
|
|
33
|
39925
|
|
4205
|
|
|
169
|
|
33
|
39925
|
|
565
|
|
|
593
|
|
33
|
39925
|
|
4632
|
|
|
213
|
|
33
|
39925
|
|
884
|
|
|
492
|
|
33
|
39925
|
|
3580
|
|
|
172
|
|
33
|
39925
|
|
603
|
|
|
429
|
|
33
|
39925
|
|
3054
|
|
|
173
|
|
33
|
39925
|
|
575
|
|
|
692
|
|
33
|
39925
|
|
4872
|
|
|
205
|
|
33
|
39925
|
|
700
|
|
|
485
|
|
33
|
39925
|
|
3485
|
|
|
157
|
|
33
|
39925
|
|
587
|
|
|
105
|
|
33
|
39925
|
|
2948
|
|
|
23
|
|
33
|
39925
|
|
68
|
|
|
76
|
|
33
|
39925
|
|
535
|
|
|
37
|
|
33
|
39925
|
|
143
|
|
|
78
|
|
33
|
39925
|
|
615
|
|
|
18
|
|
33
|
39925
|
|
66
|
|
|
95
|
|
33
|
31069
|
|
645
|
|
|
23
|
|
33
|
31069
|
|
113
|
|
|
12
|
|
|
|
|
81
|
|
|
6
|
|
|
|
|
22
|
|
|
14
|
|
|
|
|
90
|
|
|
8
|
|
|
|
|
23
|
|
|
5
|
|
|
|
|
32
|
|
|
5
|
|
|
|
|
14
|
|
|
8
|
|
|
|
|
51
|
|
|
2
|
|
|
|
|
6
|
|
|
21
|
|
|
|
|
129
|
|
|
15
|
|
|
|
|
50
|
|
|
3
|
|
|
|
|
23
|
|
|
3
|
|
|
|
|
10
|
|
|
21
|
|
|
|
|
176
|
|
|
3
|
|
|
|
|
10
|
|
|
18
|
|
|
|
|
121
|
|
|
6
|
|
|
|
|
24
|
|
|
15
|
|
|
|
|
88
|
|
|
6
|
|
|
|
|
19
|
|
|
12
|
|
|
|
|
72
|
|
|
3
|
|
|
|
|
11
|
|
|
6
|
|
|
|
|
56
|
|
|
3
|
|
|
|
|
10
|
|
|
6
|
|
|
|
|
78
|
|
|
3
|
|
|
|
|
9
|
|
|
2
|
|
|
|
|
14
|
|
|
2
|
|
|
|
|
8
|
|
|
7
|
|
|
|
|
47
|
|
|
4
|
|
|
|
|
12
|
|
|
12
|
|
|
|
|
88
|
|
|
3
|
|
|
|
|
11
|
|
|
12
|
|
|
|
|
84
|
|
|
3
|
|
|
|
|
8
|
|
|
11
|
|
|
|
|
64
|
|
|
4
|
|
|
|
|
11
|
|
|
25
|
|
|
|
|
138
|
|
|
19
|
|
|
|
|
63
|
|
|
9
|
|
|
|
|
53
|
|
|
3
|
|
|
|
|
9
|
|
|
11
|
|
|
|
|
61
|
|
|
3
|
|
|
|
|
9
|
|
|
12
|
|
|
|
|
69
|
|
|
3
|
|
|
|
|
8
|
|
|
2
|
|
|
|
|
14
|
|
|
2
|
|
|
|
|
8
|
|
|
5
|
|
|
|
|
28
|
|
|
2
|
|
|
|
|
5
|
|
|
24
|
|
|
|
|
194
|
|
|
3
|
|
|
|
|
11
|
|
|
7
|
|
|
|
|
52
|
|
|
2
|
|
|
|
|
6
|
|
|
2
|
|
|
|
|
41
|
|
|
2
|
|
|
|
|
6
|
|
|
40
|
|
|
|
|
240
|
|
|
7
|
|
|
|
|
21
|
|
|
9
|
|
|
|
|
69
|
|
|
3
|
|
|
|
|
11
|
|
|
11
|
|
|
|
|
70
|
|
|
2
|
|
|
|
|
7
|
|
|
6
|
|
|
|
|
40
|
|
|
3
|
|
|
|
|
9
|
|
|
8
|
|
|
|
|
51
|
|
|
2
|
|
|
|
|
6
|
|
|
2
|
|
|
|
|
12
|
|
|
2
|
|
|
|
|
6
|
|
|
2
|
|
|
|
|
14
|
|
|
2
|
|
|
|
|
5
|
|
|
12
|
|
|
|
|
71
|
|
|
3
|
|
|
|
|
9
|
|
|
17
|
|
|
|
|
119
|
|
|
1
|
|
|
|
|
2
|
|
|
5
|
|
|
|
|
29
|
|
|
2
|
|
|
|
|
7
|
|
|
4
|
|
|
|
|
35
|
|
|
1
|
|
|
|
|
3
|
|
|
4
|
|
|
|
|
24
|
|
|
1
|
|
|
|
|
3
|
|
|
6
|
|
|
|
|
39
|
|
|
3
|
|
|
|
|
9
|
|
|
2
|
|
|
|
|
13
|
|
|
2
|
|
|
|
|
5
|
|
1732
|
24686
|
50
|
|
|
|
64958
|
die $@ if $@; |
1733
|
|
|
|
|
|
|
|
1734
|
24686
|
|
|
|
|
56334
|
$self->{'_property_meta_for_name'} = \%property_objects; |
1735
|
|
|
|
|
|
|
|
1736
|
|
|
|
|
|
|
# return the new class object |
1737
|
24686
|
|
|
|
|
194226
|
return $self; |
1738
|
|
|
|
|
|
|
} |
1739
|
|
|
|
|
|
|
|
1740
|
|
|
|
|
|
|
sub _apply_extra_attrs_to_class_or_role { |
1741
|
779
|
|
|
779
|
|
4103
|
my($self, $extra) = @_; |
1742
|
|
|
|
|
|
|
|
1743
|
469
|
100
|
|
|
|
1759
|
if ($extra) { |
1744
|
|
|
|
|
|
|
# some class characteristics may be only present in subclasses of UR::Object |
1745
|
|
|
|
|
|
|
# we handle these at this point, since the above is needed for bootstrapping |
1746
|
765
|
|
|
|
|
4420
|
my %still_not_found; |
1747
|
420
|
|
|
|
|
1774
|
for my $key (sort keys %$extra) { |
1748
|
784
|
100
|
|
|
|
5194
|
if ($self->can($key)) { |
1749
|
458
|
|
|
|
|
3429
|
$self->$key($extra->{$key}); |
1750
|
|
|
|
|
|
|
} |
1751
|
|
|
|
|
|
|
else { |
1752
|
769
|
|
|
|
|
4662
|
$still_not_found{$key} = $extra->{$key}; |
1753
|
|
|
|
|
|
|
} |
1754
|
|
|
|
|
|
|
} |
1755
|
767
|
100
|
|
|
|
2475
|
if (%still_not_found) { |
1756
|
426
|
100
|
|
|
|
2894
|
my $kind = $self->isa('UR::Object::Type') |
1757
|
|
|
|
|
|
|
? 'Class' |
1758
|
|
|
|
|
|
|
: 'Role'; |
1759
|
195
|
|
|
|
|
704
|
my $name = $self->id; |
1760
|
|
|
|
|
|
|
|
1761
|
439
|
|
|
|
|
3138
|
$DB::single = 1; |
1762
|
|
|
|
|
|
|
Carp::croak("Bad $kind defninition for $name. Unrecognized properties:\n\t" |
1763
|
161
|
|
|
|
|
556
|
. join("\n\t", join(' => ', map { ($_, $still_not_found{$_}) } keys %still_not_found))); |
|
673
|
|
|
|
|
4696
|
|
1764
|
|
|
|
|
|
|
} |
1765
|
|
|
|
|
|
|
} |
1766
|
|
|
|
|
|
|
|
1767
|
|
|
|
|
|
|
|
1768
|
|
|
|
|
|
|
} |
1769
|
|
|
|
|
|
|
|
1770
|
|
|
|
|
|
|
# write the module from the existing data in the class object |
1771
|
|
|
|
|
|
|
sub generate { |
1772
|
25745
|
|
|
25986
|
1
|
31801
|
my $self = shift; |
1773
|
25929
|
100
|
|
|
|
58295
|
return 1 if $self->{'generated'}; |
1774
|
|
|
|
|
|
|
|
1775
|
|
|
|
|
|
|
#my %params = @_; # Doesn't seem to be used below... |
1776
|
|
|
|
|
|
|
|
1777
|
|
|
|
|
|
|
|
1778
|
|
|
|
|
|
|
# The follwing code will override a lot intentionally. |
1779
|
|
|
|
|
|
|
# Supress the warning messages. |
1780
|
289
|
|
|
267
|
|
1562
|
no warnings; |
|
274
|
|
|
|
|
444
|
|
|
267
|
|
|
|
|
23196
|
|
1781
|
|
|
|
|
|
|
|
1782
|
|
|
|
|
|
|
# the class that this object represents |
1783
|
|
|
|
|
|
|
# the class that we're going to generate |
1784
|
|
|
|
|
|
|
# the "new class" |
1785
|
24845
|
|
|
|
|
65947
|
my $class_name = $self->class_name; |
1786
|
|
|
|
|
|
|
|
1787
|
|
|
|
|
|
|
# this is done earlier in the class definition process in _make_minimal_class_from_normalized_class_description() |
1788
|
25092
|
|
|
|
|
51422
|
my $full_name = join( '::', $class_name, '__meta__' ); |
1789
|
|
|
|
|
|
|
Sub::Install::reinstall_sub({ |
1790
|
|
|
|
|
|
|
into => $class_name, |
1791
|
|
|
|
|
|
|
as => '__meta__', |
1792
|
1736606
|
|
|
1736704
|
|
2656687
|
code => Sub::Name::subname $full_name => sub {$self}, |
|
|
|
|
1736952
|
|
|
|
|
|
|
|
1736609
|
|
|
|
|
|
|
|
1736622
|
|
|
|
|
|
|
|
1736856
|
|
|
|
|
|
|
|
1736628
|
|
|
|
|
|
|
|
1736590
|
|
|
|
|
|
|
|
1736606
|
|
|
|
|
|
|
|
1736679
|
|
|
|
|
|
|
|
1736492
|
|
|
|
|
|
|
|
1736655
|
|
|
|
|
|
|
|
1736530
|
|
|
|
|
|
|
|
1736577
|
|
|
|
|
|
|
|
1736503
|
|
|
|
|
|
|
|
1736470
|
|
|
|
|
|
|
|
1736443
|
|
|
|
|
|
|
|
1736490
|
|
|
|
|
|
|
|
1736504
|
|
|
|
|
|
|
|
1736355
|
|
|
|
|
|
|
|
1736285
|
|
|
|
|
|
|
|
1736352
|
|
|
|
|
|
|
|
1736388
|
|
|
|
|
|
|
|
1736328
|
|
|
|
|
|
|
|
1736424
|
|
|
|
|
|
|
|
1736444
|
|
|
|
|
|
|
|
1736321
|
|
|
|
|
|
|
|
1736327
|
|
|
|
|
|
|
|
1736347
|
|
|
|
|
|
|
|
1736333
|
|
|
|
|
|
|
|
1736272
|
|
|
|
|
|
|
|
1736315
|
|
|
|
|
|
|
|
1736304
|
|
|
|
|
|
|
|
1736263
|
|
|
|
|
|
|
|
1736246
|
|
|
|
|
|
|
|
1736239
|
|
|
|
|
|
|
|
1736299
|
|
|
|
|
|
|
|
1736263
|
|
|
|
|
|
|
|
1736242
|
|
|
|
|
|
|
|
1736213
|
|
|
|
|
|
|
|
1736236
|
|
|
|
|
|
|
|
1736231
|
|
|
|
|
|
|
|
1736211
|
|
|
|
|
|
|
|
1736219
|
|
|
|
|
|
|
|
1736283
|
|
|
|
|
|
|
|
1736254
|
|
|
|
|
|
|
|
1736262
|
|
|
|
|
|
|
|
1736279
|
|
|
|
|
|
|
|
1736196
|
|
|
|
|
|
|
|
1736198
|
|
|
|
|
|
|
|
1736189
|
|
|
|
|
|
|
|
1736192
|
|
|
|
|
|
|
|
1736205
|
|
|
|
|
|
|
|
1736187
|
|
|
|
|
|
|
|
1736205
|
|
|
|
|
|
|
|
1736202
|
|
|
|
|
|
|
|
1736199
|
|
|
|
|
|
|
|
1736196
|
|
|
|
|
|
|
|
1736190
|
|
|
|
|
|
|
|
1736190
|
|
|
|
|
|
|
|
1736186
|
|
|
|
|
|
|
|
1736191
|
|
|
|
|
|
|
|
1736196
|
|
|
|
|
|
|
|
1736196
|
|
|
|
|
|
|
|
1736195
|
|
|
|
|
|
|
|
1714869
|
|
|
|
|
|
|
|
1714853
|
|
|
|
|
|
|
|
1692615
|
|
|
|
|
|
|
|
1690004
|
|
|
|
|
|
|
|
1674073
|
|
|
|
|
|
|
|
1670902
|
|
|
|
|
|
|
|
1655457
|
|
|
|
|
|
|
|
1630648
|
|
|
|
|
|
|
|
1613132
|
|
|
|
|
|
|
|
1610192
|
|
|
|
|
|
|
|
1604095
|
|
|
|
|
|
|
|
1540660
|
|
|
|
|
|
|
|
1534469
|
|
|
|
|
|
|
|
1521600
|
|
|
|
|
|
|
|
1521594
|
|
|
|
|
|
|
|
1487554
|
|
|
|
|
|
|
|
1487564
|
|
|
|
|
|
|
|
1450490
|
|
|
|
|
|
|
|
31069
|
|
|
|
|
|
|
|
31069
|
|
|
|
|
|
|
|
31069
|
|
|
|
|
|
|
|
31069
|
|
|
|
|
|
|
|
31069
|
|
|
|
|
|
|
|
31069
|
|
|
|
|
|
|
|
31069
|
|
|
|
|
|
|
|
31069
|
|
|
|
|
|
|
|
31069
|
|
|
|
|
|
|
|
31069
|
|
|
|
|
|
|
|
31069
|
|
|
|
|
|
|
|
31069
|
|
|
|
|
|
|
|
31069
|
|
|
|
|
|
|
|
31069
|
|
|
|
|
|
|
|
31069
|
|
|
|
|
|
|
|
31069
|
|
|
|
|
|
|
|
31069
|
|
|
|
|
|
|
|
31069
|
|
|
|
|
|
|
|
31069
|
|
|
|
|
|
|
|
31069
|
|
|
|
|
|
|
|
31069
|
|
|
|
|
|
|
|
31069
|
|
|
|
|
|
|
|
31069
|
|
|
|
|
|
|
|
31069
|
|
|
|
|
|
|
|
31069
|
|
|
|
|
|
|
|
31069
|
|
|
|
|
|
|
|
16935
|
|
|
|
|
|
|
|
16935
|
|
|
|
|
|
|
|
16935
|
|
|
|
|
|
|
|
16935
|
|
|
|
|
|
|
|
16935
|
|
|
|
|
|
|
|
16935
|
|
|
|
|
|
|
|
16935
|
|
|
|
|
|
|
|
16935
|
|
|
|
1793
|
24851
|
|
|
|
|
274462
|
}); |
1794
|
|
|
|
|
|
|
|
1795
|
24844
|
|
|
|
|
1849670
|
my @parent_class_names = $self->parent_class_names; |
1796
|
|
|
|
|
|
|
|
1797
|
25181
|
|
|
|
|
31158
|
do { |
1798
|
267
|
|
|
267
|
|
1232
|
no strict 'refs'; |
|
276
|
|
|
|
|
501
|
|
|
267
|
|
|
|
|
8566
|
|
1799
|
24870
|
100
|
|
|
|
26856
|
if (@{ $class_name . '::ISA' }) { |
|
24994
|
|
|
|
|
96910
|
|
1800
|
|
|
|
|
|
|
#print "already have isa for class_name $class_name: " . join(",",@{ $class_name . '::ISA' }) . "\n"; |
1801
|
|
|
|
|
|
|
} |
1802
|
|
|
|
|
|
|
else { |
1803
|
266
|
|
|
268
|
|
967
|
no strict 'refs'; |
|
266
|
|
|
|
|
406
|
|
|
266
|
|
|
|
|
153703
|
|
1804
|
133
|
|
|
|
|
445
|
@{ $class_name . '::ISA' } = @parent_class_names; |
|
471
|
|
|
|
|
3435
|
|
1805
|
|
|
|
|
|
|
#print "setting isa for class_name $class_name: " . join(",",@{ $class_name . '::ISA' }) . "\n"; |
1806
|
|
|
|
|
|
|
}; |
1807
|
|
|
|
|
|
|
}; |
1808
|
|
|
|
|
|
|
|
1809
|
|
|
|
|
|
|
|
1810
|
24878
|
|
|
|
|
44619
|
my ($props, $cols) = ([], []); # for _all_properties_columns() |
1811
|
25032
|
|
|
|
|
57352
|
$self->{_all_properties_columns} = [$props, $cols]; |
1812
|
|
|
|
|
|
|
|
1813
|
24789
|
|
|
|
|
30470
|
my $id_props = []; # for _all_id_properties() |
1814
|
25079
|
|
|
|
|
41540
|
$self->{_all_id_properties} = $id_props; |
1815
|
|
|
|
|
|
|
|
1816
|
|
|
|
|
|
|
# build the supplemental classes |
1817
|
24809
|
|
|
|
|
38417
|
for my $parent_class_name (@parent_class_names) { |
1818
|
26305
|
100
|
|
|
|
61322
|
next if $parent_class_name eq "UR::Object"; |
1819
|
|
|
|
|
|
|
|
1820
|
20873
|
100
|
|
|
|
39995
|
if ($parent_class_name eq $class_name) { |
1821
|
286
|
|
|
|
|
2042
|
Carp::confess("$class_name has parent class list which includes itself?: @parent_class_names\n"); |
1822
|
|
|
|
|
|
|
} |
1823
|
|
|
|
|
|
|
|
1824
|
20847
|
|
|
|
|
65629
|
my $parent_class_meta = UR::Object::Type->get(class_name => $parent_class_name); |
1825
|
|
|
|
|
|
|
|
1826
|
20996
|
100
|
|
|
|
44909
|
unless ($parent_class_meta) { |
1827
|
|
|
|
|
|
|
#$DB::single = 1; |
1828
|
161
|
|
|
|
|
553
|
$parent_class_meta = UR::Object::Type->get(class_name => $parent_class_name); |
1829
|
306
|
|
|
|
|
2185
|
Carp::confess("Cannot generate $class_name: Failed to find class meta-data for base class $parent_class_name."); |
1830
|
|
|
|
|
|
|
} |
1831
|
|
|
|
|
|
|
|
1832
|
20835
|
100
|
|
|
|
67082
|
unless ($parent_class_meta->generated()) { |
1833
|
1119
|
|
|
|
|
9025
|
$parent_class_meta->generate(); |
1834
|
|
|
|
|
|
|
} |
1835
|
|
|
|
|
|
|
|
1836
|
20813
|
100
|
|
|
|
49240
|
unless ($parent_class_meta->{_all_properties_columns}) { |
1837
|
171
|
|
|
|
|
1119
|
Carp::confess("No _all_properties_columns for $parent_class_name?"); |
1838
|
|
|
|
|
|
|
} |
1839
|
|
|
|
|
|
|
|
1840
|
|
|
|
|
|
|
# inherit properties and columns |
1841
|
20821
|
|
|
|
|
21824
|
my ($p, $c) = @{ $parent_class_meta->{_all_properties_columns} }; |
|
20838
|
|
|
|
|
36785
|
|
1842
|
20798
|
100
|
|
|
|
48151
|
push @$props, @$p if $p; |
1843
|
20905
|
100
|
|
|
|
40235
|
push @$cols, @$c if $c; |
1844
|
20830
|
|
|
|
|
25733
|
my $id_p = $parent_class_meta->{_all_id_properties}; |
1845
|
20941
|
100
|
|
|
|
51967
|
push @$id_props, @$id_p if $id_p; |
1846
|
|
|
|
|
|
|
} |
1847
|
|
|
|
|
|
|
|
1848
|
|
|
|
|
|
|
|
1849
|
|
|
|
|
|
|
# set up accessors/mutators for properties |
1850
|
24815
|
|
|
|
|
67189
|
my @property_objects = |
1851
|
|
|
|
|
|
|
UR::Object::Property->get(class_name => $self->class_name); |
1852
|
|
|
|
|
|
|
|
1853
|
24830
|
|
|
|
|
127760
|
my @id_property_objects = $self->direct_id_property_metas; |
1854
|
24755
|
|
|
|
|
29142
|
my %id_property; |
1855
|
24926
|
|
|
|
|
38613
|
for my $ipo (@id_property_objects) { |
1856
|
21679
|
|
|
|
|
62503
|
$id_property{$ipo->property_name} = 1; |
1857
|
|
|
|
|
|
|
} |
1858
|
|
|
|
|
|
|
|
1859
|
24946
|
100
|
|
|
|
54791
|
if (@id_property_objects) { |
1860
|
18474
|
|
|
|
|
28776
|
$id_props = []; |
1861
|
18444
|
|
|
|
|
29928
|
for my $ipo (@id_property_objects) { |
1862
|
21645
|
|
|
|
|
45667
|
push @$id_props, $ipo->property_name; |
1863
|
|
|
|
|
|
|
} |
1864
|
|
|
|
|
|
|
} |
1865
|
|
|
|
|
|
|
|
1866
|
24829
|
|
|
|
|
27050
|
my $has_table; |
1867
|
24740
|
|
|
|
|
36505
|
my @parent_classes = map { UR::Object::Type->get(class_name => $_) } @parent_class_names; |
|
26149
|
|
|
|
|
77419
|
|
1868
|
24751
|
|
|
|
|
43613
|
for my $co ($self, @parent_classes) { |
1869
|
50334
|
100
|
|
|
|
161812
|
if ($co->table_name) { |
1870
|
577
|
|
|
|
|
1151
|
$has_table = 1; |
1871
|
601
|
|
|
|
|
1583
|
last; |
1872
|
|
|
|
|
|
|
} |
1873
|
|
|
|
|
|
|
} |
1874
|
|
|
|
|
|
|
|
1875
|
24727
|
|
|
|
|
81257
|
my $data_source_obj = $self->data_source; |
1876
|
24817
|
|
|
|
|
26694
|
my $columns_are_upper_case; |
1877
|
24730
|
100
|
|
|
|
46436
|
if ($data_source_obj) { |
1878
|
2222
|
|
|
|
|
10924
|
$columns_are_upper_case = $data_source_obj->table_and_column_names_are_upper_case; |
1879
|
|
|
|
|
|
|
} |
1880
|
|
|
|
|
|
|
|
1881
|
24718
|
|
|
|
|
39694
|
my @sort_list = map { [$_->property_name, $_] } @property_objects; |
|
76567
|
|
|
|
|
105903
|
|
1882
|
24720
|
|
|
|
|
61898
|
for my $sorted_item ( sort { $a->[0] cmp $b->[0] } @sort_list ) { |
|
87883
|
|
|
|
|
72586
|
|
1883
|
76513
|
|
|
|
|
53048
|
my $property_object = $sorted_item->[1]; |
1884
|
76543
|
100
|
|
|
|
101791
|
if ($property_object->column_name) { |
1885
|
1854
|
|
|
|
|
3133
|
push @$props, $property_object->property_name; |
1886
|
1950
|
100
|
|
|
|
5171
|
push @$cols, $columns_are_upper_case ? uc($property_object->column_name) : $property_object->column_name; |
1887
|
|
|
|
|
|
|
} |
1888
|
|
|
|
|
|
|
} |
1889
|
|
|
|
|
|
|
|
1890
|
|
|
|
|
|
|
# set the flag to prevent this from occurring multiple times. |
1891
|
24739
|
|
|
|
|
89793
|
$self->generated(1); |
1892
|
|
|
|
|
|
|
|
1893
|
|
|
|
|
|
|
# read in filesystem package if there is one |
1894
|
|
|
|
|
|
|
#$self->use_filesystem_package($class_name); |
1895
|
|
|
|
|
|
|
|
1896
|
|
|
|
|
|
|
# Let each class in the inheritance hierarchy do any initialization |
1897
|
|
|
|
|
|
|
# required for this class. Note that the _init_subclass method does |
1898
|
|
|
|
|
|
|
# not call SUPER::, but relies on this code to find its parents. This |
1899
|
|
|
|
|
|
|
# is the only way around a sparsely-filled multiple inheritance tree. |
1900
|
|
|
|
|
|
|
|
1901
|
|
|
|
|
|
|
# TODO: Replace with $class_name->EVERY::LAST::_init_subclass() |
1902
|
|
|
|
|
|
|
|
1903
|
|
|
|
|
|
|
#unless ( |
1904
|
|
|
|
|
|
|
# $bootstrapping |
1905
|
|
|
|
|
|
|
# and |
1906
|
|
|
|
|
|
|
# $UR::Object::_init_subclass->{$class_name} |
1907
|
|
|
|
|
|
|
#) |
1908
|
|
|
|
|
|
|
{ |
1909
|
24765
|
|
|
|
|
22935
|
my @inheritance = $class_name->inheritance; |
|
24706
|
|
|
|
|
511344
|
|
1910
|
24744
|
|
|
|
|
30489
|
my %done; |
1911
|
24708
|
|
|
|
|
35113
|
for my $parent (reverse @inheritance) { |
1912
|
89014
|
|
|
|
|
216667
|
my $initializer = $parent->can("_init_subclass"); |
1913
|
88999
|
100
|
|
|
|
2702675
|
next unless $initializer; |
1914
|
4406
|
100
|
|
|
|
15397
|
next if $done{$initializer}; |
1915
|
2685
|
100
|
|
|
|
10564
|
$initializer->($class_name,$class_name) |
1916
|
|
|
|
|
|
|
or die "Parent class $parent failed to initialize subclass " |
1917
|
|
|
|
|
|
|
. "$class_name :" . $parent->error_message; |
1918
|
2704
|
|
|
|
|
10835
|
$done{$initializer} = 1; |
1919
|
|
|
|
|
|
|
} |
1920
|
|
|
|
|
|
|
} |
1921
|
|
|
|
|
|
|
|
1922
|
24712
|
100
|
|
|
|
144992
|
unless ($class_name->isa("UR::Object")) { |
1923
|
27
|
|
|
|
|
191
|
print Data::Dumper::Dumper('@C::ISA',\@C::ISA,'@B::ISA',\@B::ISA); |
1924
|
|
|
|
|
|
|
} |
1925
|
|
|
|
|
|
|
|
1926
|
|
|
|
|
|
|
# ensure the class is generated |
1927
|
24704
|
100
|
|
|
|
59826
|
die "Error in module for $class_name. Resulting class does not appear to be generated!" unless $self->generated; |
1928
|
|
|
|
|
|
|
|
1929
|
|
|
|
|
|
|
# ensure the class inherits from UR::Object |
1930
|
24721
|
100
|
|
|
|
71846
|
die "$class_name does not inherit from UR::Object!" unless $class_name->isa("UR::Object"); |
1931
|
|
|
|
|
|
|
|
1932
|
24700
|
|
|
|
|
115327
|
return 1; |
1933
|
|
|
|
|
|
|
} |
1934
|
|
|
|
|
|
|
|
1935
|
|
|
|
|
|
|
|
1936
|
|
|
|
|
|
|
1; |
1937
|
|
|
|
|
|
|
|
1938
|
|
|
|
|
|
|
|