caruby-tissue 1.5.6 → 2.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +17 -0
- data/History.md +5 -1
- data/README.md +2 -2
- data/bin/crtdump +2 -8
- data/bin/crtexample +2 -5
- data/bin/crtmigrate +3 -6
- data/bin/crtsmoke +3 -8
- data/conf/wustl/{log4j.properties → linux/log4j.properties} +3 -3
- data/conf/wustl/windows/log4j.properties +40 -0
- data/examples/galena/Gemfile +16 -0
- data/examples/galena/Gemfile.lock +88 -0
- data/examples/galena/README.md +16 -16
- data/examples/galena/Rakefile +30 -0
- data/examples/galena/bin/seed +5 -11
- data/examples/galena/conf/annotation/defaults.yaml +2 -0
- data/examples/galena/conf/{migration/annotation_fields.yaml → annotation/fields.yaml} +2 -4
- data/examples/galena/conf/defaults.yaml +9 -0
- data/examples/galena/conf/{migration/filter_fields.yaml → filter/fields.yaml} +0 -1
- data/examples/galena/conf/filter/values.yaml +8 -0
- data/examples/galena/conf/{migration/frozen_defaults.yaml → frozen/defaults.yaml} +0 -0
- data/examples/galena/conf/{migration/frozen_fields.yaml → frozen/fields.yaml} +0 -2
- data/examples/galena/conf/{migration/general_fields.yaml → general/fields.yaml} +0 -24
- data/examples/galena/conf/registration/fields.yaml +6 -0
- data/examples/galena/conf/{migration/simple_fields.yaml → simple/fields.yaml} +1 -6
- data/examples/galena/data/annotation.csv +1 -1
- data/examples/galena/data/filter.csv +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/data/simple.csv +1 -1
- data/examples/galena/galena.gemspec +24 -0
- data/examples/galena/lib/galena/filter.rb +25 -0
- data/examples/galena/lib/galena/{tissue/migration/frozen_shims.rb → frozen.rb} +6 -10
- data/examples/galena/lib/galena/seed.rb +126 -0
- data/examples/galena/lib/galena/version.rb +3 -0
- data/examples/galena/lib/galena.rb +18 -7
- data/examples/galena/log/galena.log +37351 -0
- data/examples/galena/log/galena.log.0 +147830 -0
- data/examples/galena/spec/annotation_spec.rb +46 -0
- data/examples/galena/spec/filter_spec.rb +94 -0
- data/examples/galena/spec/frozen_spec.rb +39 -0
- data/examples/galena/spec/general_spec.rb +62 -0
- data/examples/galena/spec/registration_spec.rb +37 -0
- data/examples/galena/spec/seed.rb +107 -0
- data/examples/galena/spec/simple_spec.rb +58 -0
- data/examples/galena/spec/spec_helper.rb +11 -0
- data/examples/galena/spec/support/migration.rb +70 -0
- data/lib/catissue/annotation/annotatable.rb +10 -8
- data/lib/catissue/annotation/annotation.rb +7 -7
- data/lib/catissue/annotation/de_integration.rb +9 -20
- data/lib/catissue/annotation/importer.rb +148 -0
- data/lib/catissue/annotation/introspector.rb +32 -0
- data/lib/catissue/annotation/metadata.rb +422 -0
- data/lib/catissue/annotation/proxy.rb +2 -2
- data/lib/catissue/annotation/proxy_class.rb +45 -30
- data/lib/catissue/annotation/record_entry_proxy.rb +2 -2
- data/lib/catissue/cli/command.rb +14 -24
- data/lib/catissue/cli/example.rb +5 -3
- data/lib/catissue/cli/migrate.rb +45 -37
- data/lib/catissue/cli/smoke.rb +2 -3
- data/lib/catissue/database/annotation/annotation_service.rb +8 -17
- data/lib/catissue/database/annotation/entity_facade.rb +33 -30
- data/lib/catissue/database/annotation/id_generator.rb +1 -1
- data/lib/catissue/database/annotation/integration_service.rb +11 -4
- data/lib/catissue/database/annotation/reference_writer.rb +38 -38
- data/lib/catissue/database/controlled_value_finder.rb +13 -28
- data/lib/catissue/database/controlled_values.rb +73 -45
- data/lib/catissue/database.rb +637 -277
- data/lib/catissue/domain/abstract_domain_object.rb +5 -0
- data/lib/catissue/domain/abstract_position.rb +3 -5
- data/lib/catissue/domain/abstract_specimen.rb +79 -65
- data/lib/catissue/domain/abstract_specimen_collection_group.rb +3 -6
- data/lib/catissue/domain/address.rb +0 -2
- data/lib/catissue/domain/cancer_research_group.rb +0 -3
- data/lib/catissue/domain/capacity.rb +2 -4
- data/lib/catissue/domain/check_in_check_out_event_parameter.rb +0 -3
- data/lib/catissue/domain/collection_event_parameters.rb +2 -7
- data/lib/catissue/domain/collection_protocol.rb +11 -16
- data/lib/catissue/domain/collection_protocol_event.rb +19 -12
- data/lib/catissue/domain/collection_protocol_registration.rb +8 -12
- data/lib/catissue/domain/consent_tier_response.rb +0 -4
- data/lib/catissue/domain/consent_tier_status.rb +1 -4
- data/lib/catissue/domain/container.rb +10 -10
- data/lib/catissue/domain/container_position.rb +4 -7
- data/lib/catissue/domain/container_type.rb +4 -7
- data/lib/catissue/domain/department.rb +0 -3
- data/lib/catissue/domain/disposal_event_parameters.rb +5 -5
- data/lib/catissue/domain/embedded_event_parameters.rb +1 -4
- data/lib/catissue/domain/external_identifier.rb +0 -12
- data/lib/catissue/domain/frozen_event_parameters.rb +1 -4
- data/lib/catissue/domain/institution.rb +0 -3
- data/lib/catissue/domain/new_specimen_array_order_item.rb +0 -5
- data/lib/catissue/domain/order_details.rb +0 -2
- data/lib/catissue/domain/participant/clinical/chemotherapy.rb +1 -3
- data/lib/catissue/domain/participant/clinical/duration.rb +2 -4
- data/lib/catissue/domain/participant/clinical/radiation_therapy.rb +2 -4
- data/lib/catissue/domain/participant.rb +22 -24
- data/lib/catissue/domain/participant_medical_identifier.rb +0 -4
- data/lib/catissue/domain/password.rb +0 -4
- data/lib/catissue/domain/race.rb +0 -3
- data/lib/catissue/domain/received_event_parameters.rb +3 -6
- data/lib/catissue/domain/site.rb +1 -4
- data/lib/catissue/domain/specimen/pathology/additional_finding.rb +12 -0
- data/lib/catissue/domain/specimen/pathology/details.rb +12 -0
- data/lib/catissue/domain/specimen/pathology/gleason_score.rb +12 -0
- data/lib/catissue/domain/specimen/pathology/histologic_grade.rb +12 -0
- data/lib/catissue/domain/specimen/pathology/histologic_type.rb +19 -0
- data/lib/catissue/domain/specimen/pathology/histologic_variant_type.rb +12 -0
- data/lib/catissue/domain/specimen/pathology/invasion.rb +12 -0
- data/lib/catissue/domain/specimen/pathology/prostate_specimen_gleason_score.rb +5 -11
- data/lib/catissue/domain/specimen/pathology/prostate_specimen_pathology_annotation.rb +12 -12
- data/lib/catissue/domain/specimen/pathology/specimen_additional_finding.rb +5 -14
- data/lib/catissue/domain/specimen/pathology/specimen_base_solid_tissue_pathology_annotation.rb +6 -21
- data/lib/catissue/domain/specimen/pathology/specimen_details.rb +4 -10
- data/lib/catissue/domain/specimen/pathology/specimen_histologic_grade.rb +4 -10
- data/lib/catissue/domain/specimen/pathology/specimen_histologic_type.rb +6 -14
- data/lib/catissue/domain/specimen/pathology/specimen_histologic_variant_type.rb +5 -11
- data/lib/catissue/domain/specimen/pathology/specimen_invasion.rb +5 -11
- data/lib/catissue/domain/specimen.rb +113 -76
- data/lib/catissue/domain/specimen_array.rb +0 -3
- data/lib/catissue/domain/specimen_array_content.rb +1 -4
- data/lib/catissue/domain/specimen_array_type.rb +1 -4
- data/lib/catissue/domain/specimen_characteristics.rb +0 -3
- data/lib/catissue/domain/specimen_collection_group/pathology/base_pathology_annotation.rb +2 -4
- data/lib/catissue/domain/specimen_collection_group/pathology/base_solid_tissue_pathology_annotation.rb +2 -4
- data/lib/catissue/domain/specimen_collection_group.rb +43 -53
- data/lib/catissue/domain/specimen_event_parameters.rb +24 -32
- data/lib/catissue/domain/specimen_position.rb +8 -5
- data/lib/catissue/domain/specimen_protocol.rb +3 -6
- data/lib/catissue/domain/specimen_requirement.rb +22 -20
- data/lib/catissue/domain/storage_container.rb +9 -12
- data/lib/catissue/domain/storage_type.rb +6 -10
- data/lib/catissue/domain/transfer_event_parameters.rb +3 -6
- data/lib/catissue/domain/user.rb +22 -29
- data/lib/catissue/{util → helpers}/collectible.rb +23 -18
- data/lib/catissue/helpers/collectible_event_parameters.rb +68 -0
- data/lib/catissue/helpers/controlled_value.rb +35 -0
- data/lib/catissue/{domain → helpers}/hash_code.rb +0 -0
- data/lib/catissue/{util → helpers}/location.rb +6 -5
- data/lib/catissue/helpers/log.rb +4 -0
- data/lib/catissue/{util → helpers}/person.rb +1 -1
- data/lib/catissue/{util → helpers}/position.rb +10 -8
- data/lib/catissue/helpers/properties_loader.rb +143 -0
- data/lib/catissue/{util → helpers}/storable.rb +2 -1
- data/lib/catissue/{util → helpers}/storage_type_holder.rb +9 -3
- data/lib/catissue/{annotation/annotatable_class.rb → metadata.rb} +73 -95
- data/lib/catissue/migration/migratable.rb +93 -44
- data/lib/catissue/migration/migrator.rb +26 -42
- data/lib/catissue/migration/shims.rb +1 -1
- data/lib/catissue/migration/unique.rb +76 -0
- data/lib/catissue/resource.rb +16 -20
- data/lib/catissue/version.rb +1 -1
- data/lib/catissue/wustl/logger.rb +52 -32
- data/lib/catissue.rb +38 -20
- data/test/lib/catissue/database/controlled_values_test.rb +22 -27
- data/test/lib/catissue/database/database_test.rb +18 -0
- data/test/lib/catissue/domain/address_test.rb +9 -11
- data/test/lib/catissue/domain/ca_tissue_test_defaults_test.rb +5 -16
- data/test/lib/catissue/domain/capacity_test.rb +2 -2
- data/test/lib/catissue/domain/collection_event_parameters_test.rb +16 -8
- data/test/lib/catissue/domain/collection_protocol_event_test.rb +1 -1
- data/test/lib/catissue/domain/collection_protocol_registration_test.rb +26 -16
- data/test/lib/catissue/domain/collection_protocol_test.rb +2 -2
- data/test/lib/catissue/domain/container_position_test.rb +7 -4
- data/test/lib/catissue/domain/department_test.rb +3 -3
- data/test/lib/catissue/domain/disposal_event_parameters_test.rb +1 -1
- data/test/lib/catissue/domain/external_identifier_test.rb +5 -1
- data/test/lib/catissue/domain/location_test.rb +4 -4
- data/test/lib/catissue/domain/participant_medical_identifier_test.rb +3 -3
- data/test/lib/catissue/domain/participant_test.rb +33 -20
- data/test/lib/catissue/domain/received_event_parameters_test.rb +19 -0
- data/test/lib/catissue/domain/site_test.rb +2 -2
- data/test/lib/catissue/domain/specimen_array_test.rb +3 -3
- data/test/lib/catissue/domain/specimen_array_type_test.rb +6 -6
- data/test/lib/catissue/domain/specimen_characteristics_test.rb +1 -1
- data/test/lib/catissue/domain/specimen_collection_group_test.rb +49 -13
- data/test/lib/catissue/domain/specimen_event_parameters_test.rb +4 -4
- data/test/lib/catissue/domain/specimen_position_test.rb +1 -1
- data/test/lib/catissue/domain/specimen_requirement_test.rb +2 -2
- data/test/lib/catissue/domain/specimen_test.rb +58 -24
- data/test/lib/catissue/domain/storage_container_test.rb +3 -16
- data/test/lib/catissue/domain/storage_type_test.rb +3 -3
- data/test/lib/catissue/domain/transfer_event_parameters_test.rb +17 -17
- data/test/lib/catissue/domain/user_test.rb +32 -34
- data/test/lib/catissue/helpers/properties_loader_test.rb +19 -0
- data/test/lib/catissue/migration/{test_case.rb → helpers/test_case.rb} +30 -20
- data/test/lib/examples/galena/tissue/domain/examples_test.rb +28 -38
- data/test/lib/examples/galena/tissue/helpers/test_case.rb +24 -0
- metadata +175 -99
- data/bin/crtextract +0 -47
- data/examples/galena/conf/extract/simple_fields.yaml +0 -4
- data/examples/galena/conf/migration/annotation_defaults.yaml +0 -2
- data/examples/galena/conf/migration/filter_defaults.yaml +0 -1
- data/examples/galena/conf/migration/filter_values.yaml +0 -13
- data/examples/galena/conf/migration/participant_fields.yaml +0 -4
- data/examples/galena/conf/migration/registration_fields.yaml +0 -5
- data/examples/galena/data/participant.csv +0 -1
- data/examples/galena/lib/galena/tissue/migration/filter_shims.rb +0 -41
- data/examples/galena/lib/galena/tissue/seed/defaults.rb +0 -127
- data/examples/psbin/README.md +0 -45
- data/examples/psbin/conf/adjuvant_hormone_defaults.yaml +0 -2
- data/examples/psbin/conf/adjuvant_radiation_defaults.yaml +0 -3
- data/examples/psbin/conf/biopsy_defaults.yaml +0 -3
- data/examples/psbin/conf/biopsy_fields.yaml +0 -9
- data/examples/psbin/conf/neoadjuvant_hormone_defaults.yaml +0 -2
- data/examples/psbin/conf/neoadjuvant_radiation_defaults.yaml +0 -3
- data/examples/psbin/conf/patient_defaults.yaml +0 -3
- data/examples/psbin/conf/patient_fields.yaml +0 -5
- data/examples/psbin/conf/surgery_defaults.yaml +0 -4
- data/examples/psbin/conf/surgery_fields.yaml +0 -15
- data/examples/psbin/conf/t_stage_defaults.yaml +0 -1
- data/examples/psbin/conf/t_stage_fields.yaml +0 -4
- data/examples/psbin/conf/therapy_fields.yaml +0 -5
- data/examples/psbin/data/adjuvant_hormone.csv +0 -1
- data/examples/psbin/data/adjuvant_radiation.csv +0 -1
- data/examples/psbin/data/biopsy.csv +0 -1
- data/examples/psbin/data/neoadjuvant_hormone.csv +0 -1
- data/examples/psbin/data/neoadjuvant_radiation.csv +0 -1
- data/examples/psbin/data/patient.csv +0 -1
- data/examples/psbin/data/surgery.csv +0 -1
- data/examples/psbin/data/t_stage.csv +0 -1
- data/examples/psbin/lib/psbin/biopsy_shims.rb +0 -15
- data/examples/psbin/lib/psbin/surgery_shims.rb +0 -15
- data/lib/catissue/annotation/annotation_class.rb +0 -406
- data/lib/catissue/annotation/annotation_module.rb +0 -106
- data/lib/catissue/domain.rb +0 -26
- data/lib/catissue/extract/command.rb +0 -31
- data/lib/catissue/extract/delta.rb +0 -58
- data/lib/catissue/extract/extractor.rb +0 -99
- data/lib/catissue/migration/uniquify.rb +0 -2
- data/lib/catissue/util/collectible_event_parameters.rb +0 -71
- data/lib/catissue/util/controlled_value.rb +0 -29
- data/lib/catissue/util/uniquify.rb +0 -86
- data/test/fixtures/catissue/domain/conf/catissue_override.yaml +0 -9
- data/test/fixtures/catissue/extract/conf/scg_extract.yaml +0 -3
- data/test/fixtures/catissue/extract/conf/scg_fields.yaml +0 -3
- data/test/fixtures/catissue/extract/conf/spc_extract.yaml +0 -3
- data/test/fixtures/catissue/extract/conf/spc_fields.yaml +0 -4
- data/test/fixtures/lib/catissue/defaults_test_fixture.rb +0 -206
- data/test/fixtures/lib/examples/galena/migration/alt_key_shims.rb +0 -7
- data/test/lib/catissue/domain/base_haemotology_pathology_test.rb +0 -24
- data/test/lib/catissue/extract/delta_test.rb +0 -25
- data/test/lib/catissue/extract/extractor_test.rb +0 -43
- data/test/lib/catissue/import/importable_module_test.rb +0 -14
- data/test/lib/catissue/test_case.rb +0 -247
- data/test/lib/examples/galena/tissue/migration/annotation_test.rb +0 -29
- data/test/lib/examples/galena/tissue/migration/filter_test.rb +0 -29
- data/test/lib/examples/galena/tissue/migration/frozen_test.rb +0 -36
- data/test/lib/examples/galena/tissue/migration/general_test.rb +0 -56
- data/test/lib/examples/galena/tissue/migration/participant_test.rb +0 -61
- data/test/lib/examples/galena/tissue/migration/registration_test.rb +0 -17
- data/test/lib/examples/galena/tissue/migration/seedify.rb +0 -119
- data/test/lib/examples/galena/tissue/migration/simple_test.rb +0 -30
- data/test/lib/examples/galena/tissue/migration/test_case.rb +0 -72
- data/test/lib/examples/psbin/migration_test.rb +0 -153
@@ -4,12 +4,12 @@ module CaTissue
|
|
4
4
|
module Proxy
|
5
5
|
# @return [Annotatable] the annotated domain object
|
6
6
|
def hook
|
7
|
-
send(self.class.
|
7
|
+
send(self.class.owner_property.reader)
|
8
8
|
end
|
9
9
|
|
10
10
|
# @param [Annotatable] obj the domain object to annotate
|
11
11
|
def hook=(obj)
|
12
|
-
send(self.class.
|
12
|
+
send(self.class.owner_property.writer, obj)
|
13
13
|
end
|
14
14
|
|
15
15
|
# Ensures that this proxy's hook exists in the database.
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'set'
|
2
|
-
require '
|
3
|
-
|
2
|
+
require 'jinx/helpers/collections'
|
3
|
+
|
4
|
+
require 'jinx/helpers/partial_order'
|
4
5
|
require 'catissue/annotation/annotation'
|
5
6
|
require 'catissue/annotation/proxy_1_1'
|
6
7
|
require 'catissue/annotation/record_entry_proxy'
|
@@ -9,6 +10,9 @@ module CaTissue
|
|
9
10
|
module Annotation
|
10
11
|
# Annotation hook proxy class mix-in.
|
11
12
|
module ProxyClass
|
13
|
+
# @return [CaRuby::Property] the hook class attribute meta-data for this proxy
|
14
|
+
attr_reader :hook_property
|
15
|
+
|
12
16
|
# @param [Class] klass the proxy class
|
13
17
|
def self.extended(klass)
|
14
18
|
super
|
@@ -17,55 +21,67 @@ module CaTissue
|
|
17
21
|
klass.class_eval { include mixin }
|
18
22
|
end
|
19
23
|
|
20
|
-
# @return [
|
24
|
+
# @return [Metadata] the hook class for this proxy
|
21
25
|
def hook
|
22
|
-
|
26
|
+
hook_property.type
|
23
27
|
end
|
24
28
|
|
25
29
|
# Sets this proxy's hook to the given class and creates the
|
26
30
|
# proxy => hook attribute with the given hook => proxy inverse.
|
27
31
|
#
|
28
|
-
# @param [
|
32
|
+
# @param [Metadata] klass the annotated domain object class
|
29
33
|
def hook=(klass)
|
30
34
|
# Make a new hook reference attribute.
|
31
|
-
|
32
|
-
attr_accessor(
|
35
|
+
pa = klass.name.demodulize.underscore
|
36
|
+
attr_accessor(pa)
|
33
37
|
# The attribute type is the given hook class.
|
34
|
-
add_attribute(
|
35
|
-
logger.debug { "Added #{klass.qp} annotation proxy => hook attribute #{
|
38
|
+
@hook_property = add_attribute(pa, klass)
|
39
|
+
logger.debug { "Added #{klass.qp} annotation proxy => hook attribute #{pa}." }
|
36
40
|
end
|
37
41
|
|
38
42
|
# Adds each proxy => annotation reference as a dependent attribute.
|
39
43
|
# Recursively adds dependents of all referenced annotations.
|
44
|
+
#
|
45
|
+
# This method defines a proxy attribute in each primary annotation class
|
46
|
+
# for each {#non_proxy_annotation_classes} class hierarchy.
|
40
47
|
def build_annotation_dependency_hierarchy
|
41
48
|
logger.debug { "Building annotation dependency hierarchy..." }
|
42
49
|
non_proxy_annotation_classes.each do |klass|
|
43
|
-
klass
|
44
|
-
if anc.primary? and anc.proxy_attribute.nil? then
|
45
|
-
anc.define_proxy_attribute(self)
|
46
|
-
end
|
47
|
-
end
|
48
|
-
logger.info(klass.pp_s)
|
50
|
+
ensure_primary_references_proxy(klass)
|
49
51
|
end
|
50
52
|
set_inverses
|
51
53
|
add_dependent_attributes
|
52
54
|
add_dependent_attribute_closure
|
53
55
|
end
|
54
56
|
|
57
|
+
# Ensures that the given primary class references this proxy.
|
58
|
+
#
|
59
|
+
# @param [Metadata] klass the primary annotation class to check
|
60
|
+
def ensure_primary_references_proxy(klass)
|
61
|
+
# Define the superclass proxy attributes, starting with the most general class.
|
62
|
+
klass.annotation_hierarchy.to_a.reverse_each do |anc|
|
63
|
+
if anc.primary? and anc.proxy_attribute.nil? then
|
64
|
+
anc.define_proxy_attribute(self)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
55
69
|
# Creates a reference attribute from this proxy to the given primary {Annotation} class.
|
56
70
|
#
|
57
|
-
# @param [Class] klass the annotation class
|
71
|
+
# @param [Class] klass the target annotation class
|
72
|
+
# @return [Symbol] the new annotation reference attribute
|
58
73
|
def create_annotation_attribute(klass)
|
59
74
|
# the new attribute symbol
|
60
|
-
|
61
|
-
logger.debug { "Creating annotation proxy #{qp} attribute #{
|
75
|
+
pa = klass.name.demodulize.underscore.pluralize.to_sym
|
76
|
+
logger.debug { "Creating annotation proxy #{qp} attribute #{pa} to hold primary annotation #{klass.qp} instances..." }
|
62
77
|
# Define the access methods: the reader creates a new set on demand to hold the annotations.
|
63
|
-
attr_create_on_demand_accessor(
|
78
|
+
attr_create_on_demand_accessor(pa) { Set.new }
|
64
79
|
# add the annotation collection attribute
|
65
|
-
add_attribute(
|
80
|
+
add_attribute(pa, klass, :collection)
|
66
81
|
# The annotation is dependent.
|
67
|
-
add_dependent_attribute(
|
68
|
-
|
82
|
+
add_dependent_attribute(pa, :logical)
|
83
|
+
logger.debug { "Created annotation proxy #{qp} dependent attribute #{pa}." }
|
84
|
+
pa
|
69
85
|
end
|
70
86
|
|
71
87
|
private
|
@@ -79,18 +95,17 @@ module CaTissue
|
|
79
95
|
# The inverse is the direct, unwrapped proxy reference named by the annotation module.
|
80
96
|
inv = annotation_module.name.demodulize.underscore.to_sym
|
81
97
|
# The attributes in class hierarchy general-to-specific order
|
82
|
-
|
83
|
-
logger.debug { "Setting #{self} inverses for annotation attributes #{
|
84
|
-
|
85
|
-
|
86
|
-
set_attribute_inverse(
|
98
|
+
props = annotation_attributes.properties.partial_sort_by { |prop| prop.type }.reverse
|
99
|
+
logger.debug { "Setting #{self} inverses for annotation attributes #{props.to_series}." }
|
100
|
+
props.each do |prop|
|
101
|
+
prop.type.define_proxy_attribute(self)
|
102
|
+
set_attribute_inverse(prop.to_sym, inv)
|
87
103
|
end
|
88
104
|
end
|
89
105
|
|
90
|
-
# @return <
|
106
|
+
# @return <Metadata> the non-proxy annotation classes
|
91
107
|
def non_proxy_annotation_classes
|
92
|
-
|
93
|
-
consts.select { |c| Class === c and c < Annotation and not c < Proxy }
|
108
|
+
annotation_module.annotation_classes.filter { |klass| not klass < Proxy }
|
94
109
|
end
|
95
110
|
end
|
96
111
|
end
|
@@ -8,12 +8,12 @@ module CaTissue
|
|
8
8
|
|
9
9
|
# @return [Annotatable] the annotated domain object
|
10
10
|
def hook
|
11
|
-
send(self.class.
|
11
|
+
send(self.class.owner_property.reader)
|
12
12
|
end
|
13
13
|
|
14
14
|
# @param [Annotatable] obj the domain object to annotate
|
15
15
|
def hook=(obj)
|
16
|
-
send(self.class.
|
16
|
+
send(self.class.owner_property.writer, obj)
|
17
17
|
end
|
18
18
|
end
|
19
19
|
end
|
data/lib/catissue/cli/command.rb
CHANGED
@@ -1,30 +1,19 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
rescue Exception => e
|
7
|
-
logger.error("caTissue client load was unsuccessful - #{e}:\n#{e.backtrace.qp}")
|
8
|
-
puts "caTissue client load was unsuccessful - #{e}."
|
9
|
-
puts "See the log at #{CaRuby::Log.instance.file} for more information."
|
10
|
-
exit 1
|
11
|
-
end
|
12
|
-
|
13
|
-
require 'caruby/cli/command'
|
14
|
-
require 'catissue/version'
|
1
|
+
require 'jinx/cli/command'
|
2
|
+
require 'catissue'
|
3
|
+
# defined check below guards against bundle exec redundant version.rb load.
|
4
|
+
require 'catissue/version' unless CaTissue.const_defined?('VERSION')
|
5
|
+
require 'caruby/database'
|
15
6
|
|
16
7
|
module CaTissue
|
17
8
|
module CLI
|
18
|
-
# Augments
|
19
|
-
class Command <
|
20
|
-
#
|
9
|
+
# Augments +CaRuby::CLI::Command+ with caTissue-specific command line option handlers.
|
10
|
+
class Command < Jinx::CLI::Command
|
21
11
|
# Built-in options include those specified in +CaRuby::CLI::Command.initialize+
|
22
12
|
# as well as the following:
|
23
|
-
# *
|
13
|
+
# * +--version+ : print the version of caRuby Tissue as well as the supported
|
14
|
+
# caTissue releases and exit
|
24
15
|
#
|
25
|
-
# @param
|
26
|
-
# described in +CaRuby::CLI::Command.initialize+
|
27
|
-
# @see {CaRuby::CLI::Command#initialize}
|
16
|
+
# @param (see CaRuby::CLI::Command#initialize)
|
28
17
|
def initialize(specs=[])
|
29
18
|
specs << VERSION_OPT
|
30
19
|
super
|
@@ -43,10 +32,11 @@ module CaTissue
|
|
43
32
|
super
|
44
33
|
if opts[:version] then
|
45
34
|
puts "#{CaTissue::VERSION} for caTissue v#{CaTissue::CATISSUE_VERSIONS}"
|
46
|
-
|
47
|
-
|
35
|
+
exit 0
|
36
|
+
elseuniqurify
|
37
|
+
CaRuby::Database::ACCESS_OPTS.each do |opt, *spec|
|
48
38
|
value = opts.delete(opt)
|
49
|
-
CaTissue.
|
39
|
+
CaTissue.properties[opt] = value if value
|
50
40
|
end
|
51
41
|
end
|
52
42
|
end
|
data/lib/catissue/cli/example.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
|
-
require '
|
2
|
-
require '
|
1
|
+
require File.dirname(__FILE__) + '/command'
|
2
|
+
require 'jinx/helpers/collections'
|
3
|
+
|
3
4
|
|
4
5
|
module CaTissue
|
5
6
|
module CLI
|
@@ -16,7 +17,8 @@ module CaTissue
|
|
16
17
|
|
17
18
|
# Lists the examples.
|
18
19
|
def list
|
19
|
-
root =
|
20
|
+
root = File.expand_path('examples', File.dirname(__FILE__) + '/../../..')
|
21
|
+
raise RuntimeError.new("Examples directory not found: #{root}") unless File.exists?(root)
|
20
22
|
Dir.foreach(root) do |f|
|
21
23
|
path = File.expand_path(f, root)
|
22
24
|
if File.directory?(path) and f[0, 1] != '.' then
|
data/lib/catissue/cli/migrate.rb
CHANGED
@@ -1,7 +1,4 @@
|
|
1
|
-
|
2
|
-
DEF_LOG_FILE = 'log/migration.log'
|
3
|
-
|
4
|
-
require 'catissue/cli/command'
|
1
|
+
require File.dirname(__FILE__) + '/command'
|
5
2
|
require 'catissue/migration/migrator'
|
6
3
|
|
7
4
|
module CaTissue
|
@@ -9,52 +6,63 @@ module CaTissue
|
|
9
6
|
class Migrate < Command
|
10
7
|
# The migration option specifications.
|
11
8
|
#
|
12
|
-
# The
|
9
|
+
# The +:unique+ option ensures that the migrated objects do not conflict with existing or future
|
13
10
|
# objects. This is used for testing a migration dry run. It is recommended that the trial run
|
14
11
|
# protocol is set to a test protocol as well.
|
15
12
|
SPECS = [
|
16
|
-
[:input,
|
17
|
-
[:target,
|
18
|
-
[:mapping,
|
19
|
-
[:filters,
|
20
|
-
[:defaults,
|
21
|
-
[:shims,
|
22
|
-
[:
|
23
|
-
[:
|
24
|
-
[:
|
13
|
+
[:input, 'INPUT', 'Source file to migrate'],
|
14
|
+
[:target, '-t', '--target CLASS', 'Migration target class'],
|
15
|
+
[:mapping, '-m', '--mapping FILE[,FILE...]', Array, 'The input field => caTissue attribute mapping file(s)'],
|
16
|
+
[:filters, '--filters FILE[,FILE...]', Array, 'The input value => caTissue value mapping file(s)'],
|
17
|
+
[:defaults, '-d', '--defaults FILE[,FILE...]', Array, 'The caTissue attribute default value file(s)'],
|
18
|
+
[:shims, '-s', '--shims FILE[,FILE...]', Array, 'Migration customization shim file(s) to load'],
|
19
|
+
[:controlled_values, '-k', '--controlled_values', 'Enable controlled value lookup'],
|
20
|
+
[:bad, '-b', '--bad FILE', 'Write each invalid record to the given file and continue migration'],
|
21
|
+
[:extract, '-x', '--extract FILE', 'Call the migration target extract method to write to the given extract'],
|
22
|
+
[:create, '-c', '--create', 'Always create the migration target'],
|
23
|
+
[:unique, '-u', '--unique', 'Make the migrated objects unique for testing'],
|
24
|
+
[:from, '--from N', Integer, 'Starting input record'],
|
25
|
+
[:to, '--to N', Integer, 'Ending input record'],
|
25
26
|
]
|
26
|
-
|
27
|
-
# Creates a {Migrate} command with the
|
28
|
-
# as well as the
|
27
|
+
|
28
|
+
# Creates a {Migrate} command with the {SPECS} command line specifications
|
29
|
+
# as well as the optional specifications parameter.
|
29
30
|
#
|
30
|
-
# @
|
31
|
-
# @
|
32
|
-
# @see
|
33
|
-
def initialize(&
|
34
|
-
super(SPECS) { |opts| migrate(opts, &
|
31
|
+
# @param (see CaRuby::CLI::Command#initialize)
|
32
|
+
# @yield (see #migrate)
|
33
|
+
# @yieldparam (see #migrate)
|
34
|
+
def initialize(specs=[], &block)
|
35
|
+
super(specs.concat(SPECS)) { |opts| migrate(opts, &block) }
|
35
36
|
end
|
36
37
|
|
37
38
|
private
|
38
39
|
|
39
|
-
# Starts a Migrator with the command-line options.
|
40
|
+
# Starts a Migrator with the command-line options. Each input record is migrated to
|
41
|
+
# the caTissue database.
|
40
42
|
#
|
41
|
-
# @
|
42
|
-
# @
|
43
|
-
# @see
|
44
|
-
def migrate(opts)
|
45
|
-
|
46
|
-
|
47
|
-
|
43
|
+
# @param opts (see CaTissue::Migrator#initialize)
|
44
|
+
# @yield (see CaTissue::Migrator#migrate_to_database)
|
45
|
+
# @yieldparam (see CaTissue::Migrator#migrate_to_database)
|
46
|
+
def migrate(opts, &block)
|
47
|
+
opts[:target] = resolve(opts[:target])
|
48
|
+
# Migrate the input.
|
49
|
+
CaTissue::Migrator.new(opts).migrate_to_database(&block)
|
48
50
|
end
|
49
51
|
|
50
|
-
|
51
|
-
|
52
|
-
|
52
|
+
# Resolves the given target class name in the caTissue context.
|
53
|
+
#
|
54
|
+
# @param [String] name the target class name
|
55
|
+
# @return [Class] the resolved class
|
56
|
+
# @raise [NameError] if the class could not be resolved
|
57
|
+
def resolve(name)
|
58
|
+
return if name.nil?
|
53
59
|
begin
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
60
|
+
# Strip the CaTissue module prefix, if necessary.
|
61
|
+
cnm = name.sub(/^CaTissue::/, '')
|
62
|
+
# Resolve the class in the CaTissue context.
|
63
|
+
CaTissue.module_for_name(cnm)
|
64
|
+
rescue Exception => e
|
65
|
+
Jinx.fail(NameError, "Could not load migration target class #{name}", e)
|
58
66
|
end
|
59
67
|
end
|
60
68
|
end
|
data/lib/catissue/cli/smoke.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
|
-
require '
|
2
|
-
require 'catissue/database'
|
1
|
+
require File.dirname(__FILE__) + '/command'
|
3
2
|
|
4
3
|
module CaTissue
|
5
4
|
module CLI
|
@@ -29,7 +28,7 @@ module CaTissue
|
|
29
28
|
rescue Exception => e
|
30
29
|
logger.error("caTissue database access was unsuccessful - #{e}:\n#{e.backtrace.qp}")
|
31
30
|
puts "caTissue database access was unsuccessful - #{e}."
|
32
|
-
puts "See the log
|
31
|
+
puts "See the log for more information."
|
33
32
|
end
|
34
33
|
|
35
34
|
if site then
|
@@ -1,7 +1,6 @@
|
|
1
|
-
require '
|
1
|
+
require 'jinx/helpers/inflector'
|
2
2
|
require 'caruby/database/sql_executor'
|
3
3
|
require 'caruby/database/persistence_service'
|
4
|
-
require 'catissue/annotation/annotatable'
|
5
4
|
|
6
5
|
module CaTissue
|
7
6
|
module Annotation
|
@@ -19,16 +18,14 @@ module CaTissue
|
|
19
18
|
@intgtr = integrator
|
20
19
|
end
|
21
20
|
|
22
|
-
# Augments the
|
21
|
+
# Augments the +CaRuby::PersistenceService+ create method to handle caTissue annotation
|
23
22
|
# service peculiarities, e.g.:
|
24
|
-
# * assigns the identifier, since assignment is not done automatically as is the case with
|
25
|
-
# default application service
|
23
|
+
# * assigns the identifier, since assignment is not done automatically as is the case with
|
24
|
+
# the default application service
|
26
25
|
# * associate the annotation to the hook object
|
27
26
|
# * Save all referenced annotation objects
|
28
27
|
#
|
29
|
-
# This method
|
30
|
-
# is a top-level annotation which has a reference to the {Annotation#hook} which is
|
31
|
-
# being annotated.
|
28
|
+
# This method is only called on {Metadata#primary?} annotation objects.
|
32
29
|
#
|
33
30
|
# @param [Annotation] annotation the annotation object to create
|
34
31
|
# @return [Annotation] the annotation
|
@@ -43,14 +40,8 @@ module CaTissue
|
|
43
40
|
|
44
41
|
# @param [Annotation] (see #create)
|
45
42
|
def create_annotation(annotation)
|
46
|
-
|
47
|
-
|
48
|
-
# If no hook, then this is not a primary annotation. In that case, find a referenced
|
49
|
-
# primary annotation.
|
50
|
-
# If no hook, then this is not a primary annotation. In that case, find a referenced
|
51
|
-
# primary annotation.
|
52
|
-
if hook then
|
53
|
-
create_primary_annotation(annotation, hook)
|
43
|
+
if annotation.class.primary? then
|
44
|
+
create_primary_annotation(annotation, annotation.hook)
|
54
45
|
else
|
55
46
|
create_nonprimary_annotation(annotation)
|
56
47
|
end
|
@@ -101,4 +92,4 @@ module CaTissue
|
|
101
92
|
end
|
102
93
|
end
|
103
94
|
end
|
104
|
-
end
|
95
|
+
end
|
@@ -1,12 +1,14 @@
|
|
1
1
|
require 'singleton'
|
2
|
-
require '
|
2
|
+
require 'jinx/import/java'
|
3
3
|
require 'caruby/database/sql_executor'
|
4
4
|
require 'catissue/database/annotation/id_generator'
|
5
5
|
|
6
6
|
module CaTissue
|
7
7
|
module Annotation
|
8
|
-
# EntityFacade is the caRuby
|
9
|
-
# the caTissue singleton Winnebago object for doing lots of
|
8
|
+
# EntityFacade is the caRuby substitute for the broken caTissue EntityManager.
|
9
|
+
# EntityManager is the caTissue singleton Winnebago object for doing lots of
|
10
|
+
# things with dynamic extensions. The EntityManager defects are listed in the
|
11
|
+
# various Rubydoc quirks.
|
10
12
|
class EntityFacade
|
11
13
|
include Singleton
|
12
14
|
|
@@ -38,7 +40,7 @@ module CaTissue
|
|
38
40
|
@idgen.next_identifier(table)
|
39
41
|
end
|
40
42
|
|
41
|
-
# @quirk caTissue
|
43
|
+
# @quirk caTissue Unlike the hook entity id lookup, the annotation entity id lookup strips the leading
|
42
44
|
# package prefix from the annotation class name. caTissue DE API requires this undocumented inconsistency.
|
43
45
|
#
|
44
46
|
# @quirk caTissue call into caTissue to get entity id doesn't work. caRuby uses direct SQL instead.
|
@@ -56,23 +58,23 @@ module CaTissue
|
|
56
58
|
# @param [Integer] eid the entity id to check
|
57
59
|
# @return [Boolean] whether the entity is primary
|
58
60
|
def primary?(eid)
|
59
|
-
result = @executor.
|
61
|
+
result = @executor.query(IS_PRIMARY_SQL, eid).first
|
60
62
|
not result.nil?
|
61
63
|
end
|
62
64
|
|
63
65
|
# @param [Class] klass the {Annotatable} class
|
64
66
|
# @return [Integer] the class entity id
|
65
67
|
def hook_entity_id(klass)
|
66
|
-
result = @executor.
|
68
|
+
result = @executor.query(HOOK_ENTITY_ID_SQL, klass.java_class.name).first
|
67
69
|
if result.nil? then raise AnnotationError.new("Entity id not found for static hook class #{klass.qp}") end
|
68
70
|
eid = result[0].to_i
|
69
71
|
logger.debug { "Static hook class #{klass.qp} has entity id #{eid}." }
|
70
72
|
eid
|
71
73
|
end
|
72
74
|
|
73
|
-
# @quirk caTissue call into caTissue to get entity id doesn't work for non-primary object.
|
74
|
-
# Furthermore, the SQL used for the #{#annotation_entity_id} doesn't work for associated
|
75
|
-
# classes. Use alternative SQL instead.
|
75
|
+
# @quirk caTissue The call into caTissue to get entity id doesn't work for a non-primary object.
|
76
|
+
# Furthermore, the SQL used for the #{#annotation_entity_id} doesn't work for associated
|
77
|
+
# annotation classes. Use the {ASSN_ENTITY_ID_SQL} alternative SQL instead.
|
76
78
|
#
|
77
79
|
# @param [Integer] eid the referencing entity id
|
78
80
|
# @param [String] name the association property name
|
@@ -91,16 +93,16 @@ module CaTissue
|
|
91
93
|
|
92
94
|
# @quirk caTissue Annotation classes are incorrectly mapped to entity ids, which in turn are
|
93
95
|
# incorrectly mapped to a table name. A candidate work-around is to bypass the caTissue DE
|
94
|
-
# mechanism and hit the DE Hibernate config files directly. However, the DE Hibernate
|
95
|
-
# are incorrect and possibly no longer used. Therefore, the table must be obtained
|
96
|
-
# work-arounds.
|
96
|
+
# mechanism and hit the DE Hibernate config files directly. However, the 1.1.2 DE Hibernate
|
97
|
+
# mappings are incorrect and possibly no longer used. Therefore, the table must be obtained
|
98
|
+
# by SQL work-arounds.
|
97
99
|
#
|
98
100
|
# @param [Annotation] obj the annotation object
|
99
101
|
# @return [String] the entity table name
|
100
102
|
# @param [Integer] the annotation entity identifier
|
101
103
|
# @return [String] the entity table name
|
102
104
|
def annotation_table_for_entity_id(eid)
|
103
|
-
result = @executor.
|
105
|
+
result = @executor.query(TABLE_NAME_SQL, eid).first
|
104
106
|
if result.nil? then raise AnnotationError.new("Table not found for annotation entity id #{eid}") end
|
105
107
|
tbl = result[0]
|
106
108
|
logger.debug { "Annotation entity with id #{eid} has table #{tbl}." }
|
@@ -110,14 +112,14 @@ module CaTissue
|
|
110
112
|
# @param (see #associated_entity_id)
|
111
113
|
# @return [Integer, nil] the parent entity id, if any
|
112
114
|
def parent_entity_id(eid)
|
113
|
-
result = @executor.
|
115
|
+
result = @executor.query(PARENT_ENTITY_ID_SQL, eid).first
|
114
116
|
result[0].to_i if result and result[0]
|
115
117
|
end
|
116
118
|
|
117
119
|
# Obtains the undocumented caTisue container id for the given primary entity id.
|
118
120
|
#
|
119
|
-
# @quirk caTissue EntityManager.
|
120
|
-
# (cf. https://cabig-kc.nci.nih.gov/Biospecimen/forums/viewtopic.php?f=19&t=421&sid=5252d951301e598eebf3e90036da43cb).
|
121
|
+
# @quirk caTissue 1.1.2 EntityManager.getContainerIdForEntity uses an
|
122
|
+
# incorrect table (cf. https://cabig-kc.nci.nih.gov/Biospecimen/forums/viewtopic.php?f=19&t=421&sid=5252d951301e598eebf3e90036da43cb).
|
121
123
|
# The standard DE API call submits the query:
|
122
124
|
# SELECT IDENTIFIER FROM dyextn_container WHERE ENTITY_ID = ?
|
123
125
|
# This results in the error:
|
@@ -126,14 +128,15 @@ module CaTissue
|
|
126
128
|
# SELECT IDENTIFIER FROM dyextn_container WHERE ABSTRACT_ENTITY_ID = ?
|
127
129
|
# The work-around is to call this SQL directly.
|
128
130
|
#
|
129
|
-
# @quirk caTissue
|
131
|
+
# @quirk caTissue 1.2 There are deprecated primary annotations with an entity id
|
132
|
+
# but no container id.
|
130
133
|
#
|
131
134
|
# @return [Integer] eid the primary entity id
|
132
135
|
def container_id(eid)
|
133
|
-
# The following call is broken (see method doc).
|
136
|
+
# The following call is broken in caTissue 1.1.2 (see method doc).
|
134
137
|
# EntityManager.instance.get_container_id_for_entity(eid)
|
135
|
-
# Work-around caTissue bug with direct query.
|
136
|
-
result = @executor.
|
138
|
+
# Work-around this caTissue bug with a direct query.
|
139
|
+
result = @executor.query(CTR_ID_SQL, eid).first
|
137
140
|
if result.nil? then
|
138
141
|
logger.debug("Dynamic extension container id not found for annotation with entity id #{eid}")
|
139
142
|
return
|
@@ -163,7 +166,7 @@ module CaTissue
|
|
163
166
|
# The entity group and name.
|
164
167
|
grp, name = split_annotation_entity_class_name(klass)
|
165
168
|
# Dive into some obscure SQL.
|
166
|
-
result = @executor.
|
169
|
+
result = @executor.query(ANN_ENTITY_ID_SQL, grp, name).first
|
167
170
|
result[0].to_i if result
|
168
171
|
end
|
169
172
|
|
@@ -208,23 +211,23 @@ module CaTissue
|
|
208
211
|
end
|
209
212
|
|
210
213
|
# @param (see #recursive_associated_entity_id)
|
211
|
-
# @return
|
214
|
+
# @return [Integer, nil] the directly associated entity id, if any
|
212
215
|
def nonrecursive_associated_entity_id(eid, role)
|
213
216
|
logger.debug { "Finding entity id #{eid} #{role} associated entity id..." }
|
214
|
-
result = @executor.
|
215
|
-
# The role
|
216
|
-
#
|
217
|
+
result = @executor.query(ASSN_ENTITY_ID_SQL, eid, role).first
|
218
|
+
# The role can be a mutation of the property name with spaces inserted in the
|
219
|
+
# mixed-case components, e.g. 'Additional Finding' instead of 'AdditionalFinding'.
|
217
220
|
# TODO - fix this kludge by finding out how the role relates to the property in the
|
218
221
|
# database.
|
219
222
|
if result.nil? and role =~ /.+[A-Z]/ then
|
220
223
|
alt = role.gsub(/(.)([A-Z])/, '\1 \2')
|
221
224
|
logger.debug { "Attempting to find entity id #{eid} #{role} associated entity id using variant #{alt}..." }
|
222
|
-
result = @executor.
|
225
|
+
result = @executor.query(ASSN_ENTITY_ID_SQL, eid, alt).first
|
223
226
|
end
|
224
227
|
if result.nil? and role =~ /[pP]athologic[^a]/ then
|
225
228
|
alt = role.sub(/([pP])athologic/, '\1athological')
|
226
229
|
logger.debug { "Attempting to find entity id #{eid} #{role} associated entity id using variant #{alt}..." }
|
227
|
-
result = @executor.
|
230
|
+
result = @executor.query(ASSN_ENTITY_ID_SQL, eid, alt).first
|
228
231
|
end
|
229
232
|
if result.nil? then logger.debug { "Entity id #{eid} is not directly associated with #{role}." } end
|
230
233
|
result[0].to_i if result
|
@@ -250,9 +253,9 @@ EOS
|
|
250
253
|
# The SQL to find an entity id for an annotation reference.
|
251
254
|
ASSN_ENTITY_ID_SQL = <<EOS
|
252
255
|
select assn.TARGET_ENTITY_ID
|
253
|
-
from DYEXTN_ATTRIBUTE
|
254
|
-
where assn.IDENTIFIER =
|
255
|
-
and
|
256
|
+
from DYEXTN_ATTRIBUTE pa, DYEXTN_ABSTRACT_ENTITY ae, DYEXTN_ASSOCIATION assn, DYEXTN_ROLE role
|
257
|
+
where assn.IDENTIFIER = pa.IDENTIFIER
|
258
|
+
and pa.ENTIY_ID = ae.id
|
256
259
|
and assn.TARGET_ROLE_ID = role.IDENTIFIER
|
257
260
|
and ae.id = ?
|
258
261
|
and role.name = ?
|