caruby-core 1.5.5 → 2.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +9 -0
- data/History.md +5 -1
- data/lib/caruby.rb +3 -5
- data/lib/caruby/caruby-src.tar.gz +0 -0
- data/lib/caruby/database.rb +53 -69
- data/lib/caruby/database/application_service.rb +25 -0
- data/lib/caruby/database/cache.rb +60 -0
- data/lib/caruby/database/fetched_matcher.rb +52 -38
- data/lib/caruby/database/lazy_loader.rb +4 -4
- data/lib/caruby/database/operation.rb +34 -0
- data/lib/caruby/database/persistable.rb +171 -86
- data/lib/caruby/database/persistence_service.rb +32 -34
- data/lib/caruby/database/persistifier.rb +100 -43
- data/lib/caruby/database/reader.rb +107 -85
- data/lib/caruby/database/reader_template_builder.rb +60 -0
- data/lib/caruby/database/saved_matcher.rb +3 -3
- data/lib/caruby/database/sql_executor.rb +88 -17
- data/lib/caruby/database/writer.rb +213 -177
- data/lib/caruby/database/writer_template_builder.rb +334 -0
- data/lib/caruby/{util → helpers}/controlled_value.rb +0 -0
- data/lib/caruby/{util → helpers}/coordinate.rb +4 -4
- data/lib/caruby/{util → helpers}/person.rb +3 -3
- data/lib/caruby/{util → helpers}/properties.rb +7 -9
- data/lib/caruby/{util → helpers}/roman.rb +2 -2
- data/lib/caruby/{util → helpers}/version.rb +1 -1
- data/lib/caruby/json/deserializer.rb +2 -2
- data/lib/caruby/json/serializer.rb +49 -7
- data/lib/caruby/metadata.rb +30 -0
- data/lib/caruby/metadata/java_property.rb +21 -0
- data/lib/caruby/metadata/propertied.rb +191 -0
- data/lib/caruby/metadata/property.rb +22 -0
- data/lib/caruby/metadata/property_characteristics.rb +201 -0
- data/lib/caruby/migration/migratable.rb +11 -182
- data/lib/caruby/rdbi/driver/jdbc.rb +446 -0
- data/lib/caruby/resource.rb +20 -823
- data/lib/caruby/version.rb +1 -1
- data/test/lib/caruby/database/cache_test.rb +54 -0
- data/test/lib/caruby/{util → helpers}/controlled_value_test.rb +3 -5
- data/test/lib/caruby/{util → helpers}/person_test.rb +4 -6
- data/test/lib/caruby/helpers/properties_test.rb +34 -0
- data/test/lib/caruby/{util → helpers}/roman_test.rb +2 -3
- data/test/lib/caruby/{util → helpers}/version_test.rb +2 -3
- data/test/lib/helper.rb +7 -0
- metadata +161 -214
- data/lib/caruby/cli/application.rb +0 -36
- data/lib/caruby/cli/command.rb +0 -202
- data/lib/caruby/csv/csv_mapper.rb +0 -159
- data/lib/caruby/csv/csvio.rb +0 -203
- data/lib/caruby/database/search_template_builder.rb +0 -56
- data/lib/caruby/database/store_template_builder.rb +0 -278
- data/lib/caruby/domain.rb +0 -193
- data/lib/caruby/domain/attribute.rb +0 -584
- data/lib/caruby/domain/attributes.rb +0 -628
- data/lib/caruby/domain/dependency.rb +0 -225
- data/lib/caruby/domain/id_alias.rb +0 -22
- data/lib/caruby/domain/importer.rb +0 -183
- data/lib/caruby/domain/introspection.rb +0 -176
- data/lib/caruby/domain/inverse.rb +0 -172
- data/lib/caruby/domain/inversible.rb +0 -90
- data/lib/caruby/domain/java_attribute.rb +0 -173
- data/lib/caruby/domain/merge.rb +0 -185
- data/lib/caruby/domain/metadata.rb +0 -142
- data/lib/caruby/domain/mixin.rb +0 -35
- data/lib/caruby/domain/properties.rb +0 -95
- data/lib/caruby/domain/reference_visitor.rb +0 -428
- data/lib/caruby/domain/uniquify.rb +0 -50
- data/lib/caruby/import/java.rb +0 -387
- data/lib/caruby/migration/migrator.rb +0 -918
- data/lib/caruby/migration/resource_module.rb +0 -9
- data/lib/caruby/migration/uniquify.rb +0 -17
- data/lib/caruby/util/attribute_path.rb +0 -44
- data/lib/caruby/util/cache.rb +0 -56
- data/lib/caruby/util/class.rb +0 -149
- data/lib/caruby/util/collection.rb +0 -1152
- data/lib/caruby/util/domain_extent.rb +0 -46
- data/lib/caruby/util/file_separator.rb +0 -65
- data/lib/caruby/util/inflector.rb +0 -27
- data/lib/caruby/util/log.rb +0 -95
- data/lib/caruby/util/math.rb +0 -12
- data/lib/caruby/util/merge.rb +0 -59
- data/lib/caruby/util/module.rb +0 -18
- data/lib/caruby/util/options.rb +0 -97
- data/lib/caruby/util/partial_order.rb +0 -35
- data/lib/caruby/util/pretty_print.rb +0 -204
- data/lib/caruby/util/stopwatch.rb +0 -74
- data/lib/caruby/util/topological_sync_enumerator.rb +0 -62
- data/lib/caruby/util/transitive_closure.rb +0 -55
- data/lib/caruby/util/tree.rb +0 -48
- data/lib/caruby/util/trie.rb +0 -37
- data/lib/caruby/util/uniquifier.rb +0 -30
- data/lib/caruby/util/validation.rb +0 -20
- data/lib/caruby/util/visitor.rb +0 -365
- data/lib/caruby/util/weak_hash.rb +0 -36
- data/test/lib/caruby/csv/csv_mapper_test.rb +0 -40
- data/test/lib/caruby/csv/csvio_test.rb +0 -69
- data/test/lib/caruby/database/persistable_test.rb +0 -92
- data/test/lib/caruby/domain/domain_test.rb +0 -112
- data/test/lib/caruby/domain/inversible_test.rb +0 -99
- data/test/lib/caruby/domain/reference_visitor_test.rb +0 -130
- data/test/lib/caruby/import/java_test.rb +0 -80
- data/test/lib/caruby/import/mixed_case_test.rb +0 -14
- data/test/lib/caruby/migration/test_case.rb +0 -102
- data/test/lib/caruby/test_case.rb +0 -230
- data/test/lib/caruby/util/cache_test.rb +0 -23
- data/test/lib/caruby/util/class_test.rb +0 -61
- data/test/lib/caruby/util/collection_test.rb +0 -398
- data/test/lib/caruby/util/command_test.rb +0 -55
- data/test/lib/caruby/util/domain_extent_test.rb +0 -60
- data/test/lib/caruby/util/file_separator_test.rb +0 -30
- data/test/lib/caruby/util/inflector_test.rb +0 -12
- data/test/lib/caruby/util/lazy_hash_test.rb +0 -34
- data/test/lib/caruby/util/merge_test.rb +0 -83
- data/test/lib/caruby/util/module_test.rb +0 -25
- data/test/lib/caruby/util/options_test.rb +0 -59
- data/test/lib/caruby/util/partial_order_test.rb +0 -42
- data/test/lib/caruby/util/pretty_print_test.rb +0 -85
- data/test/lib/caruby/util/properties_test.rb +0 -50
- data/test/lib/caruby/util/stopwatch_test.rb +0 -18
- data/test/lib/caruby/util/topological_sync_enumerator_test.rb +0 -69
- data/test/lib/caruby/util/transitive_closure_test.rb +0 -67
- data/test/lib/caruby/util/tree_test.rb +0 -23
- data/test/lib/caruby/util/trie_test.rb +0 -14
- data/test/lib/caruby/util/visitor_test.rb +0 -278
- data/test/lib/caruby/util/weak_hash_test.rb +0 -45
- data/test/lib/examples/clinical_trials/migration/migration_test.rb +0 -58
- data/test/lib/examples/clinical_trials/migration/test_case.rb +0 -38
@@ -1,19 +1,61 @@
|
|
1
1
|
module CaRuby
|
2
2
|
module JSON
|
3
|
-
# {Resource} => JSON serializer.
|
3
|
+
# {Jinx::Resource} => JSON serializer.
|
4
4
|
module Serializer
|
5
5
|
# @param args the JSON serialization options
|
6
|
-
# @return [String] the JSON representation of this {Resource}
|
6
|
+
# @return [String] the JSON representation of this {Jinx::Resource}
|
7
7
|
def to_json(*args)
|
8
8
|
database.lazy_loader.disable do
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
{'json_class' => [self.class.domain_module, self.class.name.demodulize].join('::'),
|
13
|
-
'data' => value_hash(self.class.nonowner_attributes)
|
9
|
+
{
|
10
|
+
'json_class' => json_class_name,
|
11
|
+
'data' => json_value_hash
|
14
12
|
}.to_json(*args)
|
15
13
|
end
|
16
14
|
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
# The JSON class name must be scoped by the Resource package module, not the
|
19
|
+
# Java package, in order to recognize the Jinx::Resource JSON hooks.
|
20
|
+
#
|
21
|
+
# @return [String] the class name qualified by the Resource package module name context
|
22
|
+
def json_class_name
|
23
|
+
[self.class.domain_module, self.class.name.demodulize].join('::')
|
24
|
+
end
|
25
|
+
|
26
|
+
# Builds a serializable attribute => value hash. An independent or owner attribute
|
27
|
+
# value is a copy of the referenced domain object consisting of only the key attributes.
|
28
|
+
#
|
29
|
+
# @return [{Symbol => Object}] the serializable value hash
|
30
|
+
def json_value_hash
|
31
|
+
vh = value_hash(self.class.nondomain_attributes)
|
32
|
+
vh.merge!(value_hash(self.class.dependent_attributes))
|
33
|
+
self.class.independent_attributes.each do |oa|
|
34
|
+
value = send(oa) || next
|
35
|
+
vh[oa] = owner.copy(owner.class.all_key_attributes)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def json_independent_reference(ref)
|
40
|
+
return ref.map { |item| json_independent_reference(item) } if ref.collection?
|
41
|
+
ref.copy(json_foreign_key_value_hash(ref))
|
42
|
+
end
|
43
|
+
|
44
|
+
def json_foreign_key_value_hash(ref)
|
45
|
+
json_key_value_hash(ref, ref.class.primary_key_attributes) or
|
46
|
+
json_key_value_hash(ref, ref.class.secondary_key_attributes) or
|
47
|
+
json_key_value_hash(ref, ref.class.alternate_key_attributes)
|
48
|
+
Hash::EMPTY_HASH
|
49
|
+
end
|
50
|
+
|
51
|
+
def json_key_value_hash(ref, attributes)
|
52
|
+
attributes.to_compact_hash { |ka| json_foreign_key_value(ref, ka) || return }
|
53
|
+
end
|
54
|
+
|
55
|
+
def json_foreign_key_value(ref, attribute)
|
56
|
+
value = ref.send(attribute) || return
|
57
|
+
Jinx::Resource === value ? json_foreign_key_value_hash(value) : value
|
58
|
+
end
|
17
59
|
end
|
18
60
|
end
|
19
61
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'jinx/json/deserializer'
|
2
|
+
require 'caruby/metadata/propertied'
|
3
|
+
|
4
|
+
module CaRuby
|
5
|
+
# The metadata persistence mix-in.
|
6
|
+
module Metadata
|
7
|
+
include Propertied, Jinx::JSON::Deserializer, Jinx::Metadata
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
# @param [Property] the property to print
|
12
|
+
# @return [<Symbol>] the flags to modify the property
|
13
|
+
def pretty_print_attribute_flags(prop)
|
14
|
+
flags = super
|
15
|
+
flags << :logical if prop.logical?
|
16
|
+
flags << :autogenerated if prop.autogenerated?
|
17
|
+
flags
|
18
|
+
end
|
19
|
+
|
20
|
+
# @return [{String => <Symbol>}] the attributes to print
|
21
|
+
def pretty_print_attribute_hash
|
22
|
+
super.merge!({
|
23
|
+
'creatable domain attributes' => creatable_domain_attributes,
|
24
|
+
'updatable domain attributes' => updatable_domain_attributes,
|
25
|
+
'fetched domain attributes' => fetched_domain_attributes,
|
26
|
+
'cascaded domain attributes' => cascaded_attributes
|
27
|
+
})
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'jinx/metadata/java_property'
|
2
|
+
require 'caruby/metadata/property_characteristics'
|
3
|
+
|
4
|
+
# Mix persistence into +Jinx::JavaProperty+.
|
5
|
+
module CaRuby
|
6
|
+
class JavaProperty < Jinx::JavaProperty
|
7
|
+
include CaRuby::PropertyCharacteristics
|
8
|
+
|
9
|
+
def initialize(pd, declarer, restricted_type=nil)
|
10
|
+
super
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
# @param [Symbol] the flag to set
|
16
|
+
# @return [Boolean] whether the flag is supported
|
17
|
+
def flag_supported?(flag)
|
18
|
+
super or CaRuby::PropertyCharacteristics::SUPPORTED_FLAGS.include?(flag)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,191 @@
|
|
1
|
+
require 'jinx/metadata/propertied'
|
2
|
+
require 'caruby/metadata/property'
|
3
|
+
require 'caruby/metadata/java_property'
|
4
|
+
|
5
|
+
module CaRuby
|
6
|
+
# Augments a caRuby application domain class with {PropertyCharacteristics} persistence meta-data.
|
7
|
+
#
|
8
|
+
# A Jinx-enabled caRuby application domain module enables CaRuby persistence by adding the following
|
9
|
+
# method definition:
|
10
|
+
# def self.add_metadata(klass)
|
11
|
+
# super
|
12
|
+
# klass.extend(CaRuby::Propertied)
|
13
|
+
# end
|
14
|
+
module Propertied
|
15
|
+
include Jinx::Propertied
|
16
|
+
|
17
|
+
# @return [<Symbol>] the dependent attributes
|
18
|
+
def autogenerated_dependent_attributes
|
19
|
+
@ag_dep_flt ||= dependent_attributes.compose { |prop| prop.autogenerated? }
|
20
|
+
end
|
21
|
+
|
22
|
+
# @return [<Symbol>] the autogenerated logical dependent attributes
|
23
|
+
# @see #logical_dependent_attributes
|
24
|
+
# @see Property#autogenerated?
|
25
|
+
def autogenerated_logical_dependent_attributes
|
26
|
+
@ag_log_dep_flt ||= dependent_attributes.compose { |prop| prop.autogenerated? and prop.logical? }
|
27
|
+
end
|
28
|
+
|
29
|
+
# @return [<Symbol>] the {Property#fetch_saved?} attributes
|
30
|
+
def saved_attributes_to_fetch
|
31
|
+
@sv_ftch_flt ||= domain_attributes.compose { |prop| prop.fetch_saved? }
|
32
|
+
end
|
33
|
+
|
34
|
+
# @return [<Symbol>] the logical dependent attributes
|
35
|
+
# @see Property#logical?
|
36
|
+
def logical_dependent_attributes
|
37
|
+
@log_dep_flt ||= dependent_attributes.compose { |prop| prop.logical? }
|
38
|
+
end
|
39
|
+
|
40
|
+
# @return [<Symbol>] the auto-generated attributes
|
41
|
+
# @see Property#autogenerated?
|
42
|
+
def autogenerated_attributes
|
43
|
+
@ag_flt ||= attribute_filter { |prop| prop.autogenerated? }
|
44
|
+
end
|
45
|
+
|
46
|
+
# @return [<Symbol>] the auto-generated non-domain attributes
|
47
|
+
# @see Property#nondomain?
|
48
|
+
# @see Property#autogenerated?
|
49
|
+
def autogenerated_nondomain_attributes
|
50
|
+
@ag_nd_flt ||= attribute_filter { |prop| prop.autogenerated? and prop.nondomain? }
|
51
|
+
end
|
52
|
+
|
53
|
+
# @return [<Symbol>] the {Property#volatile?} non-domain attributes
|
54
|
+
def volatile_nondomain_attributes
|
55
|
+
@unsvd_nd_flt ||= attribute_filter { |prop| prop.volatile? and prop.nondomain? }
|
56
|
+
end
|
57
|
+
|
58
|
+
# @return [<Symbol>] the domain attributes which can serve as a query parameter
|
59
|
+
# @see Property#searchable?
|
60
|
+
def searchable_attributes
|
61
|
+
@srchbl_flt ||= attribute_filter { |prop| prop.searchable? }
|
62
|
+
end
|
63
|
+
|
64
|
+
# @return [<Symbol>] the create/update cascaded domain attributes
|
65
|
+
# @see Property#cascaded?
|
66
|
+
def cascaded_attributes
|
67
|
+
@cscd_flt ||= domain_attributes.compose { |prop| prop.cascaded? }
|
68
|
+
end
|
69
|
+
|
70
|
+
# @return [<Symbol>] the {#cascaded_attributes} which are saved with a proxy
|
71
|
+
# using the dependent saver_proxy method
|
72
|
+
def proxied_savable_template_attributes
|
73
|
+
@px_cscd_flt ||= savable_template_attributes.compose { |prop| prop.proxied_save? }
|
74
|
+
end
|
75
|
+
|
76
|
+
# @return [<Symbol>] the {#cascaded_attributes} which do not have a
|
77
|
+
# #{Property#proxied_save?}
|
78
|
+
def unproxied_savable_template_attributes
|
79
|
+
@unpx_sv_tmpl_flt ||= savable_template_attributes.compose { |prop| not prop.proxied_save? }
|
80
|
+
end
|
81
|
+
|
82
|
+
# @return [<Symbol>] the {#domain_attributes} to {Property#include_in_save_template?}
|
83
|
+
def savable_template_attributes
|
84
|
+
@sv_tmpl_flt ||= domain_attributes.compose { |prop| prop.include_in_save_template? }
|
85
|
+
end
|
86
|
+
|
87
|
+
# Returns the physical or auto-generated logical dependent attributes that can
|
88
|
+
# be copied from a save result to the given save argument object.
|
89
|
+
#
|
90
|
+
# @return [<Symbol>] the attributes that can be copied from a save result to a
|
91
|
+
# save argument object
|
92
|
+
# @see Property#autogenerated?
|
93
|
+
def copyable_saved_attributes
|
94
|
+
@cp_sv_flt ||= dependent_attributes.compose { |prop| prop.autogenerated? or not prop.logical? }
|
95
|
+
end
|
96
|
+
|
97
|
+
# @return [<Symbol>] the attributes which are {Property#creatable?}
|
98
|
+
def creatable_attributes
|
99
|
+
@cr_flt ||= attribute_filter { |prop| prop.creatable? }
|
100
|
+
end
|
101
|
+
|
102
|
+
# @return [<Symbol>] the attributes which are {Property#updatable?}
|
103
|
+
def updatable_attributes
|
104
|
+
@upd_flt ||= attribute_filter { |prop| prop.updatable? }
|
105
|
+
end
|
106
|
+
|
107
|
+
def fetched_dependent_attributes
|
108
|
+
@fch_dep_flt ||= (fetched_domain_attributes & dependent_attributes).to_a
|
109
|
+
end
|
110
|
+
|
111
|
+
# @return [<Symbol>] the saved dependent attributes
|
112
|
+
def saved_dependent_attributes
|
113
|
+
@sv_dep_flt ||= attribute_filter { |prop| prop.dependent? and prop.saved? }
|
114
|
+
end
|
115
|
+
|
116
|
+
# @return [<Symbol>] the saved {Property#independent?} attributes
|
117
|
+
# @see Property#saved?
|
118
|
+
def saved_independent_attributes
|
119
|
+
@sv_ind_flt ||= attribute_filter { |prop| prop.independent? and prop.saved? }
|
120
|
+
end
|
121
|
+
|
122
|
+
# @return [<Symbol>] the domain {Property#sync?} attributes
|
123
|
+
def sync_domain_attributes
|
124
|
+
@sv_sync_dom_flt ||= domain_attributes.compose { |prop| prop.sync? }
|
125
|
+
end
|
126
|
+
|
127
|
+
# @return [<Symbol>] the non-domain {Property#saved?} attributes
|
128
|
+
def saved_nondomain_attributes
|
129
|
+
@sv_ndom_flt ||= nondomain_attributes.compose { |prop| prop.saved? }
|
130
|
+
end
|
131
|
+
|
132
|
+
# @return [<Symbol>] the {Property#volatile?} {#nondomain_attributes}
|
133
|
+
def volatile_nondomain_attributes
|
134
|
+
@vl_ndom_flt ||= nondomain_attributes.compose { |prop| prop.volatile? }
|
135
|
+
end
|
136
|
+
|
137
|
+
# @return [<Symbol>] the domain {#creatable_attributes}
|
138
|
+
def creatable_domain_attributes
|
139
|
+
@cr_dom_flt ||= domain_attributes.compose { |prop| prop.creatable? }
|
140
|
+
end
|
141
|
+
|
142
|
+
# @return [<Symbol>] the domain {#updatable_attributes}
|
143
|
+
def updatable_domain_attributes
|
144
|
+
@upd_dom_flt ||= domain_attributes.compose { |prop| prop.updatable? }
|
145
|
+
end
|
146
|
+
|
147
|
+
# @return [<Symbol>] the attributes which are populated from the database
|
148
|
+
# @see Property#fetched?
|
149
|
+
def fetched_attributes
|
150
|
+
@fch_flt ||= attribute_filter { |prop| prop.fetched? }
|
151
|
+
end
|
152
|
+
|
153
|
+
# Returns the domain attributes which are populated in a query on the given fetched instance of
|
154
|
+
# this metadata's subject class. The domain attribute is fetched if it satisfies the following
|
155
|
+
# conditions:
|
156
|
+
# * the attribute is a dependent attribute or of abstract domain type
|
157
|
+
# * the attribute is not specified as unfetched in the configuration
|
158
|
+
#
|
159
|
+
# @return [<Symbol>] the attributes which are {Property#fetched?}
|
160
|
+
def fetched_domain_attributes
|
161
|
+
@fch_dom_flt ||= domain_attributes.compose { |prop| prop.fetched? }
|
162
|
+
end
|
163
|
+
|
164
|
+
#@return [<Symbol>] the #domain_attributes which are not #fetched_domain_attributes
|
165
|
+
def unfetched_attributes
|
166
|
+
@unftchd_flt ||= domain_attributes.compose { |prop| not prop.fetched? }
|
167
|
+
end
|
168
|
+
|
169
|
+
alias :toxic_attributes :unfetched_attributes
|
170
|
+
|
171
|
+
# @return [<Symbol>] the Java attribute non-abstract {#unfetched_attributes}
|
172
|
+
def loadable_attributes
|
173
|
+
@ld_flt ||= unfetched_attributes.compose { |prop| prop.java_property? and not prop.type.abstract? }
|
174
|
+
end
|
175
|
+
|
176
|
+
private
|
177
|
+
|
178
|
+
def create_nonjava_property(attribute, type, *flags)
|
179
|
+
Property.new(attribute, self, type, *flags)
|
180
|
+
end
|
181
|
+
|
182
|
+
def create_java_property(pd)
|
183
|
+
JavaProperty.new(pd, self)
|
184
|
+
end
|
185
|
+
|
186
|
+
# Augments +Jinx::Propertied#default_mandatory_local_attributes to exclude auto-generated properties.
|
187
|
+
def default_mandatory_local_attributes
|
188
|
+
super.delete_if { |ma| property(ma).autogenerated? }
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'jinx/metadata/property'
|
2
|
+
require 'caruby/metadata/property_characteristics'
|
3
|
+
|
4
|
+
# Mix persistence into +Jinx::Property+.
|
5
|
+
module CaRuby
|
6
|
+
class Property < Jinx::Property
|
7
|
+
include CaRuby::PropertyCharacteristics
|
8
|
+
|
9
|
+
def initialize(attribute, declarer, type=nil, *flags)
|
10
|
+
super
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
# @param [Symbol] the flag to set
|
16
|
+
# @return [Boolean] whether the flag is supported
|
17
|
+
def flag_supported?(flag)
|
18
|
+
super or CaRuby::PropertyCharacteristics::SUPPORTED_FLAGS.include?(flag)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
@@ -0,0 +1,201 @@
|
|
1
|
+
require 'jinx/metadata/property_characteristics'
|
2
|
+
|
3
|
+
module CaRuby
|
4
|
+
# The CaRuby::PropertyCharacteristics mixin captures persistence metadata.
|
5
|
+
module PropertyCharacteristics
|
6
|
+
# The supported persistence-specific property qualifier flags. This set augments the
|
7
|
+
# +Jinx::Property::SUPPORTED_FLAGS+ set for persistence adapters. See the complementary
|
8
|
+
# methods for an explanation of the flag option, e.g. {#autogenerated?} for the
|
9
|
+
# +:autogenerated+ flag.
|
10
|
+
SUPPORTED_FLAGS = [
|
11
|
+
:autogenerated, :logical, :cascaded, :no_cascade_update_to_create, :saved, :unsaved, :fetched,
|
12
|
+
:unfetched, :include_in_save_template, :fetch_saved, :create_only, :update_only, :nosync,
|
13
|
+
:volatile].to_set
|
14
|
+
|
15
|
+
# Returns whether the subject attribute is fetched, determined as follows:
|
16
|
+
# * An attribute marked with the :fetched flag is fetched.
|
17
|
+
# * An attribute marked with the :unfetched flag is not fetched.
|
18
|
+
# Otherwise, a non-domain attribute is fetched, and a domain attribute is
|
19
|
+
# fetched if one of the following conditions hold:
|
20
|
+
# * A dependent domain attribute is fetched if it is not logical.
|
21
|
+
# * An owner domain attribute is fetched by default.
|
22
|
+
# * An independent domain attribute is fetched if it is abstract and not derived.
|
23
|
+
#
|
24
|
+
# @return [Boolean] whether the attribute is fetched
|
25
|
+
def fetched?
|
26
|
+
return true if @flags.include?(:fetched)
|
27
|
+
return false if @flags.include?(:unfetched)
|
28
|
+
nondomain? or dependent? ? fetched_dependent? : fetched_independent?
|
29
|
+
end
|
30
|
+
|
31
|
+
# Returns whether the subject attribute is not saved.
|
32
|
+
#
|
33
|
+
# @return [Boolean] whether the attribute is unsaved
|
34
|
+
def unsaved?
|
35
|
+
@flags.include?(:unsaved)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Returns whether the subject attribute is a dependent whose value is automatically generated
|
39
|
+
# with place-holder domain objects when the parent is created. An attribute is auto-generated
|
40
|
+
# if the +:autogenerated+ flag is set.
|
41
|
+
#
|
42
|
+
# @return [Boolean] whether the attribute is auto-generated
|
43
|
+
def autogenerated?
|
44
|
+
@flags.include?(:autogenerated)
|
45
|
+
end
|
46
|
+
|
47
|
+
# Returns whether this attribute must be fetched when a declarer instance is saved.
|
48
|
+
# An attribute is a saved fetch attribute if any of the following conditions hold:
|
49
|
+
# * it is {#autogenerated?}
|
50
|
+
# * it is {#cascaded?} and marked with the +:unfetched+ flag
|
51
|
+
# * it is marked with the +:fetch_saved+ flag
|
52
|
+
#
|
53
|
+
# @return [Boolean] whether the subject attribute must be refetched in order to reflect
|
54
|
+
# the database content
|
55
|
+
def fetch_saved?
|
56
|
+
@flags.include?(:fetch_saved) or autogenerated? or (cascaded? and @flags.include?(:unfetched))
|
57
|
+
end
|
58
|
+
|
59
|
+
# Returns whether the subject attribute is either:
|
60
|
+
# 1. an owner attribute which does not automatically cascade application service creation
|
61
|
+
# or update to the referenced dependent, or
|
62
|
+
# 2. the dependent attribute whose inverse is a logical owner attribute
|
63
|
+
#
|
64
|
+
# @return [Boolean] whether the attribute is an uncascaded dependent
|
65
|
+
def logical?
|
66
|
+
@flags.include?(:logical) or (owner? and inverse_property and inverse_property.logical?)
|
67
|
+
end
|
68
|
+
|
69
|
+
# A Java attribute is creatable if all of the following conditions hold:
|
70
|
+
# * the attribute is {#saved?}
|
71
|
+
# * the attribute :update_only flag is not set
|
72
|
+
#
|
73
|
+
# @return [Boolean] whether this attribute is saved in a create operation
|
74
|
+
def creatable?
|
75
|
+
saved? and not @flags.include?(:update_only)
|
76
|
+
end
|
77
|
+
|
78
|
+
# A Java attribute is updatable if all of the following conditions hold:
|
79
|
+
# * the attribute is {#saved?}
|
80
|
+
# * the attribute :create_only flag is not set
|
81
|
+
#
|
82
|
+
# @return [Boolean] whether this attribute is saved in a update operation
|
83
|
+
def updatable?
|
84
|
+
saved? and not @flags.include?(:create_only)
|
85
|
+
end
|
86
|
+
|
87
|
+
# Indicates whether this reference propery is saved when its owner is saved.
|
88
|
+
#
|
89
|
+
# @return [Boolean] whether the attribute is a physical dependent or the +:cascaded+ flag is set
|
90
|
+
def cascaded?
|
91
|
+
(dependent? and not logical?) or @flags.include?(:cascaded)
|
92
|
+
end
|
93
|
+
|
94
|
+
# Determines whether this propery is included in a save operation argument.
|
95
|
+
#
|
96
|
+
# @return [Boolean] whether this attribute is {#cascaded?} or marked with the
|
97
|
+
# +:include_in_save_template+ flag
|
98
|
+
def include_in_save_template?
|
99
|
+
cascaded? or @flags.include?(:include_in_save_template)
|
100
|
+
end
|
101
|
+
|
102
|
+
# Returns whether this attribute is #{#cascaded?} and cascades a parent update to a child
|
103
|
+
# create. This corresponds to the Hibernate +save-update+ cascade style but not the Hibernate
|
104
|
+
# +all+ cascade style.
|
105
|
+
#
|
106
|
+
# This method returns true if this attribute is cascaded and the +:no_cascade_update_to_create+
|
107
|
+
# flag is not set. Set this flag if the Hibernate mapping specifies the +all+ cascade style.
|
108
|
+
# Failure to set this flag will result in the caTissue Hibernate error:
|
109
|
+
# Exception: gov.nih.nci.system.applicationservice.ApplicationException:
|
110
|
+
# The given object has a null identifier:
|
111
|
+
# followed by the attribute type name.
|
112
|
+
#
|
113
|
+
# @return [Boolean] whether the attribute cascades to crate when the owner is updated
|
114
|
+
def cascade_update_to_create?
|
115
|
+
cascaded? and not @flags.include?(:no_cascade_update_to_create)
|
116
|
+
end
|
117
|
+
|
118
|
+
# A Java property attribute is saved if none of the following conditions hold:
|
119
|
+
# * the attribute :unsaved flag is set
|
120
|
+
# * the attribute is {#proxied_save?}
|
121
|
+
# and any of the following conditions hold:
|
122
|
+
# * the attibute is {#nondomain?}
|
123
|
+
# * the attribute is cascaded
|
124
|
+
# * the attribute value is not a collection
|
125
|
+
# * the attribute does not have an inverse
|
126
|
+
# * the attribute :saved flag is set
|
127
|
+
#
|
128
|
+
# @return [Boolean] whether this attribute is saved in a create or update operation
|
129
|
+
def saved?
|
130
|
+
@flags.include?(:saved) or
|
131
|
+
(java_property? and not @flags.include?(:unsaved) and not proxied_save? and
|
132
|
+
(nondomain? or cascaded? or not collection? or inverse.nil? or unidirectional_java_dependent?))
|
133
|
+
end
|
134
|
+
|
135
|
+
# @return [Boolean] whether this attribute is #{#saved?} and does not have the
|
136
|
+
# +:nosync+ flag set
|
137
|
+
def sync?
|
138
|
+
saved? and not @flags.include?(:nosync)
|
139
|
+
end
|
140
|
+
|
141
|
+
# @return [Boolean] whether this attribute is not {#saved?}
|
142
|
+
def unsaved?
|
143
|
+
not saved?
|
144
|
+
end
|
145
|
+
|
146
|
+
# @return [Boolean] whether the attribute return {#type} is a Resource class which
|
147
|
+
# implements the saver_proxy method
|
148
|
+
def proxied_save?
|
149
|
+
domain? and type.method_defined?(:saver_proxy)
|
150
|
+
end
|
151
|
+
|
152
|
+
# Returns whether this attribute's referents must exist before an instance of the
|
153
|
+
# declarer class can be created. An attribute is a savable prerequisite if it is
|
154
|
+
# either:
|
155
|
+
# * a {#cascaded?} dependent which does not #{#cascade_update_to_create?}, or
|
156
|
+
# * a {#saved?} {#independent?} 1:M or M:N association.
|
157
|
+
#
|
158
|
+
# @return [Boolean] whether this attribute is a create prerequisite
|
159
|
+
def savable_prerequisite?
|
160
|
+
return true if cascaded? and @flags.include?(:no_cascade_update_to_create)
|
161
|
+
return false unless independent? and saved?
|
162
|
+
return true unless collection?
|
163
|
+
inv_prop = inverse_property
|
164
|
+
inv_prop.nil? or inv_prop.collection?
|
165
|
+
end
|
166
|
+
|
167
|
+
# @return [Boolean] whether the subject attribute is not saved
|
168
|
+
def transient?
|
169
|
+
not saved?
|
170
|
+
end
|
171
|
+
|
172
|
+
# @return [Boolean] whether this is a non-collection Java attribute
|
173
|
+
def searchable?
|
174
|
+
java_property? and not collection?
|
175
|
+
end
|
176
|
+
|
177
|
+
# @return [Boolean] whether this attribute is set by the server
|
178
|
+
def volatile?
|
179
|
+
to_sym == :identifier or @flags.include?(:volatile)
|
180
|
+
end
|
181
|
+
|
182
|
+
private
|
183
|
+
|
184
|
+
# @param [Symbol] the flag to set
|
185
|
+
# @return [Boolean] whether the flag is supported
|
186
|
+
def flag_supported?(flag)
|
187
|
+
super or SUPPORTED_FLAGS.include?(flag)
|
188
|
+
end
|
189
|
+
|
190
|
+
# @return [Boolean] whether this dependent attribute is fetched. Only physical dependents are fetched by default.
|
191
|
+
def fetched_dependent?
|
192
|
+
not (logical? or @flags.include?(:unfetched))
|
193
|
+
end
|
194
|
+
|
195
|
+
# @return [Boolean] whether this independent attribute is fetched. Only abstract, non-derived independent
|
196
|
+
# references are fetched by default.
|
197
|
+
def fetched_independent?
|
198
|
+
type.abstract? and not (derived? or @flags.include?(:unfetched))
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|