| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package UR; |
|
2
|
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
|
|
4
|
|
|
|
|
|
|
# The UR module is itself a "UR::Namespace", besides being the root |
|
5
|
|
|
|
|
|
|
# module which bootstraps the system. The class definition itself |
|
6
|
|
|
|
|
|
|
# is made at the bottom of the file. |
|
7
|
|
|
|
|
|
|
|
|
8
|
266
|
|
|
266
|
|
2180501
|
use strict; |
|
|
266
|
|
|
|
|
343
|
|
|
|
266
|
|
|
|
|
6931
|
|
|
9
|
266
|
|
|
266
|
|
816
|
use warnings FATAL => 'all'; |
|
|
266
|
|
|
|
|
954
|
|
|
|
266
|
|
|
|
|
12718
|
|
|
10
|
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
# Set the version at compile time, since some other modules borrow it. |
|
12
|
|
|
|
|
|
|
our $VERSION = "0.46"; # UR $VERSION |
|
13
|
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
# Ensure we get detailed errors while starting up. |
|
15
|
|
|
|
|
|
|
# This is disabled at the bottom of the module. |
|
16
|
266
|
|
|
266
|
|
915
|
use Carp; |
|
|
266
|
|
|
|
|
325
|
|
|
|
266
|
|
|
|
|
18386
|
|
|
17
|
|
|
|
|
|
|
$SIG{__DIE__} = \&Carp::confess; |
|
18
|
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
# Ensure that, if the application changes directory, we do not |
|
20
|
|
|
|
|
|
|
# change where we load modules while running. |
|
21
|
266
|
|
|
266
|
|
983
|
use Cwd; |
|
|
266
|
|
|
|
|
323
|
|
|
|
266
|
|
|
|
|
118114
|
|
|
22
|
|
|
|
|
|
|
my @PERL5LIB = ($ENV{PERL5LIB} ? split(':', $ENV{PERL5LIB}) : ()); |
|
23
|
|
|
|
|
|
|
for my $dir (@INC, @PERL5LIB) { |
|
24
|
|
|
|
|
|
|
next unless -d $dir; |
|
25
|
|
|
|
|
|
|
$dir = Cwd::abs_path($dir) || $dir; |
|
26
|
|
|
|
|
|
|
} |
|
27
|
|
|
|
|
|
|
$ENV{PERL5LIB} = join(':', @PERL5LIB); |
|
28
|
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
# Also need to fix modules that were already loaded, so that when |
|
30
|
|
|
|
|
|
|
# a namespace is loaded the path will not change out from |
|
31
|
|
|
|
|
|
|
# underneath it. |
|
32
|
|
|
|
|
|
|
for my $module (keys %INC) { |
|
33
|
|
|
|
|
|
|
$INC{$module} = Cwd::abs_path($INC{$module}); |
|
34
|
|
|
|
|
|
|
} |
|
35
|
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
# UR supports several environment variables, found under UR/ENV |
|
37
|
|
|
|
|
|
|
# Any UR_* variable which is set but does NOT corresponde to a module found will cause an exit |
|
38
|
|
|
|
|
|
|
# (a hedge against typos such as UR_DBI_NO_COMMMMIT=1 leading to unexpected behavior) |
|
39
|
|
|
|
|
|
|
for my $e (keys %ENV) { |
|
40
|
|
|
|
|
|
|
next unless substr($e,0,3) eq 'UR_'; |
|
41
|
|
|
|
|
|
|
eval "use UR::Env::$e"; |
|
42
|
|
|
|
|
|
|
if ($@) { |
|
43
|
|
|
|
|
|
|
my $path = __FILE__; |
|
44
|
|
|
|
|
|
|
$path =~ s/.pm$//; |
|
45
|
|
|
|
|
|
|
my @files = glob($path . '/Env/*'); |
|
46
|
|
|
|
|
|
|
my @vars = map { /UR\/Env\/(.*).pm/; $1 } @files; |
|
47
|
|
|
|
|
|
|
print STDERR "Environment variable $e set to $ENV{$e} but there were errors using UR::Env::$e:\n" |
|
48
|
|
|
|
|
|
|
. "Available variables:\n\t" |
|
49
|
|
|
|
|
|
|
. join("\n\t",@vars) |
|
50
|
|
|
|
|
|
|
. "\n"; |
|
51
|
|
|
|
|
|
|
exit 1; |
|
52
|
|
|
|
|
|
|
} |
|
53
|
|
|
|
|
|
|
} |
|
54
|
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
# These two dump info about used modules and libraries at program exit. |
|
56
|
|
|
|
|
|
|
END { |
|
57
|
266
|
50
|
|
266
|
|
11747
|
if ($ENV{UR_USED_LIBS}) { |
|
58
|
0
|
|
|
|
|
0
|
print STDERR "Used library include paths (\@INC):\n"; |
|
59
|
0
|
|
|
|
|
0
|
for my $lib (@INC) { |
|
60
|
0
|
|
|
|
|
0
|
print STDERR "$lib\n"; |
|
61
|
|
|
|
|
|
|
} |
|
62
|
0
|
|
|
|
|
0
|
print STDERR "\n"; |
|
63
|
|
|
|
|
|
|
} |
|
64
|
266
|
50
|
|
|
|
1043
|
if ($ENV{UR_USED_MODS}) { |
|
65
|
0
|
|
|
|
|
0
|
print STDERR "Used modules and paths (\%INC):\n"; |
|
66
|
0
|
|
|
|
|
0
|
for my $mod (sort keys %INC) { |
|
67
|
0
|
0
|
|
|
|
0
|
if ($ENV{UR_USED_MODS} > 1) { |
|
68
|
0
|
|
|
|
|
0
|
print STDERR "$mod => $INC{$mod}\n"; |
|
69
|
|
|
|
|
|
|
} else { |
|
70
|
0
|
|
|
|
|
0
|
print STDERR "$mod\n"; |
|
71
|
|
|
|
|
|
|
} |
|
72
|
|
|
|
|
|
|
} |
|
73
|
0
|
|
|
|
|
0
|
print STDERR "\n"; |
|
74
|
|
|
|
|
|
|
} |
|
75
|
266
|
50
|
|
|
|
1012
|
if ($ENV{UR_DBI_SUMMARIZE_SQL}) { |
|
76
|
0
|
|
|
|
|
|
UR::DBI::print_sql_summary(); |
|
77
|
|
|
|
|
|
|
} |
|
78
|
|
|
|
|
|
|
} |
|
79
|
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
#Class::AutoloadCAN must be used before Class::Autouse, or the can methods will break in confusing ways. |
|
81
|
266
|
|
|
266
|
|
112741
|
use Class::AutoloadCAN; |
|
|
266
|
|
|
|
|
170445
|
|
|
|
266
|
|
|
|
|
1248
|
|
|
82
|
266
|
|
|
266
|
|
135145
|
use Class::Autouse; |
|
|
266
|
|
|
|
|
1225705
|
|
|
|
266
|
|
|
|
|
3854
|
|
|
83
|
|
|
|
|
|
|
BEGIN { |
|
84
|
266
|
|
|
266
|
|
20618
|
my $v = $Class::Autouse::VERSION; |
|
85
|
266
|
0
|
33
|
|
|
11228
|
unless (($v =~ /^\d+\.?\d*$/ && $v >= 2.0) |
|
|
|
|
33
|
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
86
|
|
|
|
|
|
|
or $v eq '1.99_02' |
|
87
|
|
|
|
|
|
|
or $v eq '1.99_04') { |
|
88
|
0
|
|
|
|
|
0
|
die "UR requires Class::Autouse 2.0 or greater (or 1.99_02 or 1.99_04)!!"; |
|
89
|
|
|
|
|
|
|
} |
|
90
|
|
|
|
|
|
|
}; |
|
91
|
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
# Regular deps |
|
93
|
266
|
|
|
266
|
|
115187
|
use Date::Format; |
|
|
266
|
|
|
|
|
1463131
|
|
|
|
266
|
|
|
|
|
303684
|
|
|
94
|
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
# |
|
96
|
|
|
|
|
|
|
# Because UR modules execute code when compiling to define their classes, |
|
97
|
|
|
|
|
|
|
# and require each other for that code to execute, there are bootstrapping |
|
98
|
|
|
|
|
|
|
# problems. |
|
99
|
|
|
|
|
|
|
# |
|
100
|
|
|
|
|
|
|
# Everything which is part of the core framework "requires" UR |
|
101
|
|
|
|
|
|
|
# which, of course, executes AFTER it has compiled its SUBS, |
|
102
|
|
|
|
|
|
|
# but BEFORE it defines its class. |
|
103
|
|
|
|
|
|
|
# |
|
104
|
|
|
|
|
|
|
# Everything which _uses_ the core of the framework "uses" its namespace, |
|
105
|
|
|
|
|
|
|
# either the specific top-level namespace module, or "UR" itself for components/extensions. |
|
106
|
|
|
|
|
|
|
# |
|
107
|
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
require UR::Exit; |
|
109
|
|
|
|
|
|
|
require UR::Util; |
|
110
|
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
require UR::DBI::Report; # this is used by UR::DBI |
|
112
|
|
|
|
|
|
|
require UR::DBI; # this needs a new name, and need only be used by UR::DataSource::RDBMS |
|
113
|
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
require UR::ModuleBase; # this should be switched to a role |
|
115
|
|
|
|
|
|
|
require UR::ModuleConfig; # used by ::Time, and also ::Lock ::Daemon |
|
116
|
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
require UR::Object::Iterator; |
|
118
|
|
|
|
|
|
|
require UR::Context::AutoUnloadPool; |
|
119
|
|
|
|
|
|
|
require UR::DeletedRef; |
|
120
|
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
require UR::Object; |
|
122
|
|
|
|
|
|
|
require UR::Object::Type; |
|
123
|
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
require UR::Object::Ghost; |
|
125
|
|
|
|
|
|
|
require UR::Object::Property; |
|
126
|
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
require UR::Observer; |
|
128
|
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
require UR::BoolExpr::Util; |
|
130
|
|
|
|
|
|
|
require UR::BoolExpr; # has meta |
|
131
|
|
|
|
|
|
|
require UR::BoolExpr::Template; # has meta |
|
132
|
|
|
|
|
|
|
require UR::BoolExpr::Template::PropertyComparison; # has meta |
|
133
|
|
|
|
|
|
|
require UR::BoolExpr::Template::Composite; # has meta |
|
134
|
|
|
|
|
|
|
require UR::BoolExpr::Template::And; # has meta |
|
135
|
|
|
|
|
|
|
require UR::BoolExpr::Template::Or; # has meta |
|
136
|
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
require UR::Object::Index; |
|
138
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
# |
|
140
|
|
|
|
|
|
|
# Define core metadata. |
|
141
|
|
|
|
|
|
|
# |
|
142
|
|
|
|
|
|
|
# This is done outside of the actual modules since the define() method |
|
143
|
|
|
|
|
|
|
# uses all of the modules themselves to do its work. |
|
144
|
|
|
|
|
|
|
# |
|
145
|
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
UR::Object::Type->define( |
|
147
|
|
|
|
|
|
|
class_name => 'UR::Object', |
|
148
|
|
|
|
|
|
|
is => [], # the default is to inherit from UR::Object, which is circular, so we explicitly say nothing |
|
149
|
|
|
|
|
|
|
is_abstract => 1, |
|
150
|
|
|
|
|
|
|
composite_id_separator => "\t", |
|
151
|
|
|
|
|
|
|
id_by => [ |
|
152
|
|
|
|
|
|
|
id => { is => 'Scalar', doc => 'unique identifier' } |
|
153
|
|
|
|
|
|
|
], |
|
154
|
|
|
|
|
|
|
id_generator => '-urinternal', |
|
155
|
|
|
|
|
|
|
); |
|
156
|
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
UR::Object::Type->define( |
|
158
|
|
|
|
|
|
|
class_name => "UR::Object::Index", |
|
159
|
|
|
|
|
|
|
id_by => ['indexed_class_name','indexed_property_string'], |
|
160
|
|
|
|
|
|
|
has => ['indexed_class_name','indexed_property_string'], |
|
161
|
|
|
|
|
|
|
is_transactional => 0, |
|
162
|
|
|
|
|
|
|
); |
|
163
|
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
UR::Object::Type->define( |
|
165
|
|
|
|
|
|
|
class_name => 'UR::Object::Ghost', |
|
166
|
|
|
|
|
|
|
is_abstract => 1, |
|
167
|
|
|
|
|
|
|
); |
|
168
|
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
UR::Object::Type->define( |
|
170
|
|
|
|
|
|
|
class_name => 'UR::Entity', |
|
171
|
|
|
|
|
|
|
extends => ['UR::Object'], |
|
172
|
|
|
|
|
|
|
is_abstract => 1, |
|
173
|
|
|
|
|
|
|
); |
|
174
|
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
UR::Object::Type->define( |
|
176
|
|
|
|
|
|
|
class_name => 'UR::Entity::Ghost', |
|
177
|
|
|
|
|
|
|
extends => ['UR::Object::Ghost'], |
|
178
|
|
|
|
|
|
|
is_abstract => 1, |
|
179
|
|
|
|
|
|
|
); |
|
180
|
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
# MORE METADATA CLASSES |
|
182
|
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
# For bootstrapping reasons, the properties with default values also need to be listed in |
|
184
|
|
|
|
|
|
|
# %class_property_defaults defined in UR::Object::Type::Initializer. If you make changes |
|
185
|
|
|
|
|
|
|
# to default values, please keep these in sync. |
|
186
|
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
UR::Object::Type->define( |
|
188
|
|
|
|
|
|
|
class_name => 'UR::Object::Type', |
|
189
|
|
|
|
|
|
|
doc => 'class/type meta-objects for UR', |
|
190
|
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
id_by => 'class_name', |
|
192
|
|
|
|
|
|
|
sub_classification_method_name => '_resolve_meta_class_name', |
|
193
|
|
|
|
|
|
|
is_abstract => 1, |
|
194
|
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
has => [ |
|
196
|
|
|
|
|
|
|
class_name => { is => 'Text', len => 256, is_optional => 1, |
|
197
|
|
|
|
|
|
|
doc => 'the name for the class described' }, |
|
198
|
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
properties => { |
|
200
|
|
|
|
|
|
|
is_many => 1, |
|
201
|
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
# this is calculated instead of a regular relationship |
|
203
|
|
|
|
|
|
|
# so we can do appropriate inheritance filtering. |
|
204
|
|
|
|
|
|
|
# We need an isa operator and its converse |
|
205
|
|
|
|
|
|
|
# in order to be fully declarative internally here |
|
206
|
|
|
|
|
|
|
calculate => 'shift->_properties(@_);', |
|
207
|
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
doc => 'property meta-objects for the class' |
|
209
|
|
|
|
|
|
|
}, |
|
210
|
|
|
|
|
|
|
id_properties => { is_many => 1, |
|
211
|
|
|
|
|
|
|
calculate => q( grep { defined $_->is_id } shift->_properties(@_) ), |
|
212
|
|
|
|
|
|
|
doc => 'meta-objects for the ID properties of the class' }, |
|
213
|
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
doc => { is => 'Text', len => 1024, is_optional => 1, |
|
215
|
|
|
|
|
|
|
doc => 'a one-line description of the class/type' }, |
|
216
|
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
is_abstract => { is => 'Boolean', default_value => 0, |
|
218
|
|
|
|
|
|
|
doc => 'abstract classes must be subclassified into a concreate class at create/load time' }, |
|
219
|
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
is_final => { is => 'Boolean', default_value => 0, |
|
221
|
|
|
|
|
|
|
doc => 'further subclassification is prohibited on final classes' }, |
|
222
|
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
is_transactional => { is => 'Boolean', default_value => 1, is_optional => 1, |
|
224
|
|
|
|
|
|
|
doc => 'non-transactional objects are left out of in-memory transactions' }, |
|
225
|
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
is_singleton => { is => 'Boolean', default_value => 0, |
|
227
|
|
|
|
|
|
|
doc => 'singleton classes have only one instance, or have each instance fall into a distinct subclass' }, |
|
228
|
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
namespace => { is => 'Text', len => 256, is_optional => 1, |
|
230
|
|
|
|
|
|
|
doc => 'the first "word" in the class name, which points to a UR::Namespace' }, |
|
231
|
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
schema_name => { is => 'Text', len => 256, is_optional => 1, |
|
233
|
|
|
|
|
|
|
doc => 'an arbitrary grouping for classes for which instances share a common storage system' }, |
|
234
|
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
data_source_id => { is => 'Text', len => 256, is_optional => 1, |
|
236
|
|
|
|
|
|
|
doc => 'for classes which persist beyond their current process, the identifier for their storage manager' }, |
|
237
|
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
#data_source_meta => { is => 'UR::DataSource', id_by => 'data_source_id', is_optional => 1, }, |
|
239
|
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
generated => { is => 'Boolean', is_transient => 1, default_value => 0, |
|
241
|
|
|
|
|
|
|
doc => 'an internal flag set when the class meta has fabricated accessors and methods in the class namespace' }, |
|
242
|
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
meta_class_name => { is => 'Text', |
|
244
|
|
|
|
|
|
|
doc => 'even meta-classess have a meta-class' }, |
|
245
|
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
composite_id_separator => { is => 'Text', len => 2 , default_value => "\t", is_optional => 1, |
|
247
|
|
|
|
|
|
|
doc => 'for classes whose objects have a multi-value "id", this overrides using a "\t" to compose/decompose' }, |
|
248
|
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
valid_signals => { is => 'ARRAY', is_optional => 1, |
|
250
|
|
|
|
|
|
|
doc => 'List of non-standard signal names observers can bind to ' }, |
|
251
|
|
|
|
|
|
|
# details used by the managment of the "real" entity outside of the app (persistence) |
|
252
|
|
|
|
|
|
|
table_name => { is => 'Text', len => undef, is_optional => 1, |
|
253
|
|
|
|
|
|
|
doc => 'for classes with a data source, this specifies the table or equivalent data structure which holds instances' }, |
|
254
|
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
select_hint => { is => 'Text', len => 1024 , is_optional => 1, |
|
256
|
|
|
|
|
|
|
doc => 'used to optimize access to underlying storage (database specific)' }, |
|
257
|
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
join_hint => { is => 'Text', len => 1024 , is_optional => 1, |
|
259
|
|
|
|
|
|
|
doc => 'used to optimize access to underlying storage when this class is part of a join (database specific)' }, |
|
260
|
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
id_generator => { is => 'Text', len => 256, is_optional => 1, |
|
262
|
|
|
|
|
|
|
doc => 'override the default choice for generating new object IDs' }, |
|
263
|
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
# different ways of handling subclassing at object load time |
|
265
|
|
|
|
|
|
|
subclassify_by => { is => 'Text', len => 256, is_optional => 1, |
|
266
|
|
|
|
|
|
|
doc => 'when set, the method specified will return the name of a specific subclass into which the object should go' }, |
|
267
|
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
subclass_description_preprocessor => { is => 'MethodName', len => 255, is_optional => 1, |
|
269
|
|
|
|
|
|
|
doc => 'a method which should pre-process the class description of sub-classes before construction' }, |
|
270
|
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
sub_classification_method_name => { is => 'Text', len => 256, is_optional => 1, |
|
272
|
|
|
|
|
|
|
doc => 'like subclassify_by, but examines whole objects not a single property' }, |
|
273
|
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
use_parallel_versions => { is => 'Boolean', is_optional => 1, default_value => 0, |
|
275
|
|
|
|
|
|
|
doc => 'inheriting from the is class will redirect to a ::V? module implemeting a specific version' }, |
|
276
|
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
# obsolete/internal |
|
278
|
|
|
|
|
|
|
type_name => { is => 'Text', len => 256, is_deprecated => 1, is_optional => 1 }, |
|
279
|
|
|
|
|
|
|
er_role => { is => 'Text', len => 256, is_optional => 1, default_value => 'entity' }, |
|
280
|
|
|
|
|
|
|
source => { is => 'Text', len => 256 , default_value => 'data dictionary', is_optional => 1 }, # This is obsolete and should be removed later |
|
281
|
|
|
|
|
|
|
sub_classification_meta_class_name => { is => 'Text', len => 1024 , is_optional => 1, |
|
282
|
|
|
|
|
|
|
doc => 'obsolete' }, |
|
283
|
|
|
|
|
|
|
first_sub_classification_method_name => { is => 'Text', len => 256, is_optional => 1, |
|
284
|
|
|
|
|
|
|
doc => 'cached value to handle a complex inheritance hierarchy with storage at some levels but not others' }, |
|
285
|
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
### Relationships with the other meta-classes (used internally) ### |
|
288
|
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
# UR::Namespaces are singletons referenced through their name |
|
290
|
|
|
|
|
|
|
namespace_meta => { is => 'UR::Namespace', id_by => 'namespace' }, |
|
291
|
|
|
|
|
|
|
is => { is => 'ARRAY', is_mutable => 0, doc => 'List of the parent class names' }, |
|
292
|
|
|
|
|
|
|
roles => { is => 'ARRAY', is_mutable => 0, is_optional => 1, doc => 'List of the roles consumed by this class' }, |
|
293
|
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
# linking to the direct parents, and the complete ancestry |
|
295
|
|
|
|
|
|
|
parent_class_metas => { is => 'UR::Object::Type', id_by => 'is', |
|
296
|
|
|
|
|
|
|
doc => 'The list of UR::Object::Type objects for the classes that are direct parents of this class' },#, is_many => 1 }, |
|
297
|
|
|
|
|
|
|
parent_class_names => { via => 'parent_class_metas', to => 'class_name', is_many => 1 }, |
|
298
|
|
|
|
|
|
|
parent_meta_class_names => { via => 'parent_class_metas', to => 'meta_class_name', is_many => 1 }, |
|
299
|
|
|
|
|
|
|
ancestry_meta_class_names => { via => 'ancestry_class_metas', to => 'meta_class_name', is_many => 1 }, |
|
300
|
|
|
|
|
|
|
ancestry_class_metas => { is => 'UR::Object::Type', id_by => 'is', where => [-recurse => [class_name => 'is']], |
|
301
|
|
|
|
|
|
|
doc => 'Climb the ancestry tree and return the class objects for all of them' }, |
|
302
|
|
|
|
|
|
|
ancestry_class_names => { via => 'ancestry_class_metas', to => 'class_name', is_many => 1 }, |
|
303
|
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
# This one isn't useful on its own, but is used to build the all_* accessors below |
|
305
|
|
|
|
|
|
|
all_class_metas => { is => 'UR::Object::Type', calculate => 'return ($self, $self->ancestry_class_metas)' }, |
|
306
|
|
|
|
|
|
|
|
|
307
|
|
|
|
|
|
|
# Properties defined on this class, parent classes, etc. |
|
308
|
|
|
|
|
|
|
# There's also a property_meta_by_name() method defined in the class |
|
309
|
|
|
|
|
|
|
direct_property_metas => { is => 'UR::Object::Property', reverse_as => 'class_meta', is_many => 1 }, |
|
310
|
|
|
|
|
|
|
direct_property_names => { via => 'direct_property_metas', to => 'property_name', is_many => 1 }, |
|
311
|
|
|
|
|
|
|
direct_id_property_metas => { is => 'UR::Object::Property', reverse_as => 'class_meta', where => [ 'is_id true' => 1, -order_by => 'is_id' ], is_many => 1 }, |
|
312
|
|
|
|
|
|
|
direct_id_property_names => { via => 'direct_id_property_metas', to => 'property_name', is_many => 1 }, |
|
313
|
|
|
|
|
|
|
|
|
314
|
|
|
|
|
|
|
ancestry_property_metas => { via => 'ancestry_class_metas', to => 'direct_property_metas', is_many => 1 }, |
|
315
|
|
|
|
|
|
|
ancestry_property_names => { via => 'ancestry_class_metas', to => 'direct_property_names', is_many => 1 }, |
|
316
|
|
|
|
|
|
|
ancestry_id_property_metas => { via => 'ancestry_class_metas', to => 'direct_id_property_metas', is_many => 1 }, |
|
317
|
|
|
|
|
|
|
ancestry_id_property_names => { via => 'ancestry_id_property_metas', to => 'property_name', is_many => 1 }, |
|
318
|
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
all_property_metas => { via => 'all_class_metas', to => 'direct_property_metas', is_many => 1 }, |
|
320
|
|
|
|
|
|
|
all_property_names => { via => 'all_property_metas', to => 'property_name', is_many => 1 }, |
|
321
|
|
|
|
|
|
|
all_id_property_metas => { via => 'all_class_metas', to => 'direct_id_property_metas', is_many => 1 }, |
|
322
|
|
|
|
|
|
|
all_id_property_names => { via => 'all_id_property_metas', to => 'property_name', is_many => 1 }, |
|
323
|
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
direct_id_by_property_metas => { via => 'direct_property_metas', to => '__self__', where => ['id_by true' => 1], is_many => 1, doc => "Properties with 'id_by' metadata, ie. direct object accessor properties" } , |
|
325
|
|
|
|
|
|
|
all_id_by_property_metas => { via => 'all_class_metas', to => 'direct_id_by_property_metas', is_many => 1}, |
|
326
|
|
|
|
|
|
|
direct_reverse_as_property_metas => { via => 'direct_property_metas', to => '__self__', where => ['reverse_as true' => 1], is_many => 1, doc => "Properties with 'reverse_as' metadata, ie. indirect object accessor properties" }, |
|
327
|
|
|
|
|
|
|
all_reverse_as_property_metas => { via => 'all_class_metas', to => 'direct_reverse_as_property_metas', is_many => 1}, |
|
328
|
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
# Datasource related stuff |
|
330
|
|
|
|
|
|
|
direct_column_names => { via => 'direct_property_metas', to => 'column_name', is_many => 1, where => [column_name => { operator => 'true' }] }, |
|
331
|
|
|
|
|
|
|
direct_id_column_names => { via => 'direct_id_property_metas', to => 'column_name', is_many => 1, where => [column_name => { operator => 'true'}] }, |
|
332
|
|
|
|
|
|
|
ancestry_column_names => { via => 'ancestry_class_metas', to => 'direct_column_names', is_many => 1 }, |
|
333
|
|
|
|
|
|
|
ancestry_id_column_names => { via => 'ancestry_class_metas', to => 'direct_id_column_names', is_many => 1 }, |
|
334
|
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
# Are these *columnless* properties actually necessary? The user could just use direct_property_metas(column_name => undef) |
|
336
|
|
|
|
|
|
|
direct_columnless_property_metas => { is => 'UR::Object::Property', reverse_as => 'class_meta', where => [column_name => undef], is_many => 1 }, |
|
337
|
|
|
|
|
|
|
direct_columnless_property_names => { via => 'direct_columnless_property_metas', to => 'property_name', is_many => 1 }, |
|
338
|
|
|
|
|
|
|
ancestry_columnless_property_metas => { via => 'ancestry_class_metas', to => 'direct_columnless_property_metas', is_many => 1 }, |
|
339
|
|
|
|
|
|
|
ancestry_columnless_property_names => { via => 'ancestry_columnless_property_metas', to => 'property_name', is_many => 1 }, |
|
340
|
|
|
|
|
|
|
ancestry_table_names => { via => 'ancestry_class_metas', to => 'table_name', is_many => 1 }, |
|
341
|
|
|
|
|
|
|
all_table_names => { via => 'all_class_metas', to => 'table_name', is_many => 1 }, |
|
342
|
|
|
|
|
|
|
all_column_names => { via => 'all_class_metas', to => 'direct_column_names', is_many => 1 }, |
|
343
|
|
|
|
|
|
|
all_id_column_names => { via => 'all_class_metas', to => 'direct_id_column_names', is_many => 1 }, |
|
344
|
|
|
|
|
|
|
all_columnless_property_metas => { via => 'all_class_metas', to => 'direct_columnless_property_metas', is_many => 1 }, |
|
345
|
|
|
|
|
|
|
all_columnless_property_names => { via => 'all_class_metas', to => 'direct_columnless_property_names', is_many => 1 }, |
|
346
|
|
|
|
|
|
|
], |
|
347
|
|
|
|
|
|
|
); |
|
348
|
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
UR::Object::Type->define( |
|
350
|
|
|
|
|
|
|
class_name => 'UR::Object::Property', |
|
351
|
|
|
|
|
|
|
id_properties => [ |
|
352
|
|
|
|
|
|
|
class_name => { is => 'Text', len => 256 }, |
|
353
|
|
|
|
|
|
|
property_name => { is => 'Text', len => 256 }, |
|
354
|
|
|
|
|
|
|
], |
|
355
|
|
|
|
|
|
|
has_optional => [ |
|
356
|
|
|
|
|
|
|
property_type => { is => 'Text', len => 256 , is_optional => 1}, |
|
357
|
|
|
|
|
|
|
column_name => { is => 'Text', len => 256, is_optional => 1 }, |
|
358
|
|
|
|
|
|
|
data_length => { is => 'Text', len => 32, is_optional => 1 }, |
|
359
|
|
|
|
|
|
|
data_type => { is => 'Text', len => 256, is_optional => 1 }, |
|
360
|
|
|
|
|
|
|
calculated_default => { is_optional => 1 }, |
|
361
|
|
|
|
|
|
|
default_value => { is_optional => 1 }, |
|
362
|
|
|
|
|
|
|
valid_values => { is => 'ARRAY', is_optional => 1, }, |
|
363
|
|
|
|
|
|
|
example_values => { is => 'ARRAY', is_optional => 1, doc => 'example valid values; used to generate help text for Commands' }, |
|
364
|
|
|
|
|
|
|
doc => { is => 'Text', len => 1000, is_optional => 1 }, |
|
365
|
|
|
|
|
|
|
is_id => { is => 'Integer', default_value => undef, doc => 'denotes this is an ID property of the class, and ranks them' }, |
|
366
|
|
|
|
|
|
|
is_optional => { is => 'Boolean' , default_value => 0}, |
|
367
|
|
|
|
|
|
|
is_transient => { is => 'Boolean' , default_value => 0}, |
|
368
|
|
|
|
|
|
|
is_constant => { is => 'Boolean' , default_value => 0}, # never changes |
|
369
|
|
|
|
|
|
|
is_mutable => { is => 'Boolean' , default_value => 1}, # can be changed explicitly via accessor (cannot be constant) |
|
370
|
|
|
|
|
|
|
is_volatile => { is => 'Boolean' , default_value => 0}, # changes w/o a signal: (cannot be constant or transactional) |
|
371
|
|
|
|
|
|
|
is_classwide => { is => 'Boolean' , default_value => 0}, |
|
372
|
|
|
|
|
|
|
is_delegated => { is => 'Boolean' , default_value => 0}, |
|
373
|
|
|
|
|
|
|
is_calculated => { is => 'Boolean' , default_value => 0}, |
|
374
|
|
|
|
|
|
|
is_transactional => { is => 'Boolean' , default_value => 1}, # STM works on these, and the object can possibly save outside the app |
|
375
|
|
|
|
|
|
|
is_abstract => { is => 'Boolean' , default_value => 0}, |
|
376
|
|
|
|
|
|
|
is_concrete => { is => 'Boolean' , default_value => 1}, |
|
377
|
|
|
|
|
|
|
is_final => { is => 'Boolean' , default_value => 0}, |
|
378
|
|
|
|
|
|
|
is_many => { is => 'Boolean' , default_value => 0}, |
|
379
|
|
|
|
|
|
|
is_aggregate => { is => 'Boolean' , default_value => 0}, |
|
380
|
|
|
|
|
|
|
is_deprecated => { is => 'Boolean', default_value => 0}, |
|
381
|
|
|
|
|
|
|
is_numeric => { calculate_from => ['data_type'], }, |
|
382
|
|
|
|
|
|
|
id_by => { is => 'ARRAY', is_optional => 1}, |
|
383
|
|
|
|
|
|
|
id_class_by => { is => 'Text', is_optional => 1}, |
|
384
|
|
|
|
|
|
|
is_undocumented => { is => 'Boolean', is_optional => 1, doc => 'do not show in documentation to users' }, |
|
385
|
|
|
|
|
|
|
doc_position => { is => 'Number', is_optional => 1, doc => 'override the sort position within documentation' }, |
|
386
|
|
|
|
|
|
|
access_as => { is => 'Text', is_optional => 1, doc => 'when id_class_by is set, and this is set to "auto", primitives will return as their ID instead of boxed' }, |
|
387
|
|
|
|
|
|
|
order_by => { is => 'ARRAY', is_optional => 1}, |
|
388
|
|
|
|
|
|
|
specify_by => { is => 'Text', is_optional => 1}, |
|
389
|
|
|
|
|
|
|
reverse_as => { is => 'ARRAY', is_optional => 1 }, |
|
390
|
|
|
|
|
|
|
implied_by => { is => 'Text' , is_optional => 1}, |
|
391
|
|
|
|
|
|
|
via => { is => 'Text' , is_optional => 1 }, |
|
392
|
|
|
|
|
|
|
to => { is => 'Text' , is_optional => 1}, |
|
393
|
|
|
|
|
|
|
where => { is => 'ARRAY', is_optional => 1}, |
|
394
|
|
|
|
|
|
|
calculate => { is => 'Text' , is_optional => 1}, |
|
395
|
|
|
|
|
|
|
calculate_from => { is => 'ARRAY' , is_optional => 1}, |
|
396
|
|
|
|
|
|
|
calculate_perl => { is => 'Perl' , is_optional => 1}, |
|
397
|
|
|
|
|
|
|
calculate_sql => { is => 'SQL' , is_optional => 1}, |
|
398
|
|
|
|
|
|
|
calculate_js => { is => 'JavaScript' , is_optional => 1}, |
|
399
|
|
|
|
|
|
|
constraint_name => { is => 'Text' , is_optional => 1}, |
|
400
|
|
|
|
|
|
|
is_legacy_eav => { is => 'Boolean' , is_optional => 1}, |
|
401
|
|
|
|
|
|
|
is_dimension => { is => 'Boolean', is_optional => 1}, |
|
402
|
|
|
|
|
|
|
is_specified_in_module_header => { is => 'Boolean', default_value => 0 }, |
|
403
|
|
|
|
|
|
|
position_in_module_header => { is => 'Integer', is_optional => 1, doc => "Line in the class definition source's section this property appears" }, |
|
404
|
|
|
|
|
|
|
singular_name => { is => 'Text' }, |
|
405
|
|
|
|
|
|
|
plural_name => { is => 'Text' }, |
|
406
|
|
|
|
|
|
|
|
|
407
|
|
|
|
|
|
|
class_meta => { is => 'UR::Object::Type', id_by => 'class_name' }, |
|
408
|
|
|
|
|
|
|
r_class_meta => { is => 'UR::Object::Type', id_by => 'data_type' }, |
|
409
|
|
|
|
|
|
|
], |
|
410
|
|
|
|
|
|
|
unique_constraints => [ |
|
411
|
|
|
|
|
|
|
{ properties => [qw/property_name class_name/], sql => 'SUPER_FAKE_O4' }, |
|
412
|
|
|
|
|
|
|
], |
|
413
|
|
|
|
|
|
|
); |
|
414
|
|
|
|
|
|
|
|
|
415
|
|
|
|
|
|
|
|
|
416
|
|
|
|
|
|
|
UR::Object::Type->define( |
|
417
|
|
|
|
|
|
|
class_name => 'UR::Object::Property::Calculated::From', |
|
418
|
|
|
|
|
|
|
id_properties => [qw/class_name calculated_property_name source_property_name/], |
|
419
|
|
|
|
|
|
|
); |
|
420
|
|
|
|
|
|
|
|
|
421
|
|
|
|
|
|
|
require UR::Singleton; |
|
422
|
|
|
|
|
|
|
require UR::Namespace; |
|
423
|
|
|
|
|
|
|
|
|
424
|
|
|
|
|
|
|
UR::Object::Type->define( |
|
425
|
|
|
|
|
|
|
class_name => 'UR', |
|
426
|
|
|
|
|
|
|
extends => ['UR::Namespace'], |
|
427
|
|
|
|
|
|
|
); |
|
428
|
|
|
|
|
|
|
|
|
429
|
|
|
|
|
|
|
require UR::Context; |
|
430
|
|
|
|
|
|
|
UR::Object::Type->initialize_bootstrap_classes; |
|
431
|
|
|
|
|
|
|
|
|
432
|
|
|
|
|
|
|
require UR::Role; |
|
433
|
|
|
|
|
|
|
require Command; |
|
434
|
|
|
|
|
|
|
|
|
435
|
|
|
|
|
|
|
$UR::initialized = 1; |
|
436
|
|
|
|
|
|
|
|
|
437
|
|
|
|
|
|
|
require UR::Change; |
|
438
|
|
|
|
|
|
|
require UR::Context::Root; |
|
439
|
|
|
|
|
|
|
require UR::Context::Process; |
|
440
|
|
|
|
|
|
|
require UR::Object::Tag; |
|
441
|
|
|
|
|
|
|
|
|
442
|
|
|
|
|
|
|
do { |
|
443
|
|
|
|
|
|
|
UR::Context->_initialize_for_current_process(); |
|
444
|
|
|
|
|
|
|
}; |
|
445
|
|
|
|
|
|
|
|
|
446
|
|
|
|
|
|
|
require UR::ModuleLoader; # signs us up with Class::Autouse |
|
447
|
|
|
|
|
|
|
require UR::Value::Iterator; |
|
448
|
|
|
|
|
|
|
require UR::Object::View; |
|
449
|
|
|
|
|
|
|
require UR::Object::Join; |
|
450
|
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
sub main::ur_core { |
|
452
|
0
|
|
|
0
|
|
|
print STDERR "Dumping rules and templates to ./ur_core.stor...\n"; |
|
453
|
0
|
|
|
|
|
|
my $dump; |
|
454
|
0
|
0
|
|
|
|
|
unless(open($dump, ">ur_core.stor")) { |
|
455
|
0
|
|
|
|
|
|
print STDERR "Can't open ur_core.stor for writing: $!"; |
|
456
|
0
|
|
|
|
|
|
exit; |
|
457
|
|
|
|
|
|
|
} |
|
458
|
|
|
|
|
|
|
store_fd([ |
|
459
|
0
|
|
|
|
|
|
$UR::Object::rule_templates, |
|
460
|
|
|
|
|
|
|
$UR::Object::rules, |
|
461
|
|
|
|
|
|
|
], |
|
462
|
|
|
|
|
|
|
$dump); |
|
463
|
0
|
|
|
|
|
|
close $dump; |
|
464
|
0
|
|
|
|
|
|
exit(); |
|
465
|
|
|
|
|
|
|
} |
|
466
|
|
|
|
|
|
|
|
|
467
|
|
|
|
|
|
|
1; |
|
468
|
|
|
|
|
|
|
__END__ |