line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package UR::Object::Type; |
2
|
|
|
|
|
|
|
|
3
|
266
|
|
|
266
|
|
1001
|
use warnings; |
|
266
|
|
|
|
|
297
|
|
|
266
|
|
|
|
|
7693
|
|
4
|
266
|
|
|
266
|
|
879
|
use strict; |
|
266
|
|
|
|
|
273
|
|
|
266
|
|
|
|
|
14437
|
|
5
|
|
|
|
|
|
|
require UR; |
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
# Used during bootstrapping. |
8
|
|
|
|
|
|
|
our @ISA = qw(UR::Object); |
9
|
|
|
|
|
|
|
our $VERSION = "0.46"; # UR $VERSION;; |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
our @CARP_NOT = qw( UR::Object UR::Context UR::ModuleLoader Class::Autouse UR::BoolExpr ); |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
# Most of the API for this module are legacy internals required by UR. |
14
|
266
|
|
|
266
|
|
124329
|
use UR::Object::Type::InternalAPI; |
|
266
|
|
|
|
|
910
|
|
|
266
|
|
|
|
|
4738
|
|
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
# This module implements define(), and most everything behind it. |
17
|
266
|
|
|
266
|
|
198916
|
use UR::Object::Type::Initializer; |
|
266
|
|
|
|
|
648
|
|
|
266
|
|
|
|
|
3490
|
|
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
# The methods used by the initializer to write accessors in perl. |
20
|
266
|
|
|
266
|
|
166193
|
use UR::Object::Type::AccessorWriter; |
|
266
|
|
|
|
|
641
|
|
|
266
|
|
|
|
|
3530
|
|
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
# The methods to extract/(re)create definition text in the module source file. |
23
|
266
|
|
|
266
|
|
126853
|
use UR::Object::Type::ModuleWriter; |
|
266
|
|
|
|
|
2183
|
|
|
266
|
|
|
|
|
6982
|
|
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
# Present the internal definer as an external method |
26
|
12892
|
|
|
12892
|
1
|
443826
|
sub define { shift->__define__(@_) } |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
# For efficiency, certain hash keys inside the class cache property metadata |
29
|
|
|
|
|
|
|
# These go in this array, and are cleared when property metadata is mutated |
30
|
|
|
|
|
|
|
our @cache_keys; |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
# This is the function behind $class_meta->properties(...) |
33
|
|
|
|
|
|
|
# It mimics the has-many object accessor, but handles inheritance |
34
|
|
|
|
|
|
|
# Once we have "isa" and "is-parent-of" operator we can do this with regular operators. |
35
|
|
|
|
|
|
|
push @cache_keys, '_properties'; |
36
|
|
|
|
|
|
|
sub _properties { |
37
|
240
|
|
|
240
|
|
991
|
my $self = shift; |
38
|
240
|
|
66
|
|
|
933
|
my $all = $self->{_properties} ||= do { |
39
|
|
|
|
|
|
|
# start with everything, as it's a small list |
40
|
136
|
|
|
|
|
863
|
my $map = $self->_property_name_class_map; |
41
|
136
|
|
|
|
|
200
|
my @all; |
42
|
136
|
|
|
|
|
720
|
for my $property_name (sort keys %$map) { |
43
|
991
|
|
|
|
|
874
|
my $class_names = $map->{$property_name}; |
44
|
991
|
|
|
|
|
905
|
my $class_name = $class_names->[0]; |
45
|
991
|
|
|
|
|
1237
|
my $id = $class_name . "\t" . $property_name; |
46
|
991
|
|
|
|
|
1735
|
my $property_meta = UR::Object::Property->get($id); |
47
|
991
|
50
|
|
|
|
1504
|
unless ($property_meta) { |
48
|
0
|
|
|
|
|
0
|
Carp::confess("Failed to find property meta for $class_name $property_name?"); |
49
|
|
|
|
|
|
|
} |
50
|
991
|
|
|
|
|
1276
|
push @all, $property_meta; |
51
|
|
|
|
|
|
|
} |
52
|
136
|
|
|
|
|
510
|
\@all; |
53
|
|
|
|
|
|
|
}; |
54
|
240
|
100
|
|
|
|
616
|
if (@_) { |
55
|
121
|
|
|
|
|
744
|
my ($bx, %extra) = UR::Object::Property->define_boolexpr(@_); |
56
|
121
|
|
|
|
|
292
|
my @matches = grep { $bx->evaluate($_) } @$all; |
|
811
|
|
|
|
|
1501
|
|
57
|
121
|
100
|
|
|
|
397
|
if (%extra) { |
58
|
|
|
|
|
|
|
# Additional meta-properties on meta-properties are not queryable until we |
59
|
|
|
|
|
|
|
# put the UR::Object::Property into a private sub-class. |
60
|
|
|
|
|
|
|
# This will give us most of the functionality. |
61
|
4
|
|
|
|
|
11
|
for my $key (keys %extra) { |
62
|
4
|
|
|
|
|
24
|
my ($name,$op) = ($key =~ /(\w+)\s*(.*)/); |
63
|
4
|
100
|
|
|
|
18
|
unless (defined $self->{attributes_have}->{$name}) { |
64
|
1
|
|
|
|
|
8
|
die "unknown property $name used to query properties of " . $self->class_name; |
65
|
|
|
|
|
|
|
} |
66
|
3
|
0
|
33
|
|
|
12
|
if ($op and $op ne '==' and $op ne 'eq') { |
|
|
|
33
|
|
|
|
|
67
|
0
|
|
|
|
|
0
|
die "operations besides equals are not supported currently for added meta-properties like $name on class " . $self->class_name; |
68
|
|
|
|
|
|
|
} |
69
|
3
|
|
|
|
|
7
|
my $value = $extra{$key}; |
70
|
266
|
|
|
266
|
|
93415
|
no warnings; |
|
266
|
|
|
|
|
621
|
|
|
266
|
|
|
|
|
141221
|
|
71
|
3
|
100
|
|
|
|
8
|
@matches = grep { $_->can($name) and $_->$name eq $value } @matches; |
|
7
|
|
|
|
|
25
|
|
72
|
|
|
|
|
|
|
} |
73
|
|
|
|
|
|
|
} |
74
|
120
|
50
|
|
|
|
422
|
return if not defined wantarray; |
75
|
120
|
100
|
|
|
|
585
|
return @matches if wantarray; |
76
|
7
|
50
|
|
|
|
20
|
die "Matched multiple meta-properties, but called in scalar context!" . Data::Dumper::Dumper(\@matches) if @matches > 1; |
77
|
7
|
|
|
|
|
21
|
return $matches[0]; |
78
|
|
|
|
|
|
|
} |
79
|
|
|
|
|
|
|
else { |
80
|
119
|
|
|
|
|
486
|
@$all; |
81
|
|
|
|
|
|
|
} |
82
|
|
|
|
|
|
|
} |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
sub property { |
85
|
446
|
50
|
|
446
|
1
|
4300
|
if (@_ == 2) { |
86
|
|
|
|
|
|
|
# optimize for the common case |
87
|
446
|
|
|
|
|
554
|
my ($self, $property_name) = @_; |
88
|
446
|
|
|
|
|
1319
|
my $class_names = $self->_property_name_class_map->{$property_name}; |
89
|
446
|
100
|
66
|
|
|
1912
|
return unless $class_names and @$class_names; |
90
|
414
|
|
|
|
|
874
|
my $id = $class_names->[0] . "\t" . $property_name; |
91
|
414
|
|
|
|
|
1079
|
return UR::Object::Property->get($id); |
92
|
|
|
|
|
|
|
} |
93
|
|
|
|
|
|
|
else { |
94
|
|
|
|
|
|
|
# this forces scalar context, raising an exception if |
95
|
|
|
|
|
|
|
# the params used result in more than one match |
96
|
0
|
|
|
|
|
0
|
my $one = shift->properties(@_); |
97
|
0
|
|
|
|
|
0
|
return $one; |
98
|
|
|
|
|
|
|
} |
99
|
|
|
|
|
|
|
} |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
push @cache_keys, '_property_names'; |
102
|
|
|
|
|
|
|
sub property_names { |
103
|
0
|
|
|
0
|
0
|
0
|
my $self = $_[0]; |
104
|
0
|
|
0
|
|
|
0
|
my $names = $self->{_property_names} ||= do { |
105
|
0
|
|
|
|
|
0
|
my @names = sort keys %{ shift->_property_name_class_map }; |
|
0
|
|
|
|
|
0
|
|
106
|
0
|
|
|
|
|
0
|
\@names; |
107
|
|
|
|
|
|
|
}; |
108
|
0
|
|
|
|
|
0
|
return @$names; |
109
|
|
|
|
|
|
|
} |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
push @cache_keys, '_property_name_class_map'; |
112
|
|
|
|
|
|
|
sub _property_name_class_map { |
113
|
582
|
|
|
582
|
|
714
|
my $self = shift; |
114
|
582
|
|
66
|
|
|
1737
|
my $map = $self->{_property_name_class_map} ||= do { |
115
|
214
|
|
|
|
|
483
|
my %map = (); |
116
|
214
|
|
|
|
|
909
|
for my $class_name ($self->class_name, $self->ancestry_class_names) { |
117
|
731
|
|
|
|
|
1814
|
my $class_meta = UR::Object::Type->get($class_name); |
118
|
731
|
50
|
|
|
|
1671
|
if (my $has = $class_meta->{has}) { |
119
|
731
|
|
|
|
|
2242
|
for my $key (sort keys %$has) { |
120
|
1433
|
|
100
|
|
|
4489
|
my $classes = $map{$key} ||= []; |
121
|
1433
|
|
|
|
|
2204
|
push @$classes, $class_name; |
122
|
|
|
|
|
|
|
} |
123
|
|
|
|
|
|
|
} |
124
|
|
|
|
|
|
|
} |
125
|
214
|
|
|
|
|
733
|
\%map; |
126
|
|
|
|
|
|
|
}; |
127
|
582
|
|
|
|
|
1038
|
return $map; |
128
|
|
|
|
|
|
|
} |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
# The prior implementation of _properties() (behind ->properties()) |
131
|
|
|
|
|
|
|
# filtered out certain property meta. This is the old version. |
132
|
|
|
|
|
|
|
# The new version above will return one object per property name in |
133
|
|
|
|
|
|
|
# the meta ancestry. |
134
|
|
|
|
|
|
|
sub _legacy_properties { |
135
|
0
|
|
|
0
|
|
|
my $self = shift; |
136
|
0
|
0
|
|
|
|
|
if (@_) { |
137
|
0
|
|
|
|
|
|
my $bx = UR::Object::Property->define_boolexpr(@_); |
138
|
0
|
|
|
|
|
|
my @matches = grep { $bx->evaluate($_) } $self->property_metas; |
|
0
|
|
|
|
|
|
|
139
|
0
|
0
|
|
|
|
|
return if not defined wantarray; |
140
|
0
|
0
|
|
|
|
|
return @matches if wantarray; |
141
|
0
|
0
|
|
|
|
|
die "Matched multiple meta-properties, but called in scalar context!" . Data::Dumper::Dumper(\@matches) if @matches > 1; |
142
|
0
|
|
|
|
|
|
return $matches[0]; |
143
|
|
|
|
|
|
|
} |
144
|
|
|
|
|
|
|
else { |
145
|
0
|
|
|
|
|
|
$self->property_metas; |
146
|
|
|
|
|
|
|
} |
147
|
|
|
|
|
|
|
} |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
1; |
150
|
|
|
|
|
|
|
|