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.
Files changed (126) hide show
  1. data/Gemfile +9 -0
  2. data/History.md +5 -1
  3. data/lib/caruby.rb +3 -5
  4. data/lib/caruby/caruby-src.tar.gz +0 -0
  5. data/lib/caruby/database.rb +53 -69
  6. data/lib/caruby/database/application_service.rb +25 -0
  7. data/lib/caruby/database/cache.rb +60 -0
  8. data/lib/caruby/database/fetched_matcher.rb +52 -38
  9. data/lib/caruby/database/lazy_loader.rb +4 -4
  10. data/lib/caruby/database/operation.rb +34 -0
  11. data/lib/caruby/database/persistable.rb +171 -86
  12. data/lib/caruby/database/persistence_service.rb +32 -34
  13. data/lib/caruby/database/persistifier.rb +100 -43
  14. data/lib/caruby/database/reader.rb +107 -85
  15. data/lib/caruby/database/reader_template_builder.rb +60 -0
  16. data/lib/caruby/database/saved_matcher.rb +3 -3
  17. data/lib/caruby/database/sql_executor.rb +88 -17
  18. data/lib/caruby/database/writer.rb +213 -177
  19. data/lib/caruby/database/writer_template_builder.rb +334 -0
  20. data/lib/caruby/{util → helpers}/controlled_value.rb +0 -0
  21. data/lib/caruby/{util → helpers}/coordinate.rb +4 -4
  22. data/lib/caruby/{util → helpers}/person.rb +3 -3
  23. data/lib/caruby/{util → helpers}/properties.rb +7 -9
  24. data/lib/caruby/{util → helpers}/roman.rb +2 -2
  25. data/lib/caruby/{util → helpers}/version.rb +1 -1
  26. data/lib/caruby/json/deserializer.rb +2 -2
  27. data/lib/caruby/json/serializer.rb +49 -7
  28. data/lib/caruby/metadata.rb +30 -0
  29. data/lib/caruby/metadata/java_property.rb +21 -0
  30. data/lib/caruby/metadata/propertied.rb +191 -0
  31. data/lib/caruby/metadata/property.rb +22 -0
  32. data/lib/caruby/metadata/property_characteristics.rb +201 -0
  33. data/lib/caruby/migration/migratable.rb +11 -182
  34. data/lib/caruby/rdbi/driver/jdbc.rb +446 -0
  35. data/lib/caruby/resource.rb +20 -823
  36. data/lib/caruby/version.rb +1 -1
  37. data/test/lib/caruby/database/cache_test.rb +54 -0
  38. data/test/lib/caruby/{util → helpers}/controlled_value_test.rb +3 -5
  39. data/test/lib/caruby/{util → helpers}/person_test.rb +4 -6
  40. data/test/lib/caruby/helpers/properties_test.rb +34 -0
  41. data/test/lib/caruby/{util → helpers}/roman_test.rb +2 -3
  42. data/test/lib/caruby/{util → helpers}/version_test.rb +2 -3
  43. data/test/lib/helper.rb +7 -0
  44. metadata +161 -214
  45. data/lib/caruby/cli/application.rb +0 -36
  46. data/lib/caruby/cli/command.rb +0 -202
  47. data/lib/caruby/csv/csv_mapper.rb +0 -159
  48. data/lib/caruby/csv/csvio.rb +0 -203
  49. data/lib/caruby/database/search_template_builder.rb +0 -56
  50. data/lib/caruby/database/store_template_builder.rb +0 -278
  51. data/lib/caruby/domain.rb +0 -193
  52. data/lib/caruby/domain/attribute.rb +0 -584
  53. data/lib/caruby/domain/attributes.rb +0 -628
  54. data/lib/caruby/domain/dependency.rb +0 -225
  55. data/lib/caruby/domain/id_alias.rb +0 -22
  56. data/lib/caruby/domain/importer.rb +0 -183
  57. data/lib/caruby/domain/introspection.rb +0 -176
  58. data/lib/caruby/domain/inverse.rb +0 -172
  59. data/lib/caruby/domain/inversible.rb +0 -90
  60. data/lib/caruby/domain/java_attribute.rb +0 -173
  61. data/lib/caruby/domain/merge.rb +0 -185
  62. data/lib/caruby/domain/metadata.rb +0 -142
  63. data/lib/caruby/domain/mixin.rb +0 -35
  64. data/lib/caruby/domain/properties.rb +0 -95
  65. data/lib/caruby/domain/reference_visitor.rb +0 -428
  66. data/lib/caruby/domain/uniquify.rb +0 -50
  67. data/lib/caruby/import/java.rb +0 -387
  68. data/lib/caruby/migration/migrator.rb +0 -918
  69. data/lib/caruby/migration/resource_module.rb +0 -9
  70. data/lib/caruby/migration/uniquify.rb +0 -17
  71. data/lib/caruby/util/attribute_path.rb +0 -44
  72. data/lib/caruby/util/cache.rb +0 -56
  73. data/lib/caruby/util/class.rb +0 -149
  74. data/lib/caruby/util/collection.rb +0 -1152
  75. data/lib/caruby/util/domain_extent.rb +0 -46
  76. data/lib/caruby/util/file_separator.rb +0 -65
  77. data/lib/caruby/util/inflector.rb +0 -27
  78. data/lib/caruby/util/log.rb +0 -95
  79. data/lib/caruby/util/math.rb +0 -12
  80. data/lib/caruby/util/merge.rb +0 -59
  81. data/lib/caruby/util/module.rb +0 -18
  82. data/lib/caruby/util/options.rb +0 -97
  83. data/lib/caruby/util/partial_order.rb +0 -35
  84. data/lib/caruby/util/pretty_print.rb +0 -204
  85. data/lib/caruby/util/stopwatch.rb +0 -74
  86. data/lib/caruby/util/topological_sync_enumerator.rb +0 -62
  87. data/lib/caruby/util/transitive_closure.rb +0 -55
  88. data/lib/caruby/util/tree.rb +0 -48
  89. data/lib/caruby/util/trie.rb +0 -37
  90. data/lib/caruby/util/uniquifier.rb +0 -30
  91. data/lib/caruby/util/validation.rb +0 -20
  92. data/lib/caruby/util/visitor.rb +0 -365
  93. data/lib/caruby/util/weak_hash.rb +0 -36
  94. data/test/lib/caruby/csv/csv_mapper_test.rb +0 -40
  95. data/test/lib/caruby/csv/csvio_test.rb +0 -69
  96. data/test/lib/caruby/database/persistable_test.rb +0 -92
  97. data/test/lib/caruby/domain/domain_test.rb +0 -112
  98. data/test/lib/caruby/domain/inversible_test.rb +0 -99
  99. data/test/lib/caruby/domain/reference_visitor_test.rb +0 -130
  100. data/test/lib/caruby/import/java_test.rb +0 -80
  101. data/test/lib/caruby/import/mixed_case_test.rb +0 -14
  102. data/test/lib/caruby/migration/test_case.rb +0 -102
  103. data/test/lib/caruby/test_case.rb +0 -230
  104. data/test/lib/caruby/util/cache_test.rb +0 -23
  105. data/test/lib/caruby/util/class_test.rb +0 -61
  106. data/test/lib/caruby/util/collection_test.rb +0 -398
  107. data/test/lib/caruby/util/command_test.rb +0 -55
  108. data/test/lib/caruby/util/domain_extent_test.rb +0 -60
  109. data/test/lib/caruby/util/file_separator_test.rb +0 -30
  110. data/test/lib/caruby/util/inflector_test.rb +0 -12
  111. data/test/lib/caruby/util/lazy_hash_test.rb +0 -34
  112. data/test/lib/caruby/util/merge_test.rb +0 -83
  113. data/test/lib/caruby/util/module_test.rb +0 -25
  114. data/test/lib/caruby/util/options_test.rb +0 -59
  115. data/test/lib/caruby/util/partial_order_test.rb +0 -42
  116. data/test/lib/caruby/util/pretty_print_test.rb +0 -85
  117. data/test/lib/caruby/util/properties_test.rb +0 -50
  118. data/test/lib/caruby/util/stopwatch_test.rb +0 -18
  119. data/test/lib/caruby/util/topological_sync_enumerator_test.rb +0 -69
  120. data/test/lib/caruby/util/transitive_closure_test.rb +0 -67
  121. data/test/lib/caruby/util/tree_test.rb +0 -23
  122. data/test/lib/caruby/util/trie_test.rb +0 -14
  123. data/test/lib/caruby/util/visitor_test.rb +0 -278
  124. data/test/lib/caruby/util/weak_hash_test.rb +0 -45
  125. data/test/lib/examples/clinical_trials/migration/migration_test.rb +0 -58
  126. 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
- # The JSON class must be scoped by the domain module, not the Java package, in order
10
- # to recognize the Resource JSON hooks.
11
- # The data is the attribute => value hash.
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