caruby-tissue 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. data/History.txt +4 -0
  2. data/LEGAL +5 -0
  3. data/LICENSE +22 -0
  4. data/README.md +44 -0
  5. data/bin/crtdump +31 -0
  6. data/bin/crtexample +18 -0
  7. data/bin/crtextract +47 -0
  8. data/bin/crtmigrate +17 -0
  9. data/bin/crtsmoke +27 -0
  10. data/examples/galena/README.md +53 -0
  11. data/examples/galena/bin/migrate.rb +42 -0
  12. data/examples/galena/bin/seed.rb +43 -0
  13. data/examples/galena/conf/extract/simple_fields.yaml +4 -0
  14. data/examples/galena/conf/migration/filter_fields.yaml +7 -0
  15. data/examples/galena/conf/migration/filter_migration.yaml +9 -0
  16. data/examples/galena/conf/migration/frozen_fields.yaml +11 -0
  17. data/examples/galena/conf/migration/frozen_migration.yaml +9 -0
  18. data/examples/galena/conf/migration/general_fields.yaml +42 -0
  19. data/examples/galena/conf/migration/general_migration.yaml +9 -0
  20. data/examples/galena/conf/migration/simple_fields.yaml +30 -0
  21. data/examples/galena/conf/migration/simple_migration.yaml +7 -0
  22. data/examples/galena/conf/migration/small_fields.yaml +24 -0
  23. data/examples/galena/conf/migration/small_migration.yaml +9 -0
  24. data/examples/galena/data/filter.csv +1 -0
  25. data/examples/galena/data/frozen.csv +1 -0
  26. data/examples/galena/data/general.csv +1 -0
  27. data/examples/galena/data/minimal.csv +1 -0
  28. data/examples/galena/data/simple.csv +1 -0
  29. data/examples/galena/data/small.csv +1 -0
  30. data/examples/galena/doc/CaTissue.html +93 -0
  31. data/examples/galena/doc/CaTissue/CollectionProtocolRegistration.html +181 -0
  32. data/examples/galena/doc/CaTissue/Participant.html +241 -0
  33. data/examples/galena/doc/CaTissue/SpecimenCollectionGroup.html +190 -0
  34. data/examples/galena/doc/CaTissue/StorageContainer.html +179 -0
  35. data/examples/galena/doc/CaTissue/TissueSpecimen.html +320 -0
  36. data/examples/galena/doc/Galena.html +290 -0
  37. data/examples/galena/doc/Galena/Seed.html +203 -0
  38. data/examples/galena/doc/Galena/Seed/Defaults.html +646 -0
  39. data/examples/galena/doc/_index.html +188 -0
  40. data/examples/galena/doc/class_list.html +36 -0
  41. data/examples/galena/doc/css/common.css +1 -0
  42. data/examples/galena/doc/css/full_list.css +53 -0
  43. data/examples/galena/doc/css/style.css +307 -0
  44. data/examples/galena/doc/file.README.html +108 -0
  45. data/examples/galena/doc/file_list.html +38 -0
  46. data/examples/galena/doc/frames.html +13 -0
  47. data/examples/galena/doc/index.html +108 -0
  48. data/examples/galena/doc/js/app.js +202 -0
  49. data/examples/galena/doc/js/full_list.js +149 -0
  50. data/examples/galena/doc/js/jquery.js +154 -0
  51. data/examples/galena/doc/method_list.html +179 -0
  52. data/examples/galena/doc/top-level-namespace.html +112 -0
  53. data/examples/galena/lib/README.html +33 -0
  54. data/examples/galena/lib/galena.rb +8 -0
  55. data/examples/galena/lib/galena/cli/seed.rb +43 -0
  56. data/examples/galena/lib/galena/migration/filter_shims.rb +43 -0
  57. data/examples/galena/lib/galena/migration/frozen_shims.rb +54 -0
  58. data/examples/galena/lib/galena/seed/defaults.rb +97 -0
  59. data/lib/catissue.rb +26 -0
  60. data/lib/catissue/cli/command.rb +51 -0
  61. data/lib/catissue/cli/example.rb +31 -0
  62. data/lib/catissue/cli/migrate.rb +60 -0
  63. data/lib/catissue/cli/smoke.rb +45 -0
  64. data/lib/catissue/database.rb +451 -0
  65. data/lib/catissue/database/annotation/annotatable_service.rb +25 -0
  66. data/lib/catissue/database/annotation/annotation_service.rb +79 -0
  67. data/lib/catissue/database/annotation/annotator.rb +84 -0
  68. data/lib/catissue/database/annotation/entity_manager.rb +10 -0
  69. data/lib/catissue/database/annotation/integration_service.rb +87 -0
  70. data/lib/catissue/database/controlled_value_finder.rb +43 -0
  71. data/lib/catissue/database/controlled_values.rb +162 -0
  72. data/lib/catissue/domain/abstract_domain_object.rb +8 -0
  73. data/lib/catissue/domain/abstract_position.rb +22 -0
  74. data/lib/catissue/domain/abstract_specimen.rb +288 -0
  75. data/lib/catissue/domain/abstract_specimen_collection_group.rb +25 -0
  76. data/lib/catissue/domain/address.rb +13 -0
  77. data/lib/catissue/domain/cancer_research_group.rb +11 -0
  78. data/lib/catissue/domain/capacity.rb +34 -0
  79. data/lib/catissue/domain/check_in_check_out_event_parameter.rb +19 -0
  80. data/lib/catissue/domain/collection_event_parameters.rb +13 -0
  81. data/lib/catissue/domain/collection_protocol.rb +177 -0
  82. data/lib/catissue/domain/collection_protocol_event.rb +108 -0
  83. data/lib/catissue/domain/collection_protocol_registration.rb +108 -0
  84. data/lib/catissue/domain/consent_tier_response.rb +13 -0
  85. data/lib/catissue/domain/consent_tier_status.rb +29 -0
  86. data/lib/catissue/domain/container.rb +234 -0
  87. data/lib/catissue/domain/container_position.rb +21 -0
  88. data/lib/catissue/domain/container_type.rb +131 -0
  89. data/lib/catissue/domain/department.rb +13 -0
  90. data/lib/catissue/domain/disposal_event_parameters.rb +13 -0
  91. data/lib/catissue/domain/embedded_event_parameters.rb +10 -0
  92. data/lib/catissue/domain/external_identifier.rb +22 -0
  93. data/lib/catissue/domain/frozen_event_parameters.rb +10 -0
  94. data/lib/catissue/domain/institution.rb +13 -0
  95. data/lib/catissue/domain/new_specimen_array_order_item.rb +35 -0
  96. data/lib/catissue/domain/order_details.rb +25 -0
  97. data/lib/catissue/domain/participant.rb +138 -0
  98. data/lib/catissue/domain/participant_medical_identifier.rb +38 -0
  99. data/lib/catissue/domain/password.rb +11 -0
  100. data/lib/catissue/domain/race.rb +11 -0
  101. data/lib/catissue/domain/received_event_parameters.rb +25 -0
  102. data/lib/catissue/domain/scg_event_parameters.rb +11 -0
  103. data/lib/catissue/domain/site.rb +30 -0
  104. data/lib/catissue/domain/specimen.rb +456 -0
  105. data/lib/catissue/domain/specimen_array.rb +47 -0
  106. data/lib/catissue/domain/specimen_array_content.rb +19 -0
  107. data/lib/catissue/domain/specimen_array_type.rb +20 -0
  108. data/lib/catissue/domain/specimen_characteristics.rb +20 -0
  109. data/lib/catissue/domain/specimen_collection_group.rb +412 -0
  110. data/lib/catissue/domain/specimen_event_parameters.rb +111 -0
  111. data/lib/catissue/domain/specimen_position.rb +38 -0
  112. data/lib/catissue/domain/specimen_protocol.rb +34 -0
  113. data/lib/catissue/domain/specimen_requirement.rb +143 -0
  114. data/lib/catissue/domain/storage_container.rb +204 -0
  115. data/lib/catissue/domain/storage_type.rb +82 -0
  116. data/lib/catissue/domain/transfer_event_parameters.rb +53 -0
  117. data/lib/catissue/domain/user.rb +100 -0
  118. data/lib/catissue/extract/command.rb +31 -0
  119. data/lib/catissue/extract/delta.rb +62 -0
  120. data/lib/catissue/extract/extractor.rb +99 -0
  121. data/lib/catissue/migration/migrator.rb +101 -0
  122. data/lib/catissue/migration/shims.rb +108 -0
  123. data/lib/catissue/migration/uniquify.rb +111 -0
  124. data/lib/catissue/resource.rb +84 -0
  125. data/lib/catissue/util/controlled_value.rb +29 -0
  126. data/lib/catissue/util/location.rb +116 -0
  127. data/lib/catissue/util/log.rb +30 -0
  128. data/lib/catissue/util/person.rb +31 -0
  129. data/lib/catissue/util/position.rb +54 -0
  130. data/lib/catissue/util/storable.rb +34 -0
  131. data/lib/catissue/util/storage_type_holder.rb +30 -0
  132. data/lib/catissue/version.rb +7 -0
  133. metadata +212 -0
@@ -0,0 +1,108 @@
1
+ require 'caruby/migration/migrator'
2
+
3
+ module CaTissue
4
+ shims SpecimenCollectionGroup, CollectionProtocolRegistration, SpecimenCharacteristics,
5
+ SpecimenEventParameters, CollectionEventParameters, ReceivedEventParameters
6
+
7
+ class SpecimenCollectionGroup
8
+ @@diagnosis_cv_finder = nil
9
+
10
+ # Sets this SpecimenCollectionGroup diagnosis ControlledValueFinder.
11
+ def self.diagnosis_cv_finder=(finder)
12
+ @@diagnosis_cv_finder = finder
13
+ end
14
+
15
+ # Returns the diagnosis controlled value as follows:
16
+ # * If CV lookup is disabled, then this method returns value.
17
+ # * Otherwise, if the value is remapped via a configuration remap file,
18
+ # then this method returns the remapped CV.
19
+ # * Otherwise, if the value is a valid CV, then this method returns value.
20
+ # * Otherwise, this method returns nil.
21
+ def self.diagnosis_controlled_value(value)
22
+ @@diagnosis_cv_finder.nil? ? value : @@diagnosis_cv_finder.controlled_value(value)
23
+ end
24
+
25
+ # Returns the {#diagnosis_controlled_value}.
26
+ def migrate_clinical_diagnosis(value, row)
27
+ SpecimenCollectionGroup.diagnosis_controlled_value(value)
28
+ end
29
+ end
30
+
31
+ class SpecimenCharacteristics
32
+ @@tissue_site_cv_finder = nil
33
+
34
+ # Sets this SpecimenCharacteristics tissue site ControlledValueFinder.
35
+ def self.tissue_site_cv_finder=(finder)
36
+ @@tissue_site_cv_finder = finder
37
+ end
38
+
39
+ # Returns the tissue site controlled value as follows:
40
+ # * If CV lookup is disabled, then this method returns value.
41
+ # * Otherwise, if the value is remapped via a configuration remap file,
42
+ # then this method returns the remapped CV.
43
+ # * Otherwise, if the value is a valid CV, then this method returns value.
44
+ # * Otherwise, this method returns nil.
45
+ #
46
+ # @return the caTissue tissue site permissible value
47
+ def self.tissue_site_controlled_value(value)
48
+ @@tissue_site_cv_finder.nil? ? value : @@tissue_site_cv_finder.controlled_value(value)
49
+ end
50
+
51
+ # Returns the {#tissue_site_controlled_value}.
52
+ def migrate_tissue_site(value, row)
53
+ standard_cv_tissue_site(value) or variant_cv_tissue_site(value)
54
+ end
55
+
56
+ private
57
+
58
+ # Returns the {#tissue_site_controlled_value}.
59
+ #
60
+ # @return the caTissue tissue site permissible value
61
+ def standard_cv_tissue_site(value)
62
+ SpecimenCharacteristics.tissue_site_controlled_value(value)
63
+ end
64
+
65
+ # Returns the {#tissue_site_controlled_value} which adds the 'NOS' suffix to a value
66
+ # without one or removes 'NOS' from a value with the suffix.
67
+ #
68
+ # @return the caTissue tissue site permissible value
69
+ def variant_cv_tissue_site(value)
70
+ # try an NOS suffix variation
71
+ variation = value =~ /, NOS$/ ? value[0...-', NOS'.length] : value + ', NOS'
72
+ cv = SpecimenCharacteristics.tissue_site_controlled_value(variation)
73
+ logger.warn("Migrator substituted tissue site #{cv} for #{value}.") if cv
74
+ cv
75
+ end
76
+ end
77
+
78
+ class SpecimenEventParameters
79
+ # Returns nil by default, since only SCGEventParameters have a SCG owner.
80
+ # {SCGEventParameters#migrate_specimen_collection_group} overrides this method.
81
+ #
82
+ # @return nil
83
+ def migrate_specimen_collection_group(scg, row)
84
+ nil
85
+ end
86
+ end
87
+
88
+ module SCGEventParameters
89
+ #@param [SpecimenCollectionGroup] scg the migrated owner SCG
90
+ # @return [SpecimenCollectionGroup] scg
91
+ # @see SpecimenEventParameters#migrate_specimen_collection_group
92
+ def migrate_specimen_collection_group(scg, row)
93
+ # unset the specimen parent if necessary
94
+ self.specimen = nil if specimen and scg
95
+ scg
96
+ end
97
+
98
+ # Returns the given Specimen spc unless this SCGEventParameters already has a SCG owner.
99
+ # A SCGEventParameters is preferentially set to a migrated SCG rather than a migrated
100
+ # Specimen.
101
+ #
102
+ #@param [Specimen] spc the migrated owner specimen
103
+ # @return [Specimen, nil] spc unless there is already a SCG owner
104
+ def migrate_specimen(spc, row)
105
+ spc unless specimen_collection_group
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,111 @@
1
+ require 'caruby/migration/uniquify'
2
+
3
+ module CaTissue
4
+ shims CollectionProtocol, Site, User, Container, ExternalIdentifier, ParticipantMedicalIdentifier,
5
+ CollectionProtocolRegistration, SpecimenCollectionGroup, Specimen
6
+
7
+ class CollectionProtocol
8
+ include CaRuby::Migratable::Unique
9
+
10
+ # Makes this CP's title unique.
11
+ def uniquify
12
+ self.title = self.short_title = uniquify_value(short_title)
13
+ end
14
+ end
15
+
16
+ class Site
17
+ include CaRuby::Migratable::Unique
18
+
19
+ # Makes this Site's name unique.
20
+ def uniquify
21
+ self.name = uniquify_value(name)
22
+ end
23
+ end
24
+
25
+ class CollectionProtocolRegistration
26
+ include CaRuby::Migratable::Unique
27
+
28
+ # Makes this CPR's PPI unique.
29
+ def uniquify
30
+ self.protocol_participant_identifier = uniquify_value(protocol_participant_identifier)
31
+ end
32
+ end
33
+
34
+ class Container
35
+ include CaRuby::Migratable::Unique
36
+
37
+ # Makes this Container's name unique.
38
+ def uniquify
39
+ self.name = uniquify_value(name)
40
+ end
41
+ end
42
+
43
+ class ContainerType
44
+ include CaRuby::Migratable::Unique
45
+
46
+ # Makes this ContainerType's name unique.
47
+ def uniquify
48
+ self.name = uniquify_value(name)
49
+ end
50
+ end
51
+
52
+ class StorageType
53
+ include CaRuby::Migratable::Unique
54
+
55
+ # Makes this StorageType and the ContainerTypes which it holds unique.
56
+ def uniquify
57
+ super
58
+ child_types.each { |ct| ct.uniquify if ContainerType === ct }
59
+ end
60
+ end
61
+
62
+ class SpecimenCollectionGroup
63
+ include CaRuby::Migratable::Unique
64
+
65
+ # Makes this SCG's SPN unique.
66
+ def uniquify
67
+ self.surgical_pathology_number = uniquify_value(surgical_pathology_number)
68
+ end
69
+ end
70
+
71
+ class Specimen
72
+ include CaRuby::Migratable::Unique
73
+
74
+ # Makes this Specimen's label unique.
75
+ def uniquify
76
+ self.label = uniquify_value(label.uniquify) if label
77
+ end
78
+ end
79
+
80
+ class ExternalIdentifier
81
+ include CaRuby::Migratable::Unique
82
+
83
+ # Makes this ExternalIdentifier's value unique.
84
+ def uniquify
85
+ self.value = uniquify_value(value)
86
+ end
87
+ end
88
+
89
+ class ParticipantMedicalIdentifier
90
+ include CaRuby::Migratable::Unique
91
+
92
+ # Makes this PMI's MRN unique.
93
+ def uniquify
94
+ self.medical_record_number = uniquify_value(medical_record_number)
95
+ end
96
+ end
97
+
98
+ class User
99
+ include CaRuby::Migratable::Unique
100
+
101
+ # Makes this User's login id and email address unique.
102
+ # The result is in the form _name___suffix_+@test.com+
103
+ # where:
104
+ # * _name_ is the name prefix portion of the original email address
105
+ # * _suffix_ is a unique number
106
+ def uniquify
107
+ email = email_address ||= self.login_name || return
108
+ self.login_name = self.email_address = uniquify_value(email[/[^@]+/]) + '@test.com'
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,84 @@
1
+ require 'caruby/resource'
2
+ require 'caruby/domain/resource_module'
3
+
4
+ module CaTissue
5
+ extend CaRuby::ResourceModule
6
+
7
+ # The module included by all CaTissue domain classes.
8
+ module Resource
9
+ include CaRuby::Resource
10
+
11
+ # @param [Resource] other the domain object to compare
12
+ # @param [<Symbol>] attributes the attributes to compare
13
+ # @return [Boolean} whether each of the given attribute values either equals the
14
+ # respective other attribute value or one of the values is nil or 'Not Specified'
15
+ def tolerant_match?(other, attributes)
16
+ attributes.all? { |attr| Resource.tolerant_value_match?(send(attr), other.send(attr)) }
17
+ end
18
+
19
+ # Returns the CaTissue::Database which stores this object.
20
+ def database
21
+ @@database ||= Database.instance
22
+ end
23
+
24
+ protected
25
+
26
+ # Returns the required attributes which are nil for this domain object.
27
+ # Overrides the CaRuby::Resource method to handle the following bug:
28
+ #
29
+ # caTissue alert - Bug #67: AbstractSpecimen.setActivityStatus
30
+ # is a no-op. The Specimen activityStatus property is incorrectly pulled
31
+ # up to AbstractSpecimen. AbstractSpecimen.activityStatus is marked as
32
+ # mandatory, since it is required for Specimen. However, it is not
33
+ # mandatory, and in fact can't be set, for SpecimenRequirement.
34
+ # Work-around is to add special code to exclude activityStatus from
35
+ # the caRuby SpecimenRequirement missing mandatory attributes validation
36
+ # check.
37
+ def missing_mandatory_attributes
38
+ invalid = super
39
+ # Special case: AbstractSpecimen.setActivityStatus is a no-op.
40
+ if invalid.include?(:activity_status) and CaTissue::SpecimenRequirement === self then
41
+ invalid.delete(:activity_status)
42
+ end
43
+ invalid
44
+ end
45
+
46
+ private
47
+
48
+ # The unspecified value.
49
+ UNSPECIFIED = 'Not Specified'
50
+
51
+ # @return whether the given value equals the other value or one of the values is nil or 'Not Specified'
52
+ def self.tolerant_value_match?(value, other)
53
+ value == other or unpsecified_value?(value) or unpsecified_value?(other)
54
+ end
55
+
56
+ # @return whether the given value equals nil or {Resource.UNSPECIFIED}
57
+ def self.unpsecified_value?(value)
58
+ value.nil? or value == UNSPECIFIED
59
+ end
60
+
61
+ # Adds the given domain class to the CaTissue CaRuby::ResourceModule.
62
+ def self.included(klass)
63
+ CaTissue.add_class(klass)
64
+ end
65
+ end
66
+
67
+ # The required include mix-in module.
68
+ @mixin = Resource
69
+
70
+ # The required Java package name.
71
+ @java_package = 'edu.wustl.catissuecore.domain'
72
+
73
+ # Load the domain class definitions.
74
+ dir = File.join(File.dirname(__FILE__), 'domain')
75
+ load_dir(dir)
76
+ end
77
+
78
+ module JavaLogger
79
+ # caTissue alert - the caTissue logger must be initialized before caTissue objects are created.
80
+ # The logger at issue is the caTissue client logger, not the caTissue server logger nor
81
+ # the caRuby logger. The caTissue logger facade class is edu.wustl.common.util.logger.Logger,
82
+ # which is wrapped in Ruby as EduWustlCommonUtilLogger::Logger. TODO - isolate and report.
83
+ Java::EduWustlCommonUtilLogger::Logger.configure("")
84
+ end
@@ -0,0 +1,29 @@
1
+ require 'caruby/util/controlled_value'
2
+
3
+ module CaTissue
4
+ class ControlledValue < CaRuby::ControlledValue
5
+
6
+ PUBLIC_ID_ALIAS_MAP = {:tissue_site => 'Tissue_Site_PID', :clinical_diagnosis => 'Clinical_Diagnosis_PID'}
7
+
8
+ # Returns the standard public id string for the given public_id_or_alias.
9
+ def self.standard_public_id(public_id_or_alias)
10
+ PUBLIC_ID_ALIAS_MAP[public_id_or_alias.to_sym] or public_id_or_alias.to_s
11
+ end
12
+
13
+ attr_accessor :identifier, :public_id
14
+
15
+ attr_reader :identifier
16
+
17
+ def parent_identifier
18
+ parent.identifier if parent
19
+ end
20
+
21
+ def public_id=(public_id_or_alias)
22
+ @public_id = self.class.standard_public_id(public_id_or_alias)
23
+ end
24
+
25
+ def to_s
26
+ "#{value}"
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,116 @@
1
+ require 'caruby/util/coordinate'
2
+ require 'caruby/util/validation'
3
+
4
+ module CaTissue
5
+ # A Location is a non-Resource utility class which represents a Container row and column.
6
+ #
7
+ # Location does not capture the occupant; therefore, changing a location coordinate value alone does not
8
+ # change the storage assignment of an occupant.
9
+ class Location
10
+ include Comparable
11
+
12
+ attr_accessor :container, :coordinate
13
+
14
+ define_attribute_alias(:holder, :container)
15
+
16
+ # @param [{Symbol => Object}] params the location fields
17
+ # @option [Integer] params :in the container holding this location
18
+ # @option [Coordinate, (Integer, Integer)] params :at the location coordinate, expressed as either
19
+ # a Coordinate or a (column, row) array
20
+ # @return the new Location
21
+ def initialize(params=nil)
22
+ Options.validate(params, INIT_OPTS)
23
+ @container = Options.get(:in, params)
24
+ coord = Options.get(:at, params, Coordinate.new)
25
+ # turn an :at Array value into a Coordinate
26
+ if Array === coord and not Coordinate === coord then
27
+ coord = Coordinate.new(*coord)
28
+ end
29
+ validate_coordinate(coord)
30
+ @coordinate = coord
31
+ end
32
+
33
+ # @return this location's zero-based first dimension value
34
+ def column
35
+ @coordinate.x
36
+ end
37
+
38
+ # Sets this location's column to the given zero-based value.
39
+ def column=(value)
40
+ @coordinate.x = value
41
+ end
42
+
43
+ # @return this location's zero-based second dimension value
44
+ def row
45
+ @coordinate.y
46
+ end
47
+
48
+ # Sets this location's row to the given zero-based value.
49
+ def row=(value)
50
+ @coordinate.y = value
51
+ end
52
+
53
+ # @return [Boolean] whether other is a Location and has the same content as this Location
54
+ def ==(other)
55
+ super rescue false
56
+ end
57
+
58
+ # @param [Location] other the position to compare
59
+ # @return (see Coordinate#<=>)
60
+ # @raise [ArgumentError] if other is not an Location
61
+ def <=>(other)
62
+ raise ArgumentError.new("Can't compare #{qp} to #{other.qp}") unless @container and Location === other
63
+ unless container == other.container then
64
+ raise ArgumentError.new("Can't compare #{qp} in container #{container} to #{other.qp} in container #{other.container}")
65
+ end
66
+ @coordinate <=> other.coordinate
67
+ end
68
+
69
+ # @return [Location, nil] a new Location at the next slot in this Location's {#container},
70
+ # or nil if there are no more locations
71
+ def succ
72
+ self.class.new(:in => container, :at => @coordinate).succ! rescue nil
73
+ end
74
+
75
+ # Sets this Location to the next slot in this Location's {#container}.
76
+ #
77
+ # @raise [IndexError] if the next slot exceeds the container capacity
78
+ # @return self
79
+ def succ!
80
+ raise IndexError.new("Location #{qp} container not set") unless @container
81
+ raise IndexError.new("Location #{qp} coordinate not set") unless @coordinate
82
+ c = column.succ % @container.capacity.columns
83
+ r = c.zero? ? row.succ : row
84
+ unless r < container.capacity.rows then
85
+ raise IndexError.new("Location #{[c, r].qp} exceeds #{@container} container capacity #{container.capacity.bounds}")
86
+ end
87
+ @coordinate.x = c
88
+ @coordinate.y = r
89
+ self
90
+ end
91
+
92
+ def to_s
93
+ ctr_s = @container.print_class_and_id if @container
94
+ coord_s = @coordinate.to_s if @coordinate
95
+ content_s = "{#{ctr_s}#{coord_s}}" if ctr_s or coord_s
96
+ "#{print_class_and_id}{#{content_s}"
97
+ end
98
+
99
+ alias :inspect :to_s
100
+
101
+ alias :qp :to_s
102
+
103
+ private
104
+
105
+ INIT_OPTS = [:in, :at].to_set
106
+
107
+ # @param [CaRuby::Coordinate] coord the coordinate to validate
108
+ # @raise [IndexError] if the coordinate exceeds the container bounds
109
+ def validate_coordinate(coord)
110
+ bnds = @container && @container.bounds
111
+ if bnds and coord >= bnds then
112
+ raise IndexError.new("Location #{coord} exceeds container #{@container} dimensions #{bnds}")
113
+ end
114
+ end
115
+ end
116
+ end