caruby-tissue 1.4.2 → 1.5.1
Sign up to get free protection for your applications and to get access to all the features.
- data/History.md +53 -0
- data/bin/crtdump +1 -6
- data/bin/crtexample +1 -6
- data/bin/crtmigrate +1 -6
- data/bin/crtsmoke +1 -6
- data/conf/migration/filter_fields.yaml +1 -1
- data/conf/migration/general_fields.yaml +1 -1
- data/conf/migration/simple_fields.yaml +1 -1
- data/conf/migration/small_fields.yaml +1 -1
- data/examples/galena/README.md +34 -25
- data/examples/galena/bin/seed +2 -7
- data/examples/galena/conf/migration/annotation_fields.yaml +1 -1
- data/examples/galena/conf/migration/filter_fields.yaml +1 -1
- data/examples/galena/conf/migration/frozen_fields.yaml +2 -2
- data/examples/galena/conf/migration/general_fields.yaml +1 -1
- data/examples/galena/conf/migration/registration_fields.yaml +1 -0
- data/examples/galena/conf/migration/simple_fields.yaml +1 -1
- data/examples/galena/data/frozen.csv +1 -1
- data/examples/galena/data/general.csv +1 -1
- data/examples/galena/data/registration.csv +1 -1
- data/examples/galena/lib/galena/tissue/migration/frozen_shims.rb +8 -4
- data/examples/galena/lib/galena/tissue/seed/defaults.rb +16 -9
- data/examples/pcbin/README.md +8 -8
- data/examples/pcbin/conf/biopsy_fields.yaml +1 -1
- data/examples/pcbin/conf/patient_fields.yaml +1 -1
- data/examples/pcbin/conf/surgery_fields.yaml +1 -1
- data/examples/pcbin/conf/t_stage_fields.yaml +1 -1
- data/examples/pcbin/conf/therapy_fields.yaml +1 -1
- data/lib/catissue.rb +1 -1
- data/lib/catissue/annotation/annotatable.rb +12 -22
- data/lib/catissue/annotation/annotatable_class.rb +87 -114
- data/lib/catissue/annotation/annotation.rb +9 -44
- data/lib/catissue/annotation/annotation_class.rb +238 -145
- data/lib/catissue/annotation/annotation_module.rb +47 -59
- data/lib/catissue/annotation/de_integration.rb +12 -2
- data/lib/catissue/annotation/proxy.rb +11 -17
- data/lib/catissue/annotation/proxy_1_1.rb +47 -0
- data/lib/catissue/annotation/proxy_class.rb +55 -37
- data/lib/catissue/annotation/record_entry_proxy.rb +20 -0
- data/lib/catissue/database.rb +164 -112
- data/lib/catissue/database/annotation/annotation_service.rb +5 -5
- data/lib/catissue/database/annotation/annotator.rb +2 -2
- data/lib/catissue/database/annotation/entity_facade.rb +24 -21
- data/lib/catissue/database/annotation/id_generator.rb +26 -26
- data/lib/catissue/database/annotation/integration_service.rb +8 -8
- data/lib/catissue/database/annotation/record_entry_integrator.rb +24 -6
- data/lib/catissue/database/annotation/reference_writer.rb +33 -6
- data/lib/catissue/domain.rb +26 -0
- data/lib/catissue/domain/abstract_position.rb +1 -1
- data/lib/catissue/domain/abstract_specimen.rb +16 -16
- data/lib/catissue/domain/check_in_check_out_event_parameter.rb +1 -1
- data/lib/catissue/domain/collection_event_parameters.rb +1 -1
- data/lib/catissue/domain/collection_protocol.rb +9 -13
- data/lib/catissue/domain/collection_protocol_event.rb +4 -4
- data/lib/catissue/domain/collection_protocol_registration.rb +4 -4
- data/lib/catissue/domain/container.rb +12 -21
- data/lib/catissue/domain/container_type.rb +65 -64
- data/lib/catissue/domain/disposal_event_parameters.rb +1 -1
- data/lib/catissue/domain/hash_code.rb +3 -6
- data/lib/catissue/domain/new_specimen_array_order_item.rb +4 -4
- data/lib/catissue/domain/order_details.rb +3 -3
- data/lib/catissue/domain/participant.rb +28 -20
- data/lib/catissue/domain/participant/clinical/chemotherapy.rb +21 -0
- data/lib/catissue/domain/participant/clinical/duration.rb +11 -0
- data/lib/catissue/domain/participant/clinical/radiation_therapy.rb +21 -0
- data/lib/catissue/domain/participant_medical_identifier.rb +2 -2
- data/lib/catissue/domain/site.rb +6 -6
- data/lib/catissue/domain/specimen.rb +41 -34
- data/lib/catissue/domain/specimen/pathology/prostate_specimen_gleason_score.rb +18 -0
- data/lib/catissue/domain/specimen/pathology/prostate_specimen_pathology_annotation.rb +13 -8
- data/lib/catissue/domain/specimen/pathology/specimen_additional_finding.rb +21 -0
- data/lib/catissue/domain/specimen/pathology/specimen_base_solid_tissue_pathology_annotation.rb +30 -7
- data/lib/catissue/domain/specimen/pathology/specimen_details.rb +18 -0
- data/lib/catissue/domain/specimen/pathology/specimen_histologic_grade.rb +18 -0
- data/lib/catissue/domain/specimen/pathology/specimen_histologic_type.rb +22 -6
- data/lib/catissue/domain/specimen/pathology/specimen_histologic_variant_type.rb +18 -0
- data/lib/catissue/domain/specimen/pathology/specimen_invasion.rb +18 -0
- data/lib/catissue/domain/specimen_array.rb +8 -8
- data/lib/catissue/domain/specimen_array_content.rb +4 -4
- data/lib/catissue/domain/specimen_collection_group.rb +43 -41
- data/lib/catissue/domain/specimen_collection_group/pathology/base_pathology_annotation.rb +16 -0
- data/lib/catissue/domain/specimen_collection_group/pathology/base_solid_tissue_pathology_annotation.rb +16 -0
- data/lib/catissue/domain/specimen_position.rb +3 -3
- data/lib/catissue/domain/specimen_protocol.rb +7 -7
- data/lib/catissue/domain/specimen_requirement.rb +9 -9
- data/lib/catissue/domain/storage_container.rb +13 -13
- data/lib/catissue/domain/storage_type.rb +12 -7
- data/lib/catissue/domain/transfer_event_parameters.rb +2 -2
- data/lib/catissue/domain/user.rb +15 -15
- data/lib/catissue/extract/extractor.rb +1 -1
- data/lib/catissue/resource.rb +8 -36
- data/lib/catissue/util/location.rb +0 -13
- data/lib/catissue/util/person.rb +2 -1
- data/lib/catissue/util/position.rb +1 -11
- data/lib/catissue/util/uniquify.rb +1 -1
- data/lib/catissue/version.rb +1 -1
- data/lib/catissue/wustl/logger.rb +17 -16
- data/test/fixtures/lib/catissue/defaults_test_fixture.rb +6 -4
- data/test/lib/catissue/domain/collection_protocol_test.rb +0 -1
- data/test/lib/catissue/domain/participant_test.rb +74 -19
- data/test/lib/catissue/domain/specimen_collection_group_test.rb +14 -10
- data/test/lib/catissue/domain/specimen_test.rb +36 -60
- data/test/lib/catissue/domain/storage_type_test.rb +5 -5
- data/test/lib/catissue/domain/transfer_event_parameters_test.rb +14 -12
- data/test/lib/catissue/migration/test_case.rb +0 -1
- data/test/lib/catissue/test_case.rb +12 -12
- data/test/lib/examples/galena/tissue/domain/examples_test.rb +1 -1
- data/test/lib/examples/galena/tissue/migration/annotation_test.rb +9 -7
- data/test/lib/examples/galena/tissue/migration/frozen_test.rb +1 -1
- data/test/lib/examples/galena/tissue/migration/general_test.rb +1 -1
- data/test/lib/examples/galena/tissue/migration/registration_test.rb +3 -9
- data/test/lib/examples/galena/tissue/migration/seedify.rb +3 -3
- data/test/lib/examples/pcbin/migration_test.rb +37 -16
- metadata +24 -10
- data/History.txt +0 -50
@@ -1,4 +1,4 @@
|
|
1
|
-
Protocol: CollectionProtocol.
|
1
|
+
Protocol: CollectionProtocol.title
|
2
2
|
Patient: CollectionProtocolRegistration.protocol_participant_identifier
|
3
3
|
Specimen Type: TissueSpecimen.specimen_type
|
4
4
|
Year of Diagnosis: Participant::Clinical::NewDiagnosisHealthAnnotation.date_of_examination
|
@@ -1,4 +1,4 @@
|
|
1
|
-
Protocol: CollectionProtocol.
|
1
|
+
Protocol: CollectionProtocol.title
|
2
2
|
Patient: CollectionProtocolRegistration.protocol_participant_identifier
|
3
3
|
Clinical Staging System: Participant::Clinical::LabAnnotation.other_lab_test_name
|
4
4
|
Clinical T Stage: Participant::Clinical::LabAnnotation.result
|
data/lib/catissue.rb
CHANGED
@@ -13,32 +13,22 @@ module CaTissue
|
|
13
13
|
self.class.annotation_attribute?(attr) ? send(mth, *args) : super
|
14
14
|
rescue AnnotationError
|
15
15
|
raise
|
16
|
-
rescue
|
17
|
-
raise
|
16
|
+
rescue NoMethodError
|
18
17
|
super
|
19
18
|
end
|
20
19
|
end
|
21
20
|
|
22
|
-
#
|
23
|
-
#
|
24
|
-
# @
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
end
|
34
|
-
|
35
|
-
# @param [Symbol] attribute the hook -> annotation attribute
|
36
|
-
# @return [Annotation] the hook -> proxy attribute
|
37
|
-
# @raise (see AnnotatableClass#annotation_proxy_attribute)
|
38
|
-
def annotation_proxy(attribute)
|
39
|
-
pxy_attr = self.class.annotation_proxy_attribute(attribute)
|
40
|
-
# the hook -> proxy attribute value
|
41
|
-
send(pxy_attr)
|
21
|
+
# @param [Symbol] attribute the hook => proxy attribute
|
22
|
+
# @param [Annotation] the annotation
|
23
|
+
# @return [Proxy] the hook proxy for the given annotation
|
24
|
+
def proxy_for(attribute, annotation)
|
25
|
+
@ann_pxy_hash ||= LazyHash.new do |ann|
|
26
|
+
pxy = self.class.attribute_metadata(attribute).type.new
|
27
|
+
pxy.hook = self
|
28
|
+
send(attribute) << pxy
|
29
|
+
pxy
|
30
|
+
end
|
31
|
+
@ann_pxy_hash[annotation]
|
42
32
|
end
|
43
33
|
end
|
44
34
|
end
|
@@ -1,6 +1,7 @@
|
|
1
|
-
require 'forwardable'
|
2
1
|
require 'caruby/util/inflector'
|
2
|
+
require 'caruby/domain/metadata'
|
3
3
|
require 'catissue/annotation/annotation_module'
|
4
|
+
require 'catissue/annotation/de_integration'
|
4
5
|
|
5
6
|
module CaTissue
|
6
7
|
# Mix-in for extending a caTissue domain class with annotations.
|
@@ -9,32 +10,47 @@ module CaTissue
|
|
9
10
|
# @return [Integer, nil] the the hook class designator that is used by caTissue to persist primary
|
10
11
|
# annotation objects, or nil if this is not a primary annotation class
|
11
12
|
attr_reader :entity_id
|
13
|
+
|
14
|
+
# @return [Class] the {DEIntegration} proxy class (nil for 1.1 caTissue)
|
15
|
+
def de_integration_proxy_class
|
16
|
+
@de_integration_proxy_class or (superclass.de_integration_proxy_class if superclass < Annotatable)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Adds {CaRuby::Domain::Metadata} and {AnnotatableClass} functionality to the given class.
|
20
|
+
#
|
21
|
+
# @param [Class] the domain class to extend
|
22
|
+
def self.extend_class(klass)
|
23
|
+
# Enable the class meta-data.
|
24
|
+
klass.extend(CaRuby::Domain::Metadata)
|
25
|
+
klass.extend(self)
|
26
|
+
end
|
12
27
|
|
13
28
|
def self.extended(klass)
|
14
29
|
super
|
15
|
-
# the annotation
|
30
|
+
# Initialize the class annotation hashes.
|
16
31
|
klass.class_eval do
|
17
|
-
|
32
|
+
# Enable the class meta-data.
|
33
|
+
# the annotation name => spec hash
|
18
34
|
@ann_spec_hash = {}
|
19
|
-
|
35
|
+
# the annotation module => proxy hash
|
36
|
+
@ann_mod_pxy_hash = {}
|
20
37
|
end
|
21
38
|
end
|
22
|
-
|
39
|
+
|
23
40
|
# @return [Integer, nil] this class's entity id, if it exists, otherwise the superclass effective entity id
|
24
41
|
# if the superclass is an annotation class
|
25
42
|
def effective_entity_id
|
26
43
|
@entity_id or parent_entity_id
|
27
44
|
end
|
28
|
-
|
45
|
+
|
29
46
|
# Loads the annotations defined for this class if necessary.
|
30
47
|
def ensure_annotations_loaded
|
31
48
|
# referencing the annotations loads them
|
32
49
|
annotation_modules
|
33
50
|
end
|
34
|
-
|
35
|
-
# If there is an existing annotation whose proxy accessor is the
|
36
|
-
#
|
37
|
-
# an annotation and return whether the import was successful.
|
51
|
+
|
52
|
+
# If there is an existing annotation whose proxy accessor is the given symbol, then return true.
|
53
|
+
# Otherwise, attempt to import an annotation and return whether the import was successful.
|
38
54
|
#
|
39
55
|
# @param [Symbol] symbol the potential accessor attribute
|
40
56
|
# @return [Boolean] whether there is a corresponding annotation
|
@@ -45,34 +61,19 @@ module CaTissue
|
|
45
61
|
annotation_defined?(symbol)
|
46
62
|
end
|
47
63
|
|
48
|
-
# Refines the {CaRuby::
|
64
|
+
# Refines the {CaRuby::Domain::Attributes#toxic_attributes} to exclude annotation attributes.
|
49
65
|
#
|
50
66
|
# @return [<Symbol>] the non-annotation unfetched attributes
|
51
67
|
def toxic_attributes
|
52
68
|
@anntbl_toxic_attrs ||= unfetched_attributes.compose { |attr_md| not attr_md.type < Annotation }
|
53
69
|
end
|
54
|
-
|
55
|
-
def annotation_proxy_attribute(attribute)
|
56
|
-
annotatable_class_hierarchy.detect_value { |klass| klass.local_annotation_proxy_attribute(attribute) }
|
57
|
-
end
|
58
70
|
|
59
|
-
# Makes a new attribute in this hook class for the given annotation proxy domain attribute.
|
60
|
-
# The hook annotation reference attribute delegates to the proxy. This method is intended for
|
61
|
-
# the exclusive use of {Annotation::ProxyClass}.
|
62
|
-
#
|
63
71
|
# @param [AnnotationModule] mod the annotation module
|
64
|
-
# @
|
65
|
-
def
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
# the type referenced by the annotation proxy
|
70
|
-
klass = ann_attr_md.type
|
71
|
-
# create annotation accessors which delegate to the proxy
|
72
|
-
def_delegators(pxy_attr, *ann_attr_md.accessors)
|
73
|
-
logger.debug { "Created #{qp}.#{attribute} which delegates to the annotation proxy #{pxy_attr}." }
|
74
|
-
# add the attribute
|
75
|
-
add_annotation_attribute(attribute, klass)
|
72
|
+
# @return [Symbol] the corresponding annotation proxy reference attribute
|
73
|
+
def annotation_proxy_attribute(mod)
|
74
|
+
@ann_mod_pxy_hash[mod] or
|
75
|
+
(superclass.annotation_proxy_attribute(mod) if superclass < Annotatable) or
|
76
|
+
raise AnnotationError.new("#{qp} #{mod} proxy attribute not found.")
|
76
77
|
end
|
77
78
|
|
78
79
|
# Loads the annotations, if necessary, and tries to get the constant again.
|
@@ -88,6 +89,14 @@ module CaTissue
|
|
88
89
|
const_get(symbol)
|
89
90
|
end
|
90
91
|
end
|
92
|
+
|
93
|
+
# Filters {CaRuby::Domain::Attributes#loadable_attributes} to exclude the {#annotation_attributes}
|
94
|
+
# since annotation lazy-loading is not supported.
|
95
|
+
#
|
96
|
+
# @return (see CaRuby::Domain::Attributes#loadable_attributes)
|
97
|
+
def loadable_attributes
|
98
|
+
@antbl_ld_attrs ||= super.compose { |attr_md| not attr_md.type < Annotation }
|
99
|
+
end
|
91
100
|
|
92
101
|
def printable_attributes
|
93
102
|
@prbl_attrs ||= super.union(annotation_attributes)
|
@@ -106,7 +115,7 @@ module CaTissue
|
|
106
115
|
end
|
107
116
|
|
108
117
|
def annotation_attributes
|
109
|
-
@ann_attrs ||= append_ancestor_enum(@
|
118
|
+
@ann_attrs ||= append_ancestor_enum(@ann_mod_pxy_hash.enum_values) do |sc|
|
110
119
|
sc.annotation_attributes if sc < Annotatable
|
111
120
|
end
|
112
121
|
end
|
@@ -118,21 +127,23 @@ module CaTissue
|
|
118
127
|
@ann_mods ||= load_annotations
|
119
128
|
end
|
120
129
|
|
121
|
-
# @param [Symbol] attribute the annotation attribute
|
122
|
-
# @return [Symbol] the annotation proxy attribute
|
123
|
-
# @raise [TypeError] if the given attribute is not an annotation attribute
|
124
|
-
def local_annotation_proxy_attribute(attribute)
|
125
|
-
unless annotation_attribute?(attribute) then
|
126
|
-
raise TypeError.new("#{qp} #{attribute} is not an annotation attribute")
|
127
|
-
end
|
128
|
-
# the annotation class
|
129
|
-
klass = attribute_metadata(attribute).type
|
130
|
-
mod = klass.domain_module
|
131
|
-
@ann_mod_pxy_hash[mod]
|
132
|
-
end
|
133
|
-
|
134
130
|
private
|
135
131
|
|
132
|
+
# @param [String] name the proxy record entry class name
|
133
|
+
def annotation_proxy_class_name=(name)
|
134
|
+
@de_integration_proxy_class = Annotation::DEIntegration.proxy(name)
|
135
|
+
if @de_integration_proxy_class then
|
136
|
+
# hide the internal caTissue proxy collection attribute
|
137
|
+
attr = detect_attribute_with_type(@de_integration_proxy_class)
|
138
|
+
if attr then
|
139
|
+
remove_attribute(attr)
|
140
|
+
logger.debug { "Hid the internal caTissue #{qp} annotation record-keeping attribute #{attr}." }
|
141
|
+
end
|
142
|
+
else
|
143
|
+
logger.debug { "Ignored the missing caTissue #{qp} proxy class name #{name}, presumably unsupported in this caTissue release." }
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
136
147
|
# Loads the annotation modules in the class hierarchy.
|
137
148
|
#
|
138
149
|
# @return [<AnnotationModule>] an Enumerable on the loaded annotation modules
|
@@ -175,16 +186,17 @@ module CaTissue
|
|
175
186
|
#
|
176
187
|
# @return [<AnnotationModule>] the loaded annotation modules
|
177
188
|
def load_local_annotations
|
178
|
-
# the annotation module => proxy hash
|
179
|
-
@ann_mod_pxy_hash = {}
|
180
189
|
# an annotated class has a hook entity id
|
181
|
-
unless @ann_spec_hash.empty? then
|
182
|
-
@entity_id = Annotation::EntityFacade.instance.hook_entity_id(self)
|
183
|
-
end
|
190
|
+
unless @ann_spec_hash.empty? then initialize_annotation_holder end
|
184
191
|
# build the annotations
|
185
192
|
@ann_spec_hash.map { |name, opts| import_annotation(name, opts) }
|
193
|
+
end
|
194
|
+
|
195
|
+
# Determines this annotated class's {#entity_id} and {#de_integration_proxy_class}.
|
196
|
+
def initialize_annotation_holder
|
197
|
+
@entity_id = Annotation::EntityFacade.instance.hook_entity_id(self)
|
186
198
|
end
|
187
|
-
|
199
|
+
|
188
200
|
# @param [Symbol] attribute the annotation accessor
|
189
201
|
# @return [Module] the annotation module which implements the attribute
|
190
202
|
def annotation_attribute_module(attribute)
|
@@ -199,20 +211,19 @@ module CaTissue
|
|
199
211
|
# @raise [AnnotationError] if there is no annotation proxy class
|
200
212
|
def import_annotation(name, opts)
|
201
213
|
logger.debug { "Importing #{qp} annotation #{name}..." }
|
202
|
-
#
|
203
|
-
class_eval("
|
204
|
-
|
205
|
-
#
|
206
|
-
AnnotationModule.extend_module(
|
207
|
-
#
|
208
|
-
create_proxy_attribute(
|
209
|
-
#
|
210
|
-
|
211
|
-
#
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
mod
|
214
|
+
# Make the annotation module scoped by this Annotatable class.
|
215
|
+
class_eval("class #{name}; end")
|
216
|
+
klass = const_get(name)
|
217
|
+
# Append the AnnotationModule methods.
|
218
|
+
AnnotationModule.extend_module(klass, self, opts)
|
219
|
+
# Make the proxy attribute.
|
220
|
+
attr = create_proxy_attribute(klass)
|
221
|
+
# The proxy is a logical dependent.
|
222
|
+
add_dependent_attribute(attr, :logical)
|
223
|
+
logger.debug { "Created #{qp} annotation proxy logical dependent reference attribute #{attr}." }
|
224
|
+
# Fill out the dependency hierarchy.
|
225
|
+
klass.proxy.build_annotation_dependency_hierarchy
|
226
|
+
klass
|
216
227
|
end
|
217
228
|
|
218
229
|
# Returns whether this class has an annotation whose proxy accessor is the
|
@@ -229,59 +240,21 @@ module CaTissue
|
|
229
240
|
# The attribute reader creates an {Annotation::Proxy} instance of the method
|
230
241
|
# receiver {Annotatable} instance on demand.
|
231
242
|
#
|
232
|
-
# @param [AnnotationModule]
|
243
|
+
# @param [AnnotationModule] klass the subject annotation
|
233
244
|
# @return [Symbol] the proxy attribute
|
234
|
-
def create_proxy_attribute(
|
245
|
+
def create_proxy_attribute(klass)
|
235
246
|
# the proxy class
|
236
|
-
pxy =
|
237
|
-
# the proxy attribute
|
238
|
-
attr =
|
239
|
-
#
|
240
|
-
attr_create_on_demand_accessor(attr) {
|
241
|
-
#
|
242
|
-
add_attribute(attr, pxy, :
|
243
|
-
#
|
244
|
-
pxy.set_hook(self, attr)
|
245
|
-
logger.debug { "Added #{qp} #{mod.qp} annotation proxy attribute #{attr}." }
|
247
|
+
pxy = klass.proxy
|
248
|
+
# the proxy attribute symbol
|
249
|
+
attr = klass.name.demodulize.underscore.to_sym
|
250
|
+
# Define the proxy attribute.
|
251
|
+
attr_create_on_demand_accessor(attr) { Set.new }
|
252
|
+
# Register the attribute.
|
253
|
+
add_attribute(attr, pxy, :collection, :saved)
|
254
|
+
logger.debug { "Added #{qp} #{klass.qp} annotation proxy attribute #{attr} of type #{pxy}." }
|
246
255
|
# the annotation module => proxy attribute association
|
247
|
-
@ann_mod_pxy_hash[
|
256
|
+
@ann_mod_pxy_hash[klass] = attr
|
248
257
|
attr
|
249
258
|
end
|
250
|
-
|
251
|
-
# Makes a new attribute in this hook class for each of the given annotation module's
|
252
|
-
# proxy domain attributes. The hook annotation reference attribute delegates to the
|
253
|
-
# proxy.
|
254
|
-
#
|
255
|
-
# @param [AnnotationModule] mod the subject annotation module
|
256
|
-
# @param [Symbol] proxy_attribute the hook => proxy reference
|
257
|
-
def create_annotation_attributes(mod)
|
258
|
-
# create annotation attributes which delegate to the proxy
|
259
|
-
mod.proxy.annotation_attributes.each do |attr|
|
260
|
-
create_annotation_attribute(mod, attr)
|
261
|
-
end
|
262
|
-
end
|
263
|
-
|
264
|
-
# Adds the given annotation attribute as a dependent collection attribute with meta-data.
|
265
|
-
#
|
266
|
-
# @param [Symbol] attribute the annotation accessor
|
267
|
-
# @param [Class] type the attribute domain type
|
268
|
-
def add_annotation_attribute(attribute, type)
|
269
|
-
logger.debug { "Adding #{qp} #{type.qp} annotation attribute #{attribute}..." }
|
270
|
-
# Mark the attribute as a collection.
|
271
|
-
add_attribute(attribute, type, :collection)
|
272
|
-
|
273
|
-
# the camel-case attribute is a potential alias
|
274
|
-
jattr = attribute.to_s.camelize(:lower).to_sym
|
275
|
-
unless attribute == jattr then
|
276
|
-
add_attribute_aliases(jattr => attribute)
|
277
|
-
end
|
278
|
-
|
279
|
-
# the annotation is a dependent
|
280
|
-
add_dependent_attribute(attribute, :logical)
|
281
|
-
# add the attribute to the local collection
|
282
|
-
@local_ann_attrs << attribute
|
283
|
-
|
284
|
-
attribute
|
285
|
-
end
|
286
259
|
end
|
287
260
|
end
|
@@ -1,58 +1,23 @@
|
|
1
1
|
require 'caruby/resource'
|
2
2
|
require 'caruby/domain/id_alias'
|
3
|
+
require 'catissue/domain/hash_code'
|
3
4
|
|
4
5
|
module CaTissue
|
5
6
|
# Annotation acceess error class.
|
6
7
|
class AnnotationError < StandardError; end
|
7
8
|
|
8
|
-
# Annotation class mix-in.
|
9
|
+
# Annotation is the caTissue dynamic extension class mix-in.
|
10
|
+
#
|
11
|
+
# @quirk caTissue Annotation RecordEntry proxy classes implements hashCode with the identifier.
|
12
|
+
# Consequently, a set member is not found after identifier assignment.
|
13
|
+
# The work-around is to include the HashCode mixin, which reimplements the hash and equality
|
14
|
+
# test methods to be invariant with respect to identifier assignment.
|
9
15
|
module Annotation
|
10
|
-
include CaRuby::Resource, CaRuby::IdAlias
|
16
|
+
include CaRuby::Resource, CaRuby::IdAlias, HashCode
|
11
17
|
|
12
|
-
#
|
18
|
+
# @return [Database] the database which stores this object
|
13
19
|
def database
|
14
20
|
CaTissue::Database.instance
|
15
21
|
end
|
16
|
-
|
17
|
-
# Updates the annotation proxy to reflect the hook, if necessary.
|
18
|
-
#
|
19
|
-
# @see Proxy#ensure_identifier_reflects_hook
|
20
|
-
def ensure_proxy_reflects_hook
|
21
|
-
pxy = proxy || return
|
22
|
-
pxy.ensure_identifier_reflects_hook
|
23
|
-
end
|
24
|
-
|
25
|
-
# @return [Annotatable, nil] the hook object which owns this annotation, or nil if this annotation
|
26
|
-
# is not directly owned by a hook entity
|
27
|
-
def hook
|
28
|
-
pxy_attr_md = self.class.proxy_attribute_metadata
|
29
|
-
send(pxy_attr_md.reader) if pxy_attr_md
|
30
|
-
end
|
31
|
-
|
32
|
-
# If there is no conventional owner, then try the hook.
|
33
|
-
#
|
34
|
-
# caTissue alert - DE annotations have a physical dependency ownership model that is at odds
|
35
|
-
# with the logical model. An annotation does not directly reference its static hook owner
|
36
|
-
# instance. Rather, it references the hook proxy which stands in for the hook entity in the
|
37
|
-
# annotation package.
|
38
|
-
#
|
39
|
-
# @return the {CaRuby::Resource#owner} or the {#hook}
|
40
|
-
def owner
|
41
|
-
super or hook
|
42
|
-
end
|
43
|
-
|
44
|
-
# @return [Proxy, nil] the proxy which references this annotation, or nil if this is not a
|
45
|
-
# primary annotation
|
46
|
-
def proxy
|
47
|
-
# the annotation owner hook instance
|
48
|
-
ownr = hook || return
|
49
|
-
# the hook -> annotation reference attribute
|
50
|
-
attr = self.class.hook_proxy_attribute
|
51
|
-
if attr.nil? then
|
52
|
-
raise AnnotationError.new("Primary annotation #{qp} references hook #{hook} but doesn't have a hook proxy attribute")
|
53
|
-
end
|
54
|
-
# the owner proxy for the attribute
|
55
|
-
ownr.annotation_proxy(attr)
|
56
|
-
end
|
57
22
|
end
|
58
23
|
end
|