caruby-tissue 1.2.2 → 1.2.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (153) hide show
  1. data/History.txt +4 -0
  2. data/bin/crtdump +11 -3
  3. data/bin/{seed → crtseed} +0 -0
  4. data/conf/annotation/pathology_scg/AdditionalFinding.hbm.xml +19 -0
  5. data/conf/annotation/pathology_scg/BasePathologyAnnotation.hbm.xml +260 -0
  6. data/conf/annotation/pathology_scg/BreastMargin.hbm.xml +21 -0
  7. data/conf/annotation/pathology_scg/BreastMarginInvolved.hbm.xml +15 -0
  8. data/conf/annotation/pathology_scg/BreastMarginUninvolved.hbm.xml +14 -0
  9. data/conf/annotation/pathology_scg/CNSMargin.hbm.xml +19 -0
  10. data/conf/annotation/pathology_scg/CNSMarginLocation.hbm.xml +14 -0
  11. data/conf/annotation/pathology_scg/CarcinomaInSituStatus.hbm.xml +14 -0
  12. data/conf/annotation/pathology_scg/ColorectalLocalExcisionMarginUninvolved.hbm.xml +15 -0
  13. data/conf/annotation/pathology_scg/ColorectalResectedMarginUninvolved.hbm.xml +22 -0
  14. data/conf/annotation/pathology_scg/Cytogenetics.hbm.xml +15 -0
  15. data/conf/annotation/pathology_scg/DeepMelanomaMargin.hbm.xml +16 -0
  16. data/conf/annotation/pathology_scg/Details.hbm.xml +14 -0
  17. data/conf/annotation/pathology_scg/DirectExtensionOfTumor.hbm.xml +14 -0
  18. data/conf/annotation/pathology_scg/DistalMargin.hbm.xml +15 -0
  19. data/conf/annotation/pathology_scg/DistanceFromAnalVerge.hbm.xml +23 -0
  20. data/conf/annotation/pathology_scg/DistantMetastasis.hbm.xml +19 -0
  21. data/conf/annotation/pathology_scg/ExcionalBiopsyMarginUninvolved.hbm.xml +15 -0
  22. data/conf/annotation/pathology_scg/ExcisionalBiopsyColorectalDeepMargin.hbm.xml +15 -0
  23. data/conf/annotation/pathology_scg/ExcisionalBiopsyColorectalLateralOrMucosalMargin.hbm.xml +15 -0
  24. data/conf/annotation/pathology_scg/ExtraprostaticExtension.hbm.xml +20 -0
  25. data/conf/annotation/pathology_scg/ExtraprostaticExtensionTissueSites.hbm.xml +14 -0
  26. data/conf/annotation/pathology_scg/GleasonScore.hbm.xml +16 -0
  27. data/conf/annotation/pathology_scg/HistologicGrade.hbm.xml +16 -0
  28. data/conf/annotation/pathology_scg/HistologicType.hbm.xml +19 -0
  29. data/conf/annotation/pathology_scg/HistologicVariantType.hbm.xml +14 -0
  30. data/conf/annotation/pathology_scg/ImmunoPhenotyping.hbm.xml +16 -0
  31. data/conf/annotation/pathology_scg/Invasion.hbm.xml +16 -0
  32. data/conf/annotation/pathology_scg/KidneyMarginLocation.hbm.xml +15 -0
  33. data/conf/annotation/pathology_scg/KidneyNephrectomyMargin.hbm.xml +19 -0
  34. data/conf/annotation/pathology_scg/LateralMelanomaMargin.hbm.xml +16 -0
  35. data/conf/annotation/pathology_scg/LocalExcisionColorectalDeepMargin.hbm.xml +15 -0
  36. data/conf/annotation/pathology_scg/LocalExcisionColorectalLateralMargin.hbm.xml +20 -0
  37. data/conf/annotation/pathology_scg/LungResectionMargin.hbm.xml +17 -0
  38. data/conf/annotation/pathology_scg/LungResectionMarginsUninvolved.hbm.xml +14 -0
  39. data/conf/annotation/pathology_scg/MacroscopicExtentOfTumor.hbm.xml +14 -0
  40. data/conf/annotation/pathology_scg/MesentricMargin.hbm.xml +15 -0
  41. data/conf/annotation/pathology_scg/MetastasisTissueSite.hbm.xml +15 -0
  42. data/conf/annotation/pathology_scg/Microcalcification.hbm.xml +14 -0
  43. data/conf/annotation/pathology_scg/NottinghamHistologicScore.hbm.xml +17 -0
  44. data/conf/annotation/pathology_scg/OtherResectedOrgans.hbm.xml +15 -0
  45. data/conf/annotation/pathology_scg/PancreasMargin.hbm.xml +20 -0
  46. data/conf/annotation/pathology_scg/PancreasMarginInvolvedByInvasiveCarcinoma.hbm.xml +15 -0
  47. data/conf/annotation/pathology_scg/PancreasMarginUninvolvedByInvasiveCarcinoma.hbm.xml +20 -0
  48. data/conf/annotation/pathology_scg/PathologicalStaging.hbm.xml +16 -0
  49. data/conf/annotation/pathology_scg/PolypConfiguration.hbm.xml +15 -0
  50. data/conf/annotation/pathology_scg/PrimaryTumorStage.hbm.xml +14 -0
  51. data/conf/annotation/pathology_scg/ProstateMarginLocation.hbm.xml +15 -0
  52. data/conf/annotation/pathology_scg/ProximalMargin.hbm.xml +15 -0
  53. data/conf/annotation/pathology_scg/RadialMargin.hbm.xml +15 -0
  54. data/conf/annotation/pathology_scg/RadicalProstatectomyMargin.hbm.xml +20 -0
  55. data/conf/annotation/pathology_scg/RegionalLymphNode.hbm.xml +19 -0
  56. data/conf/annotation/pathology_scg/SatelliteNodule.hbm.xml +14 -0
  57. data/conf/annotation/pathology_scg/SpecimenCollectionGroup.hbm.xml +87 -0
  58. data/conf/annotation/pathology_scg/SpecimenIntegrity.hbm.xml +15 -0
  59. data/conf/annotation/pathology_scg/SpecimenSize.hbm.xml +17 -0
  60. data/conf/annotation/pathology_scg/TissueSide.hbm.xml +14 -0
  61. data/conf/annotation/pathology_scg/TumorSize.hbm.xml +29 -0
  62. data/conf/annotation/pathology_scg/TumorTissueSite.hbm.xml +20 -0
  63. data/conf/annotation/pathology_scg/UninvolvedMelanomaMargin.hbm.xml +15 -0
  64. data/conf/annotation/pathology_specimen/AdditionalFinding.hbm.xml +19 -0
  65. data/conf/annotation/pathology_specimen/AdditionalPathologicFinding.hbm.xml +18 -0
  66. data/conf/annotation/pathology_specimen/Details.hbm.xml +15 -0
  67. data/conf/annotation/pathology_specimen/GleasonScore.hbm.xml +16 -0
  68. data/conf/annotation/pathology_specimen/HistologicGrade.hbm.xml +16 -0
  69. data/conf/annotation/pathology_specimen/HistologicType.hbm.xml +19 -0
  70. data/conf/annotation/pathology_specimen/HistologicVariantType.hbm.xml +14 -0
  71. data/conf/annotation/pathology_specimen/Invasion.hbm.xml +16 -0
  72. data/conf/annotation/pathology_specimen/NottinghamHistologicScore.hbm.xml +17 -0
  73. data/conf/annotation/pathology_specimen/Specimen.hbm.xml +52 -0
  74. data/conf/annotation/pathology_specimen/SpecimenBaseSolidTissuePathologyAnnotation.hbm.xml +73 -0
  75. data/examples/galena/lib/galena/cli/seed.rb +0 -21
  76. data/examples/galena/lib/galena/migration/frozen_shims.rb +6 -5
  77. data/examples/galena/lib/galena/seed/defaults.rb +0 -5
  78. data/{lib → examples/galena/lib}/galena.rb +0 -0
  79. data/lib/catissue/annotation/annotatable.rb +37 -0
  80. data/lib/catissue/annotation/annotatable_class.rb +255 -0
  81. data/lib/catissue/annotation/annotation.rb +49 -0
  82. data/lib/catissue/annotation/annotation_class.rb +277 -0
  83. data/lib/catissue/annotation/annotation_module.rb +77 -0
  84. data/lib/catissue/annotation/hibernate_mapping.rb +46 -0
  85. data/lib/catissue/annotation/proxy.rb +28 -0
  86. data/lib/catissue/annotation/proxy_class.rb +68 -0
  87. data/lib/catissue/cli/migrate.rb +2 -2
  88. data/lib/catissue/cli/smoke.rb +6 -4
  89. data/lib/catissue/database/annotation/annotation_service.rb +75 -61
  90. data/lib/catissue/database/annotation/annotator.rb +17 -76
  91. data/lib/catissue/database/annotation/entity_facade.rb +265 -0
  92. data/lib/catissue/database/annotation/id_generator.rb +62 -0
  93. data/lib/catissue/database/annotation/integration_service.rb +105 -59
  94. data/lib/catissue/database/annotation/reference_writer.rb +150 -0
  95. data/lib/catissue/database/controlled_values.rb +12 -12
  96. data/lib/catissue/database.rb +148 -58
  97. data/lib/catissue/domain/abstract_specimen.rb +40 -14
  98. data/lib/catissue/domain/abstract_specimen_collection_group.rb +1 -3
  99. data/lib/catissue/domain/collection_protocol.rb +13 -5
  100. data/lib/catissue/domain/collection_protocol_event.rb +1 -14
  101. data/lib/catissue/domain/consent_tier_response.rb +2 -0
  102. data/lib/catissue/domain/consent_tier_status.rb +5 -3
  103. data/lib/catissue/domain/container.rb +14 -10
  104. data/lib/catissue/domain/container_position.rb +8 -0
  105. data/lib/catissue/domain/container_type.rb +13 -6
  106. data/lib/catissue/domain/participant.rb +15 -10
  107. data/lib/catissue/domain/site.rb +9 -3
  108. data/lib/catissue/domain/specimen.rb +79 -40
  109. data/lib/catissue/domain/specimen_array.rb +11 -1
  110. data/lib/catissue/domain/specimen_collection_group.rb +79 -41
  111. data/lib/catissue/domain/specimen_event_parameters.rb +5 -8
  112. data/lib/catissue/domain/specimen_position.rb +0 -2
  113. data/lib/catissue/domain/specimen_requirement.rb +1 -1
  114. data/lib/catissue/domain/storage_container.rb +109 -48
  115. data/lib/catissue/domain/storage_type.rb +1 -1
  116. data/lib/catissue/migration/migrator.rb +6 -14
  117. data/lib/catissue/resource.rb +18 -8
  118. data/lib/catissue/util/position.rb +11 -1
  119. data/lib/catissue/util/storable.rb +18 -11
  120. data/lib/catissue/util/storage_type_holder.rb +44 -6
  121. data/lib/catissue/version.rb +1 -1
  122. metadata +86 -35
  123. data/bin/migrate.rb +0 -42
  124. data/bin/seed.rb +0 -43
  125. data/examples/galena/doc/CaTissue/Participant.html +0 -241
  126. data/examples/galena/doc/CaTissue/SpecimenCollectionGroup.html +0 -190
  127. data/examples/galena/doc/CaTissue/StorageContainer.html +0 -179
  128. data/examples/galena/doc/CaTissue/TissueSpecimen.html +0 -320
  129. data/examples/galena/doc/CaTissue.html +0 -93
  130. data/examples/galena/doc/Galena/Seed/Defaults.html +0 -650
  131. data/examples/galena/doc/Galena/Seed.html +0 -203
  132. data/examples/galena/doc/Galena.html +0 -172
  133. data/examples/galena/doc/_index.html +0 -181
  134. data/examples/galena/doc/class_list.html +0 -36
  135. data/examples/galena/doc/css/common.css +0 -1
  136. data/examples/galena/doc/css/full_list.css +0 -53
  137. data/examples/galena/doc/css/style.css +0 -307
  138. data/examples/galena/doc/file.README.html +0 -153
  139. data/examples/galena/doc/file_list.html +0 -38
  140. data/examples/galena/doc/frames.html +0 -13
  141. data/examples/galena/doc/index.html +0 -153
  142. data/examples/galena/doc/js/app.js +0 -202
  143. data/examples/galena/doc/js/full_list.js +0 -149
  144. data/examples/galena/doc/js/jquery.js +0 -154
  145. data/examples/galena/doc/method_list.html +0 -163
  146. data/examples/galena/doc/top-level-namespace.html +0 -112
  147. data/lib/README.html +0 -33
  148. data/lib/catissue/database/annotation/annotatable_service.rb +0 -25
  149. data/lib/catissue/database/annotation/entity_manager.rb +0 -10
  150. data/lib/galena/cli/seed.rb +0 -43
  151. data/lib/galena/migration/filter_shims.rb +0 -43
  152. data/lib/galena/migration/frozen_shims.rb +0 -53
  153. data/lib/galena/seed/defaults.rb +0 -109
@@ -0,0 +1,77 @@
1
+ require 'caruby/domain/resource_module'
2
+ require 'catissue/annotation/annotation'
3
+ require 'catissue/annotation/annotation_class'
4
+ require 'catissue/annotation/proxy'
5
+ require 'catissue/annotation/proxy_class'
6
+
7
+ module CaTissue
8
+ module AnnotationModule
9
+ include CaRuby::ResourceModule
10
+
11
+ # @return [AnnotationClass] the annotation proxy class
12
+ attr_accessor :proxy
13
+
14
+ def self.extend_module(mod, hook, opts)
15
+ mod.extend(self)
16
+ mod.initialize_annotation(hook, opts)
17
+ end
18
+
19
+ def initialize_annotation(hook, opts)
20
+ extend(CaRuby::ResourceModule)
21
+ @java_package = opts[:package]
22
+ @svc_nm = opts[:service]
23
+ create_mixin
24
+ # Proxy initialization has to set proxy mid-initialization.
25
+ # That is why @proxy is writable. Although setting @proxy
26
+ # is redundant here, do so since that is the better approach
27
+ # and will be necessary if and when proxy init is cleaned up.
28
+ @proxy = import_proxy(hook)
29
+ @proxy.extend(Annotation::ProxyClass)
30
+ end
31
+
32
+ # Ensures that each primary annotation in this module has a proxy reference attribute.
33
+ # The primary annotation creates a proxy attribute if necessary.
34
+ def ensure_proxy_attributes_are_defined
35
+ @rsc_classes.each { |klass| klass.ensure_primary_has_proxy(@proxy) }
36
+ end
37
+
38
+ # Builds an annotation dependency hierarchy starting at the proxy.
39
+ def add_annotation_dependents
40
+ @proxy.add_annotation_dependents
41
+ end
42
+
43
+ def persistence_service
44
+ @ann_svc ||= Database.instance.annotator.create_annotation_service(@svc_nm)
45
+ end
46
+
47
+ private
48
+
49
+ def create_mixin
50
+ module_eval("module Resource; end")
51
+ @mixin = const_get('Resource')
52
+ mod = self
53
+ @mixin.module_eval do
54
+ include Annotation
55
+
56
+ @domain_module = mod
57
+ def self.included(klass)
58
+ super
59
+ @domain_module.add_class(klass)
60
+ klass.extend(AnnotationClass)
61
+ logger.debug { "#{klass.qp} marked as an annotation class." }
62
+ end
63
+ end
64
+ end
65
+
66
+ def import_proxy(hook)
67
+ # the annotation proxy Java class name
68
+ proxy_nm = hook.name.demodulize
69
+ logger.debug { "Importing #{hook.qp} annotation #{qp} hook proxy Java class..." }
70
+ begin
71
+ const_get(proxy_nm)
72
+ rescue CaRuby::JavaIncludeError
73
+ raise AnnotationError.new("#{hook.qp} annotation #{qp} does not have a hook proxy class - #{$!}")
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,46 @@
1
+ require 'xmlsimple'
2
+ require 'caruby/util/inflector'
3
+ require 'catissue/annotation/annotation'
4
+
5
+ module CaTissue
6
+ module Annotation
7
+ # Annotation class Hibernate mapping encapsulation.
8
+ #
9
+ # caTissue alert - caTissue doesn't appear to use Hibernate for DEs. The mappings are incorrect
10
+ # and should not be used.
11
+ class HibernateMapping
12
+
13
+ attr_accessor :table
14
+
15
+ def initialize(klass)
16
+ hbm = hibernate_mapping(klass)
17
+ @table = hbm['table']
18
+ @attr_col_hash = {}
19
+ hbm['property'].each do |name, md|
20
+ @attr_col_hash[name.underscore.to_sym] = md['column']
21
+ end
22
+ end
23
+
24
+ def column(attribute)
25
+ @attr_col_hash[attribute]
26
+ end
27
+
28
+ private
29
+
30
+ HBM_DIR = File.join(File.dirname(__FILE__), '..', '..', '..', 'conf', 'annotation')
31
+
32
+ HBM_OPTS = { 'KeyAttr' => 'name' }
33
+
34
+ def hibernate_mapping(klass)
35
+ file = hibernate_mapping_file(klass)
36
+ conf = XmlSimple.xml_in(file, HBM_OPTS)
37
+ conf['class'][klass.name.demodulize]
38
+ end
39
+
40
+ def hibernate_mapping_file(klass)
41
+ dir = klass.java_class.name[/\w+/]
42
+ File.join(HBM_DIR, dir, "#{klass.name.demodulize}.hbm.xml")
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,28 @@
1
+ module CaTissue
2
+ module Annotation
3
+ # {CaTissue::Resource} annotation hook proxy mix-in.
4
+ module Proxy
5
+ # The hook proxy identifier is the hook identifier.
6
+ # This method delegates to the hook.
7
+ #
8
+ # @return [Integer] the hook identifier
9
+ def identifier
10
+ hook.identifier if hook
11
+ end
12
+
13
+ # The hook proxy identifier cannot be set directly. Assignment is a no-op.
14
+ #
15
+ # @param [Integer] value the (ignored) identifier value
16
+ def identifier=(value); end
17
+
18
+ # Sets the +id+ Java property to the hook identifier.
19
+ # This method must be called before saving an annotation that references this proxy.
20
+ def ensure_identifier_reflects_hook
21
+ if getId.nil? then
22
+ setId(hook.identifier)
23
+ logger.debug { "Set annotation proxy #{self} identifier to that of the hook entity #{hook.qp}." }
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,68 @@
1
+ require 'set'
2
+ require 'catissue/annotation/annotation'
3
+ require 'catissue/annotation/proxy'
4
+
5
+ module CaTissue
6
+ module Annotation
7
+ # Annotation hook proxy class mix-in.
8
+ module ProxyClass
9
+ # @return [AnnotatableClass] the hook class for this proxy
10
+ attr_reader :hook
11
+
12
+ # @param [Class] klass the proxy class
13
+ def self.extended(klass)
14
+ super
15
+ klass.class_eval { include Proxy }
16
+ end
17
+
18
+ def annotation_attributes
19
+ @ann_attrs ||= domain_attributes.compose { |attr_md| attr_md.type < Annotation }
20
+ end
21
+
22
+ # Sets this proxy's hook to the given class.
23
+ # Creates the proxy => hook attribute with the given hook => proxy inverse.
24
+ #
25
+ # @param [Class] klass the hook class
26
+ # @param [Symbol] inverse the hook class hook => proxy attribute
27
+ def set_hook(klass, inverse)
28
+ @hook = klass
29
+ # Make a new hook reference attribute.
30
+ attr_accessor(:hook)
31
+ # The attribute type is the given hook class.
32
+ add_attribute(:hook, klass)
33
+ # Setting one end of the hook <-> proxy association sets the other end.
34
+ set_attribute_inverse(:hook, inverse)
35
+ logger.debug { "Added #{klass.qp} annotation proxy => hook attribute with inverse #{klass.qp}.#{inverse}." }
36
+ end
37
+
38
+ # Adds each proxy => annotation reference as a dependent attribute.
39
+ def add_annotation_dependents
40
+ annotation_attributes.each_metadata do |attr_md|
41
+ attr_md.type.add_dependent_attributes
42
+ attr_md.type.proxy = self
43
+ end
44
+ annotation_attributes.each_metadata do |attr_md|
45
+ attr_md.type.add_dependent_attribute_closure
46
+ end
47
+ end
48
+
49
+ # Creates a reference attribute from this proxy to the given primary {Annotation} class.
50
+ #
51
+ # @param [Class] klass the annotation class
52
+ # @param [Symbol] inverse the annotation => proxy attribute
53
+ def create_annotation_attribute(klass, inverse)
54
+ # the new attribute symbol
55
+ attr = klass.name.demodulize.underscore.pluralize.to_sym
56
+ logger.debug { "Creating annotation proxy #{qp} attribute #{attr} to hold primary annotation #{klass.qp} instances..." }
57
+ # Define the access methods: the reader creates a new set on demand to hold the annotations.
58
+ attr_create_on_demand_accessor(attr) { Set.new }
59
+ # add the annotation collection attribute
60
+ add_attribute(attr, klass, :collection)
61
+ # make the hook attribute which delegates to this proxy
62
+ @hook.create_annotation_attribute(domain_module, attr)
63
+ # set the attribute inverse
64
+ set_attribute_inverse(attr, inverse)
65
+ end
66
+ end
67
+ end
68
+ end
@@ -13,13 +13,13 @@ module CaTissue
13
13
  # objects. This is used for testing a migration dry run. It is recommended that the trial run
14
14
  # protocol is set to a test protocol as well.
15
15
  SPECS = [
16
- [:input, "input", "Source file to migrate"],
16
+ [:input, "-i", "input", "Source file to migrate"],
17
17
  [:target, "-t", "--target CLASS", "Migration target class"],
18
18
  [:mapping, "-m", "--mapping FILE", "The input field => caTissue attribute mapping file"],
19
19
  [:shims, "-s", "--shims FILE[,FILE...]", Array, "Migration customization shim files to load"],
20
20
  [:bad, "-b", "--bad FILE", "Write each invalid record to the given file and continue migration"],
21
21
  [:unique, "-u", "--unique", "Make the migrated objects unique for testing"],
22
- [:offset, "--offset N", Integer, "Number of input records to skip before starting the migration"]
22
+ [:offset, "-o", "--offset N", Integer, "Number of input records to skip before starting the migration"]
23
23
  ]
24
24
 
25
25
  # Creates a {CaTissue::CLI::Migrate} command with the given standard command line specifications
@@ -11,7 +11,9 @@ module CaTissue
11
11
 
12
12
  private
13
13
 
14
- DB_MSG = "Verifying database access by searching for the pre-defined #{CaTissue::Site::DEF_SITE_NAME} Site..."
14
+ DEF_SITE = CaTissue::Site.default_site
15
+
16
+ DB_MSG = "Verifying database access by searching for the pre-defined #{DEF_SITE.name} Site..."
15
17
 
16
18
  # Runs the smoke test.
17
19
  def execute
@@ -23,7 +25,7 @@ module CaTissue
23
25
 
24
26
  def find_in_transit_site
25
27
  begin
26
- site = CaTissue::Site.new(:name => CaTissue::Site::DEF_SITE_NAME).find
28
+ site = DEF_SITE.find
27
29
  rescue Exception => e
28
30
  logger.error("caTissue database access was unsuccessful - #{e}:\n#{e.backtrace.qp}")
29
31
  puts "caTissue database access was unsuccessful - #{e}."
@@ -31,11 +33,11 @@ module CaTissue
31
33
  end
32
34
 
33
35
  if site then
34
- puts "The #{CaTissue::Site::DEF_SITE_NAME} Site was found with identifier #{site.identifier}."
36
+ puts "The #{DEF_SITE.name} Site was found with identifier #{site.identifier}."
35
37
  puts "Smoke test successful."
36
38
  exit 0
37
39
  else
38
- puts "The #{CaTissue::Site::DEF_SITE_NAME} Site was not found."
40
+ puts "The #{DEF_SITE.name} Site was not found."
39
41
  puts "Smoke test unsuccessful."
40
42
  exit 69 # service unavailable error status
41
43
  end
@@ -1,79 +1,93 @@
1
1
  require 'caruby/util/inflector'
2
+ require 'caruby/database/sql_executor'
2
3
  require 'caruby/database/persistence_service'
3
- require 'caruby/util/uniquifier'
4
+ require 'catissue/annotation/annotatable'
4
5
 
5
6
  module CaTissue
6
7
  module Annotation
7
8
  # An AnnotationService queries and saves CaTissue annotations.
8
9
  class AnnotationService < CaRuby::PersistenceService
9
- # The IdGenerator calls the caTissue entity manager to create a new identifier for
10
- # an annotation.
11
- class IdGenerator
12
- # Creates a new IdGenerator with the given caTissue entity_manager.
13
- def initialize(entity_manager)
14
- super()
15
- @entity_manager = entity_manager
16
- end
17
-
18
- # Returns a new identifier for the given annotation object.
19
- def next_identifier(annotation)
20
- logger.debug { "Generating identifier for annotation #{annotation}..." }
21
- id = @entity_manager.get_next_identifier_for_entity(annotation.class.qp).to_i
22
- # work-around caTissue bug - use a high number that won't conflict with the autogenerated range
23
- # cf. https://cabig-kc.nci.nih.gov/Biospecimen/forums/viewtopic.php?f=19&t=404&sid=786325c9c46503529a2b64f0b66fed0a
24
- if id.nil? or id.zero? then
25
- id = Uniquifier.qualifier
26
- logger.warn("Entity manager did not create annotation identifier; using id #{id}.")
27
- end
28
- id
29
- end
30
- end
31
-
32
10
  # Creates an AnnotationService for the given CaTissue::Database, service name and options.
33
11
  #
34
- # Supported options include the following:
35
- # * :anchor - the required anchor class
36
- # * :integration_service - the required IntegrationService
37
- # * :entity_manager - the required EntityManager
38
- # * +version+ - the optional caTissue version identifier
39
- def initialize(database, service_name, options)
40
- super(service_name, Options.get(:version, options))
12
+ # @param [CaTissue::Database] database the database
13
+ # @param [String] name the caTissue DE service name
14
+ # @param (see CaRuby::PersistenceService#initialize)
15
+ # @option opts :hook the required hook class
16
+ # @option opts :integration_service the required IntegrationService
17
+ # @option opts (see CaRuby::PersistenceService#initialize)
18
+ def initialize(database, name, opts)
19
+ super(name, opts)
41
20
  @database = database
42
- @anchor_class = Options.get(:anchor, options)
43
- @integration_service = Options.get(:integration_service, options)
44
- entity_manager = Options.get(:entity_manager, options)
45
- @id_generator = IdGenerator.new(entity_manager)
46
- end
47
-
48
- # Query the given domain object obj with the given attribute path. The query result is
49
- # an array of CaRuby::Annotation objects. Overrides {CaRuby::PersistenceService#query} to
50
- # delegate to the caTissue integration service when the penultimate search class is this
51
- # AnnotationService anchor class, e.g.:
52
- # query(CaTissue::SpecimenCollectionGroup.new(:name => 'Biobank_1_5'), :base_pathology_annotation)
53
- # or
54
- # query(CaTissue::ReceivedEventParameters.new(:user => user), :specimen_collection_group, :base_pathology_annotation)
55
- def query(obj, *path)
56
- # delegate path[0...-1] to database unless path.length < 2
57
- return @database.query(obj, *path[0...-1]).map { |fetched| query(fetched, path[-1]) }.flatten unless path.length < 2
58
- return super unless @anchor_class === obj.class
59
- # fetch the anchor objects if necessary
60
- return @database.query(obj).map { |fetched| query(fetched, *path) }.flatten if obj.identifier.nil?
61
- # obj is an anchor with an identifier; make a template
62
- template = obj.copy(:identifier)
63
- # delegate to the integration service to find the anchor annotations
64
- @integration_service.query(template, *path)
21
+ @database.add_persistence_service(self)
22
+ @int_svc = opts[:integration_service]
65
23
  end
66
24
 
67
- # Augments the CaRuby::PersistenceService create method to handle caTissue annotation service peculiarities,
68
- # e.g. assigning an identifier since assignment is not done automatically as is the case with the default
69
- # application service.
25
+ # Augments the {CaRuby::PersistenceService} create method to handle caTissue annotation
26
+ # service peculiarities, e.g.:
27
+ # * assigns the identifier, since assignment is not done automatically as is the case with the
28
+ # default application service
29
+ # * associate the annotation to the hook object
30
+ # * Save all referenced annotation objects
31
+ #
32
+ # This method can only be called on primary annotation objects. A _primary_ annotation
33
+ # is a top-level annotation which has a reference to the {Annotation#hook} which is
34
+ # being annotated.
35
+ #
36
+ # @param [Annotation] annotation the annotation object to create
37
+ # @return [Annotation] the annotation
70
38
  def create(annotation)
71
- annotation.identifier ||= @id_generator.next_identifier(annotation)
72
- super
73
- owner = annotation.owner
74
- @integration_service.associate(owner, annotation) if CaRuby::Annotatable === owner
39
+ logger.debug { "Creating annotation #{annotation.qp}..." }
40
+ # get the hook
41
+ hook = annotation.hook
42
+ # If no hook, then this is not a primary annotation. In that case, find a referenced
43
+ # primary annotation.
44
+ if hook then
45
+ time { create_primary_annotation(annotation, hook) }
46
+ else
47
+ create_secondary_annotation(annotation)
48
+ end
49
+ logger.debug { "Created annotation #{annotation}." }
75
50
  annotation
76
51
  end
52
+
53
+ private
54
+
55
+ # @param annotation (see #create)
56
+ # @param [Annotable] the annotatable object referenced by this annotation
57
+ def create_primary_annotation(annotation, hook)
58
+ # write the annotation records
59
+ create_annotation_object(annotation)
60
+ # Create the "cascaded" references.
61
+ annotation.class.save_dependent_attributes(annotation)
62
+ # If the annotation references a hook, then delegate to the integration service to associate
63
+ # the hook to the annotation.
64
+ @int_svc.associate(hook, annotation)
65
+ end
66
+
67
+ def create_secondary_annotation(annotation)
68
+ # the owner annotation
69
+ ownr = annotation.owner
70
+ if ownr.nil? then
71
+ raise AnnotationError.new("Cannot create secondary annotation #{annotation.qp} since it does not have an owner")
72
+ end
73
+ # creating the owner creates this secondary
74
+ create(ownr)
75
+ end
76
+
77
+ # @see #create
78
+ def create_annotation_object(annotation)
79
+ # can't create a proxy
80
+ if Proxy === annotation then
81
+ raise AnnotationError.new("#{annotation} annotation proxy create is not supported")
82
+ end
83
+ # The sequence generator next id.
84
+ annotation.identifier = EntityFacade.instance.next_identifier(annotation)
85
+ # Ensure that the proxy record is up-to-date.
86
+ annotation.ensure_proxy_reflects_hook
87
+
88
+ # Delegate to standard record create.
89
+ app_service.create_object(annotation)
90
+ end
77
91
  end
78
92
  end
79
93
  end
@@ -1,84 +1,25 @@
1
- require 'caruby/util/properties'
2
1
  require 'catissue/database/annotation/integration_service'
3
- require 'catissue/database/annotation/annotatable_service'
4
2
  require 'catissue/database/annotation/annotation_service'
5
- require 'catissue/database/annotation/entity_manager'
3
+ require 'catissue/database/annotation/entity_facade'
6
4
 
7
5
  module CaTissue
8
- module Annotation
9
- # An Annotator creates annotation services for annotatable and annotation classes.
10
- class Annotator
11
- def initialize(database)
12
- @database = database
13
- #the sole DE integration service, used by the annotation services
14
- @entity_manager = Annotation::EntityManager.instance
15
- @integration_service = Annotation::IntegrationService.new(@entity_manager)
16
- @anchor_svc_hash = {}
17
- @ann_mod_svc_hash = {}
18
- end
19
-
20
- # Returns the CaRuby::PersistenceService for the given klass, or nil if klass is neither
21
- # annotatable nor an annotation.
22
- def service(klass)
23
- annotatable_service(klass) or annotation_service(klass)
24
- end
25
-
26
- private
27
-
28
- # Returns the Annotation::AnnotatableService for the given klass, or nil if klass is not annotatable.
29
- def annotatable_service(klass)
30
- return @anchor_svc_hash[klass] ||= create_annotatable_service(klass) if JavaImport::AnnotatableClass === klass
31
- annotatable_service(klass.superclass) if klass.superclass
32
- end
33
-
34
- # Returns the Annotation::AnnotatorService for the given klass, or nil if klass is not an annotation.
35
- def annotation_service(klass)
36
- return @ann_mod_svc_hash[klass.annotation_module] ||= create_annotation_service(klass.annotation_module) if JavaImport::AnnotationClass === klass
37
- annotation_service(klass.superclass) if klass.superclass
38
- end
39
-
40
- def create_annotatable_service(klass)
41
- Annotation::AnnotatableService.new(@database, @database.persistence_service, @integration_service)
42
- end
43
-
44
- def create_annotation_service(mod)
45
- Annotation::AnnotationService.new(@database, mod.service, :anchor => mod.anchor_class,
46
- :integration_service => @integration_service, :entity_manager => @entity_manager)
47
- end
6
+ # An Annotator creates annotation services for annotatable and annotation classes.
7
+ class Annotator
8
+ attr_reader :integration_service
9
+
10
+ # Initializes a new Annotator for the given database.
11
+ #
12
+ # @param [CaTissue::Database] the database
13
+ def initialize(database)
14
+ @database = database
15
+ #the sole DE integration service, used by the annotation services
16
+ @integration_service = Annotation::IntegrationService.new
17
+ end
48
18
 
49
- # TODO - delete if obsolete
50
- # Returns the class => annotator hash from the given database's properties.
51
- def create_service_hashes(database)
52
- @anchor_svc_hash = {}
53
- @pkg_svc_hash = {}
54
- #the sole DE integration service, used by the annotation services
55
- integration_service = Annotation::IntegrationService.new
56
- entity_manager = Annotation::EntityManager.instance
57
- # the anchor class => { package => { attribute => type } } hash
58
- anchor_pkg_attrs_hash = CaTissue.access_properties[CaRuby::Domain::Properties::ANNOTATIONS_PROP]
59
- return {} if anchor_pkg_attrs_hash.nil?
60
- # the package => service name hash
61
- pkg_svc_nm_hash = CaTissue.access_properties[CaRuby::Domain::Properties::ANN_SVCS_PROP]
62
- if pkg_svc_nm_hash.nil? then
63
- raise CaRuby::ConfigurationError.new("Annotation service property missing: #{CaRuby::Domain::Properties::ANN_SVCS_PROP}")
64
- end
65
- # build the anchor => service and package => service hashes
66
- anchor_service = Annotation::AnnotatableService.new(database, database.persistence_service, integration_service)
67
- # make an annotatable service for each anchor and an annotator service for each package
68
- anchor_pkg_attrs_hash.each do |anchor_cls_nm, pkg_signatures_hash|
69
- anchor_class = CaTissue.const_get(anchor_cls_nm)
70
- @anchor_svc_hash[anchor_class] = anchor_service
71
- pkg_signatures_hash.each do |pkg, signatures|
72
- svc_nm = pkg_svc_nm_hash[pkg]
73
- if svc_nm.nil? then
74
- raise CaRuby::DatabaseError.new("Annotation service property value missing for package #{pkg} in property #{CaRuby::Domain::Properties::ANN_SVCS_PROP}")
75
- end
76
- @pkg_svc_hash[pkg] = Annotation::AnnotationService.new(database, svc_nm, :anchor => anchor_class,
77
- :integration_service => integration_service, :entity_manager => entity_manager)
78
- logger.debug { "Annotator service #{anchor_class.qp} #{svc_nm} created for attributes #{signatures.pp_s(:single_line)}" }
79
- end
80
- end
81
- end
19
+ # @param [String] name the service name
20
+ # @return [Annotation::AnnotationService] the annotation service
21
+ def create_annotation_service(name)
22
+ Annotation::AnnotationService.new(@database, name, :integration_service => @integration_service)
82
23
  end
83
24
  end
84
25
  end