caruby-core 1.4.9 → 1.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. data/History.md +48 -0
  2. data/lib/caruby/cli/command.rb +2 -1
  3. data/lib/caruby/csv/csv_mapper.rb +8 -8
  4. data/lib/caruby/database/persistable.rb +44 -65
  5. data/lib/caruby/database/persistence_service.rb +12 -9
  6. data/lib/caruby/database/persistifier.rb +14 -14
  7. data/lib/caruby/database/reader.rb +53 -51
  8. data/lib/caruby/database/search_template_builder.rb +9 -10
  9. data/lib/caruby/database/store_template_builder.rb +58 -58
  10. data/lib/caruby/database/writer.rb +96 -96
  11. data/lib/caruby/database.rb +19 -19
  12. data/lib/caruby/domain/attribute.rb +581 -0
  13. data/lib/caruby/domain/attributes.rb +615 -0
  14. data/lib/caruby/domain/dependency.rb +240 -0
  15. data/lib/caruby/domain/importer.rb +183 -0
  16. data/lib/caruby/domain/introspection.rb +176 -0
  17. data/lib/caruby/domain/inverse.rb +173 -0
  18. data/lib/caruby/domain/inversible.rb +1 -2
  19. data/lib/caruby/domain/java_attribute.rb +173 -0
  20. data/lib/caruby/domain/merge.rb +13 -10
  21. data/lib/caruby/domain/metadata.rb +141 -0
  22. data/lib/caruby/domain/mixin.rb +35 -0
  23. data/lib/caruby/domain/reference_visitor.rb +5 -3
  24. data/lib/caruby/domain.rb +340 -0
  25. data/lib/caruby/import/java.rb +29 -25
  26. data/lib/caruby/migration/migratable.rb +5 -5
  27. data/lib/caruby/migration/migrator.rb +19 -15
  28. data/lib/caruby/migration/resource_module.rb +1 -1
  29. data/lib/caruby/resource.rb +39 -30
  30. data/lib/caruby/util/collection.rb +94 -33
  31. data/lib/caruby/util/coordinate.rb +28 -2
  32. data/lib/caruby/util/log.rb +4 -4
  33. data/lib/caruby/util/module.rb +12 -28
  34. data/lib/caruby/util/partial_order.rb +9 -10
  35. data/lib/caruby/util/pretty_print.rb +46 -26
  36. data/lib/caruby/util/topological_sync_enumerator.rb +10 -4
  37. data/lib/caruby/util/transitive_closure.rb +2 -2
  38. data/lib/caruby/util/visitor.rb +1 -1
  39. data/lib/caruby/version.rb +1 -1
  40. data/test/lib/caruby/database/persistable_test.rb +1 -1
  41. data/test/lib/caruby/domain/domain_test.rb +14 -28
  42. data/test/lib/caruby/domain/inversible_test.rb +1 -1
  43. data/test/lib/caruby/import/java_test.rb +5 -0
  44. data/test/lib/caruby/migration/test_case.rb +0 -1
  45. data/test/lib/caruby/test_case.rb +9 -10
  46. data/test/lib/caruby/util/collection_test.rb +23 -5
  47. data/test/lib/caruby/util/module_test.rb +10 -14
  48. data/test/lib/caruby/util/partial_order_test.rb +16 -15
  49. data/test/lib/caruby/util/visitor_test.rb +1 -1
  50. data/test/lib/examples/galena/clinical_trials/migration/test_case.rb +1 -1
  51. metadata +16 -15
  52. data/History.txt +0 -44
  53. data/lib/caruby/domain/attribute_metadata.rb +0 -551
  54. data/lib/caruby/domain/java_attribute_metadata.rb +0 -183
  55. data/lib/caruby/domain/resource_attributes.rb +0 -565
  56. data/lib/caruby/domain/resource_dependency.rb +0 -217
  57. data/lib/caruby/domain/resource_introspection.rb +0 -160
  58. data/lib/caruby/domain/resource_inverse.rb +0 -151
  59. data/lib/caruby/domain/resource_metadata.rb +0 -155
  60. data/lib/caruby/domain/resource_module.rb +0 -370
  61. data/lib/caruby/yard/resource_metadata_handler.rb +0 -8
@@ -4,12 +4,14 @@ require 'caruby/util/log'
4
4
  require 'caruby/util/pretty_print'
5
5
  require 'caruby/util/validation'
6
6
  require 'caruby/util/collection'
7
+ require 'caruby/domain'
8
+ require 'caruby/domain/mixin'
7
9
  require 'caruby/domain/merge'
8
10
  require 'caruby/domain/reference_visitor'
9
11
  require 'caruby/database/persistable'
10
12
  require 'caruby/domain/inversible'
11
- require 'caruby/domain/resource_metadata'
12
- require 'caruby/domain/resource_module'
13
+ require 'caruby/domain/metadata'
14
+ require 'caruby/domain/mixin'
13
15
  require 'caruby/migration/migratable'
14
16
 
15
17
  module CaRuby
@@ -19,9 +21,9 @@ module CaRuby
19
21
  module Resource
20
22
  include Mergeable, Migratable, Persistable, Inversible
21
23
 
22
- # JRuby alert - Bug #5090 - JRuby 1.5 object_id no longer reserved, results in String value.
23
- # See http://jira.codehaus.org/browse/JRUBY-5090.
24
- # Work-around is to make a proxy object id.
24
+ # @quirk JRuby Bug #5090 - JRuby 1.5 object_id is no longer a reserved method, and results
25
+ # in a String value rather than an Integer (cf. http://jira.codehaus.org/browse/JRUBY-5090).
26
+ # Work-around is to make a proxy object id.
25
27
  #
26
28
  # @return [Integer] the object id
27
29
  def proxy_object_id
@@ -38,10 +40,9 @@ module CaRuby
38
40
 
39
41
  # Sets the default attribute values for this domain object and its dependents. If this Resource
40
42
  # does not have an identifier, then missing attributes are set to the values defined by
41
- # {ResourceAttributes#add_attribute_defaults}.
43
+ # {Attributes#add_attribute_defaults}.
42
44
  #
43
- # _Implementation Note_: subclasses should override the private {#add_defaults_local} method
44
- # rather than this method.
45
+ # Subclasses should override the private {#add_defaults_local} method rather than this method.
45
46
  #
46
47
  # @return [Resource] self
47
48
  def add_defaults
@@ -61,7 +62,7 @@ module CaRuby
61
62
  add_defaults_recursive
62
63
  end
63
64
 
64
- # Validates this domain object and its #{ResourceAttributes.unproxied_save_template_attributes}
65
+ # Validates this domain object and its #{Attributes.unproxied_savable_template_attributes}
65
66
  # for completeness prior to a database create operation.
66
67
  # An object without an identifer is valid if it contains a non-nil value for each mandatory property.
67
68
  # Objects which have an identifier or have already been validated are skipped.
@@ -69,18 +70,30 @@ module CaRuby
69
70
  # Subclasses should not override this method, but override the private {#local_validate} instead.
70
71
  #
71
72
  # @return [Resource] this domain object
72
- # @raise (see #local_validate)
73
+ # @raise (see #validate_local)
73
74
  def validate
74
75
  if identifier.nil? and not @validated then
75
76
  validate_local
76
77
  @validated = true
77
78
  end
78
- self.class.unproxied_save_template_attributes.each do |attr|
79
+ self.class.unproxied_savable_template_attributes.each do |attr|
79
80
  send(attr).enumerate { |dep| dep.validate }
80
81
  end
81
82
  self
82
83
  end
83
84
 
85
+ # Adds the default values to this object, if it is not already fetched, and its dependents.
86
+ #
87
+ # This method is intended for use only by the {#add_defaults} method.
88
+ def add_defaults_recursive
89
+ # Add the local defaults.
90
+ # The lazy loader is enabled in order to allow subclass add_defaults_local implementations
91
+ # to pick up load-on-demand references used to set defaults.
92
+ database.lazy_loader.enable { add_defaults_local }
93
+ # add dependent defaults
94
+ each_defaults_dependent { |dep| dep.add_defaults_recursive }
95
+ end
96
+
84
97
  # @return [Boolean] whether this domain object has {#searchable_attributes}
85
98
  def searchable?
86
99
  not searchable_attributes.nil?
@@ -104,11 +117,12 @@ module CaRuby
104
117
  return key_attrs if key_searchable?(key_attrs)
105
118
  end
106
119
 
107
- # Returns a new domain object with the given attributes copied from this domain object. The attributes
108
- # argument consists of either attribute Symbols or a single Enumerable consisting of Symbols.
109
- # The default attributes are the {ResourceAttributes#nondomain_attributes}.
120
+ # Returns a new domain object with the given attributes copied from this domain object.
121
+ # The attributes argument consists of either attribute Symbols or a single Enumerable
122
+ # consisting of Symbols.
123
+ # The default attributes are the {Attributes#nondomain_attributes}.
110
124
  #
111
- # @param [<Symbol>] attributes the attributes to copy
125
+ # @param [<Symbol>, (<Symbol>)] attributes the attributes to copy
112
126
  # @return [Resource] a copy of this domain object
113
127
  def copy(*attributes)
114
128
  if attributes.empty? then
@@ -121,7 +135,7 @@ module CaRuby
121
135
  end
122
136
 
123
137
  # Clears the given attribute value. If the current value responds to the +clear+ method,
124
- # then the current value is cleared. Otherwise, the value is set to {ResourceMetadata#empty_value}.
138
+ # then the current value is cleared. Otherwise, the value is set to {Metadata#empty_value}.
125
139
  #
126
140
  # @param [Symbol] attribute the attribute to clear
127
141
  def clear_attribute(attribute)
@@ -199,7 +213,7 @@ module CaRuby
199
213
  end
200
214
 
201
215
  # Returns an attribute => value hash for the specified attributes with a non-nil, non-empty value.
202
- # The default attributes are this domain object's class {ResourceAttributes#attributes}.
216
+ # The default attributes are this domain object's class {Attributes#attributes}.
203
217
  # Only non-nil attributes defined by this Resource are included in the result hash.
204
218
  #
205
219
  # @param [<Symbol>, nil] attributes the attributes to merge
@@ -244,7 +258,7 @@ module CaRuby
244
258
  end
245
259
 
246
260
  # Returns the attributes which are required for save. This base implementation returns the
247
- # class {ResourceAttributes#mandatory_attributes}. Subclasses can override this method
261
+ # class {Attributes#mandatory_attributes}. Subclasses can override this method
248
262
  # for domain object state-specific refinements.
249
263
  #
250
264
  # @return [<Symbol>] the required attributes for a save operation
@@ -327,7 +341,7 @@ module CaRuby
327
341
  end
328
342
 
329
343
  # Returns the difference between this Persistable and the other Persistable for the
330
- # given attributes. The default attributes are the {ResourceAttributes#nondomain_attributes}.
344
+ # given attributes. The default attributes are the {Attributes#nondomain_attributes}.
331
345
  #
332
346
  # @param [Resource] other the domain object to compare
333
347
  # @param [<Symbol>, nil] attributes the attributes to compare
@@ -434,7 +448,7 @@ module CaRuby
434
448
 
435
449
  # Prints this domain object's content and recursively prints the referenced content.
436
450
  # The optional selector block determines the attributes to print. The default is the
437
- # {ResourceAttributes#java_attributes}. The database lazy loader is disabled during
451
+ # {Attributes#java_attributes}. The database lazy loader is disabled during
438
452
  # the execution of this method. Thus, the printed content reflects the transient
439
453
  # in-memory object graph rather than the persistent content.
440
454
  #
@@ -503,14 +517,6 @@ module CaRuby
503
517
 
504
518
  protected
505
519
 
506
- # Adds the default values to this object, if it is not already fetched, and its dependents.
507
- def add_defaults_recursive
508
- # add the local defaults unless there is an identifier
509
- add_defaults_local
510
- # add dependent defaults
511
- each_defaults_dependent { |dep| dep.add_defaults_recursive }
512
- end
513
-
514
520
  # Returns the required attributes for this domain object which are nil or empty.
515
521
  #
516
522
  # This method is in protected scope to allow the +CaTissue+ domain module to
@@ -697,6 +703,9 @@ module CaRuby
697
703
  end
698
704
  end
699
705
 
706
+ # @param [Attribute] attr_md the attribute to set
707
+ # @param [Resource] ref the inverse value
708
+ # @param [Symbol] the inverse => self writer method
700
709
  def delegate_to_inverse_setter(attr_md, ref, writer)
701
710
  logger.debug { "Setting #{qp} #{attr_md} by setting the #{ref.qp} inverse attribute #{attr_md.inverse}..." }
702
711
  ref.send(writer, self)
@@ -718,7 +727,7 @@ module CaRuby
718
727
  # Returns the Java type of the given attribute, or nil if attribute is not a Java property attribute.
719
728
  def java_type(attribute)
720
729
  attr_md = self.class.attribute_metadata(attribute)
721
- attr_md.property_descriptor.property_type if JavaAttributeMetadata === attr_md
730
+ attr_md.property_descriptor.property_type if JavaAttribute === attr_md
722
731
  end
723
732
 
724
733
  # Executes the given block with the database lazy loader disabled, if any.
@@ -736,7 +745,7 @@ module CaRuby
736
745
  # oldval targets. If the matcher block is given, then that block is called on the sources
737
746
  # and targets. Otherwise, {Resource.match_all} is called.
738
747
  #
739
- # @param [AttributeMetadata] attr_md the attribute to match
748
+ # @param [Attribute] attr_md the attribute to match
740
749
  # @param newval the source value
741
750
  # @param oldval the target value
742
751
  # @yield [sources, targets] matches sources to targets
@@ -65,7 +65,14 @@ module Enumerable
65
65
  end
66
66
 
67
67
  # Returns a new Hash generated from this Enumerable with a block whose arguments include the enumerated item
68
- # and its index. nil or empty values are excluded.
68
+ # and its index. Every value which is {#nil_or_empty} is excluded.
69
+ #
70
+ # @example
71
+ # [1, 2, 3].to_compact_hash_with_index { |item, index| item + index } #=> { 1 => 1, 2 => 3, 3 => 5 }
72
+ # @yield [item, index] the hash value
73
+ # @yieldparam item the enumerated value
74
+ # @yieldparam index the enumeration index
75
+ # @return [Hash] this {Enumerable} converted to a hash by the given block
69
76
  def to_compact_hash_with_index
70
77
  hash = {}
71
78
  self.each_with_index do |item, index|
@@ -77,38 +84,38 @@ module Enumerable
77
84
  hash
78
85
  end
79
86
 
80
- # Returns whether this Enumerable iterates over at least one item.
81
- #
82
87
  # This method is functionally equivalent to +to_a.empty+ but is more concise and efficient.
88
+ #
89
+ # @return [Boolean] whether this Enumerable iterates over at least one item
83
90
  def empty?
84
91
  not any? { true }
85
92
  end
86
93
 
87
- # Returns the first enumerated item in this Enumerable, or nil if this Enumerable is empty.
88
- #
89
94
  # This method is functionally equivalent to +to_a.first+ but is more concise and efficient.
95
+ #
96
+ # @return the first enumerated item in this Enumerable, or nil if this Enumerable is empty
90
97
  def first
91
98
  detect { true }
92
99
  end
93
100
 
94
- # Returns the last enumerated item in this Enumerable, or nil if this Enumerable is empty.
95
- #
96
101
  # This method is functionally equivalent to +to_a.last+ but is more concise and efficient.
102
+ #
103
+ # @return the last enumerated item in this Enumerable, or nil if this Enumerable is empty
97
104
  def last
98
105
  detect { true }
99
106
  end
100
107
 
101
- # Returns the count of items enumerated in this Enumerable.
102
- #
103
108
  # This method is functionally equivalent to +to_a.size+ but is more concise and efficient
104
109
  # for an Enumerable which does not implement the {#size} method.
110
+ #
111
+ # @return [Integer] the count of items enumerated in this Enumerable
105
112
  def size
106
113
  inject(0) { |size, item| size + 1 }
107
114
  end
108
115
 
109
116
  alias :length :size
110
117
 
111
- # Prints the content of this Enumerable as a series using {Array#to_series}.
118
+ # @return [String] the content of this Enumerable as a series using {Array#to_series}
112
119
  def to_series(conjunction=nil)
113
120
  to_a.to_series
114
121
  end
@@ -157,12 +164,12 @@ module Enumerable
157
164
  # Note, however, that unlike select, filter does not return an Array.
158
165
  # The default filter block returns the passed item.
159
166
  #
167
+ # @example
168
+ # [1, nil, 3].filter.to_a #=> [1, 3]
160
169
  # @yield [item] filter the selection filter
161
170
  # @yieldparam item the collection member to filter
162
171
  # @return [Enumerable] the filtered result
163
- # @example
164
- # [1, nil, 3].filter.to_a #=> [1, 3]
165
- def filter(&filter) # :yields: item
172
+ def filter(&filter)
166
173
  Filter.new(self, &filter)
167
174
  end
168
175
 
@@ -238,6 +245,25 @@ module Enumerable
238
245
  Joiner.new(self, other)
239
246
  end
240
247
 
248
+ # Sorts this collection's members with a partial sort operator, i.e. the comparison returns -1, 0, 1 or nil.
249
+ # The resulting sorted order places each non-nil comparable items in the sort order. The order of nil
250
+ # comparison items is indeterminate.
251
+ #
252
+ # #example
253
+ # [Array, Numeric, Enumerable, Set].partial_sort #=> [Array, Numeric, Set, Enumerable]
254
+ # @return [Enumerable] the items in this collection in partial sort order
255
+ def partial_sort
256
+ unless block_given? then return partial_sort { |item1, item2| item1 <=> item2 } end
257
+ sort { |item1, item2| yield(item1, item2) or 1 }
258
+ end
259
+
260
+ # Sorts this collection's members with a partial sort operator on the results of applying the block.
261
+ #
262
+ # @return [Enumerable] the items in this collection in partial sort order
263
+ def partial_sort_by
264
+ partial_sort { |item1, item2| yield(item1) <=> yield(item2) }
265
+ end
266
+
241
267
  # @yield [item] the transformer on the enumerated items
242
268
  # @yieldparam item an enumerated item
243
269
  # @return [Enumerable] the mapped values excluding null values
@@ -247,6 +273,7 @@ module Enumerable
247
273
 
248
274
  private
249
275
 
276
+ # This Filter helper class applies a selection block to a base enumeration.
250
277
  class Filter
251
278
  include Enumerable
252
279
 
@@ -272,7 +299,7 @@ module Enumerable
272
299
  super
273
300
  end
274
301
 
275
- # Adds an item to the base Enumerable, if thif Filter's base supports it.
302
+ # Adds an item to the base Enumerable, if this Filter's base supports it.
276
303
  #
277
304
  # @param item the item to add
278
305
  # @return [Filter] self
@@ -297,6 +324,7 @@ module Enumerable
297
324
  end
298
325
  end
299
326
 
327
+ # This Transformer helper class applies a transformer block to a base enumeration.
300
328
  class Transformer
301
329
  include Enumerable
302
330
 
@@ -320,7 +348,9 @@ module Enumerable
320
348
  end
321
349
 
322
350
  # A MultiEnumerator iterates over several Enumerators in sequence. Unlike Array#+, MultiEnumerator reflects changes to the
323
- # underlying enumerators, e.g.:
351
+ # underlying enumerators.
352
+ #
353
+ # @example
324
354
  # a = [1, 2]
325
355
  # b = [4, 5]
326
356
  # ab = MultiEnumerator.new(a, b)
@@ -328,26 +358,32 @@ module Enumerable
328
358
  # a << 3; b << 6; ab.to_a #=> [1, 2, 3, 4, 5, 6]
329
359
  class MultiEnumerator
330
360
  include Enumerable
361
+
362
+ # @return [<Enumerable>] the enumerated collections
363
+ attr_reader :components
331
364
 
332
- # Creates a new MultiEnumerator on the given Enumerator enums.
365
+ # Initializes a new {MultiEnumerator} on the given components.
366
+ #
367
+ # @param [<Enumerable>] the component enumerators to compose
333
368
  def initialize(*enums)
334
369
  super()
335
- @enums = enums
336
- @enums.compact!
370
+ @components = enums
371
+ @components.compact!
337
372
  end
338
373
 
339
374
  # Iterates over each of this MultiEnumerator's Enumerators in sequence.
340
375
  def each
341
- @enums.each { |enum| enum.each { |item| yield item } }
376
+ @components.each { |enum| enum.each { |item| yield item } }
342
377
  end
343
378
  end
344
379
  end
345
380
 
346
- # The Collector utility module implements the {on} method to apply a block to
347
- # a collection transitive closure.
381
+ # The Collector utility implements the {on} method to apply a block to a collection
382
+ # transitive closure.
348
383
  module Collector
349
384
  # Collects the result of applying the given block to the given obj.
350
- # If obj is a collection, then collects the result of recursively calling this Collector on the enumerated members.
385
+ # If obj is a collection, then collects the result of recursively calling this
386
+ # Collector on the enumerated members.
351
387
  # If obj is nil, then returns nil.
352
388
  # Otherwise, calls block on obj and returns the result.
353
389
  #
@@ -355,6 +391,7 @@ module Collector
355
391
  # Collector.on([1, 2, [3, 4]]) { |n| n * 2 } #=> [2, 4, [6, 8]]]
356
392
  # Collector.on(nil) { |n| n * 2 } #=> nil
357
393
  # Collector.on(1) { |n| n * 2 } #=> 2
394
+ # @param obj the collection or item to enumerate
358
395
  def self.on(obj, &block)
359
396
  obj.collection? ? obj.map { |item| on(item, &block) } : yield(obj) unless obj.nil?
360
397
  end
@@ -366,12 +403,17 @@ class Object
366
403
  # item in this Enumerable.
367
404
  # * Otherwise, if this object is non-nil, then the the block is called on self.
368
405
  # * Otherwise, this object is nil and this method is a no-op.
406
+ #
407
+ # @yield [item] the block to apply to this object
408
+ # @yieldparam item the enumerated items, or this object if it is non-nil and not an Enumerable
369
409
  def enumerate(&block)
370
410
  Enumerable === self ? each(&block) : yield(self) unless nil?
371
411
  end
372
412
 
373
413
  # Returns an enumerator on this Object. This default implementation returns an Enumerable::Enumerator
374
414
  # on enumerate.
415
+ #
416
+ # @return [Enumerable] this object as an enumerable item
375
417
  def to_enum
376
418
  Enumerable::Enumerator.new(self, :enumerate)
377
419
  end
@@ -395,8 +437,9 @@ class Flattener
395
437
  obj.collection? ? obj.each { |item| on(item, &block) } : yield(obj) unless obj.nil?
396
438
  end
397
439
 
398
- # Creates a new Flattener on the given object. obj can be an Enumerable,
399
- # a single non-collection object or nil.
440
+ # Initializes a new Flattener on the given object.
441
+ #
442
+ # @param obj the Enumerable or non-collection object
400
443
  def initialize(obj)
401
444
  @base = obj
402
445
  end
@@ -416,9 +459,9 @@ class Flattener
416
459
  end
417
460
  end
418
461
 
419
- # ConditionalEnumerator applies a filter to another Enumerable, e.g.:
462
+ # ConditionalEnumerator applies a filter to another Enumerable.
463
+ # @example
420
464
  # ConditionalEnumerator.new([1, 2, 3]) { |i| i < 3 }.to_a #=> [1, 2]
421
- #
422
465
  class ConditionalEnumerator
423
466
  include Enumerable
424
467
 
@@ -456,13 +499,28 @@ module Hashable
456
499
  each { |key, value| yield key }
457
500
  end
458
501
 
459
- # @return [Object,nil] the key for which the block given to this method returns a non-nil, non-false value,
502
+ # @yield [key] the detector block
503
+ # @yieldparam key the hash key
504
+ # @return [Object, nil] the key for which the detector block returns a non-nil, non-false value,
460
505
  # or nil if none
506
+ # @example
507
+ # {1 => :a, 2 => :b, 3 => :c}.detect_key { |k| k > 1 } #=> 2
461
508
  def detect_key
462
509
  each_key { |key| return key if yield key }
463
510
  nil
464
511
  end
465
512
 
513
+ # @yield [value] the detector block
514
+ # @yieldparam value the hash value
515
+ # @return [Object, nil] the key for which the detector block returns a non-nil, non-false value,
516
+ # or nil if none
517
+ # @example
518
+ # {:a => 1, :b => 2, :c => 3}.detect_key_with_value { |v| v > 1 } #=> :b
519
+ def detect_key_with_value
520
+ each { |key, value| return key if yield value }
521
+ nil
522
+ end
523
+
466
524
  # @see Hash#each_value
467
525
  def each_value
468
526
  each { |key, value| yield value }
@@ -793,29 +851,32 @@ module Hashable
793
851
  # Combines hashes. See Hash#+ for details.
794
852
  class MultiHash
795
853
  include Hashable
854
+
855
+ # @return [<Hashable>] the enumerated hashes
856
+ attr_reader :components
796
857
 
797
858
  def initialize(*hashes)
798
859
  if hashes.include?(nil) then raise ArgumentError.new("MultiHash is missing a component hash.") end
799
- @hashes = hashes
860
+ @components = hashes
800
861
  end
801
862
 
802
863
  def [](key)
803
- @hashes.each { |hash| return hash[key] if hash.has_key?(key) }
864
+ @components.each { |hash| return hash[key] if hash.has_key?(key) }
804
865
  nil
805
866
  end
806
867
 
807
868
  def has_key?(key)
808
- @hashes.any? { |hash| hash.has_key?(key) }
869
+ @components.any? { |hash| hash.has_key?(key) }
809
870
  end
810
871
 
811
872
  def has_value?(value)
812
- @hashes.any? { |hash| hash.has_value?(value) }
873
+ @components.any? { |hash| hash.has_value?(value) }
813
874
  end
814
875
 
815
876
  def each
816
- @hashes.each_with_index do |hash, index|
877
+ @components.each_with_index do |hash, index|
817
878
  hash.each do |key, value|
818
- yield(key, value) unless (0...index).any? { |i| @hashes[i].has_key?(key) }
879
+ yield(key, value) unless (0...index).any? { |i| @components[i].has_key?(key) }
819
880
  end
820
881
  end
821
882
  self
@@ -1,4 +1,4 @@
1
- # JRuby alert - SyncEnumerator moved from generator to REXML in JRuby 1.5
1
+ # JRuby SyncEnumerator moved from generator to REXML in JRuby 1.5
2
2
  require 'rexml/document'
3
3
 
4
4
  # A Coordinate is a convenience Array wrapper class with aliased #x, #y and {#z} dimensions.
@@ -41,22 +41,48 @@ class Coordinate < Array
41
41
  self[2] = value
42
42
  end
43
43
 
44
+ # @param [Coordinate] other the coordinate to compare
44
45
  # @return [Boolean] whether other is a Coordinate and has the same content as this Coordinate
45
46
  def ==(other)
46
47
  super rescue false
47
48
  end
49
+
50
+ # @param (see #==)
51
+ # @return [Boolean] the comparison result
52
+ def <(other)
53
+ (self <=> other) < 0
54
+ end
55
+
56
+ # @param (see #==)
57
+ # @return (see #<)
58
+ def <=(other)
59
+ (self <=> other) <= 0
60
+ end
61
+
62
+ # @param (see #==)
63
+ # @return (see #<)
64
+ def >(other)
65
+ (self <=> other) > 0
66
+ end
67
+
68
+ # @param (see #==)
69
+ # @return (see #<)
70
+ def >=(other)
71
+ (self <=> other) >= 0
72
+ end
48
73
 
49
74
  # Returns the comparison of the highest dimension which differs from the other
50
75
  # coordinate, or zero if all dimensions are the same. This comparator sorts
51
76
  # coordinates in z-y-x order.
52
77
  # @example
53
78
  # Coordinate.new(2, 1) < Coordinate.new(1, 2) #=> true
79
+ # @param [Coordinate] other the coordinate to compare
54
80
  # @return [Integer] the high-to-low dimension comparison
55
81
  # @raise [ArgumentError] if this Coordinate dimension size Coordinate differs from that
56
82
  # of the other Dimension or any of the dimension values are nil
57
83
  # @raise [TypeError] if other is not a Coordinate
58
84
  def <=>(other)
59
- return true if equal?(other)
85
+ return 0 if equal?(other)
60
86
  raise TypeError.new("Can't compare #{self} with #{other} since it is not a Coordinate") unless Coordinate === other
61
87
  raise ArgumentError.new("Can't compare #{self} with #{other} since it has a different dimension count") unless size == other.size
62
88
  REXML::SyncEnumerator.new(self.reverse, other.reverse).each_with_index do |pair, index|
@@ -5,7 +5,7 @@ require 'caruby/util/collection'
5
5
 
6
6
  # @return [CaRuby::Logger] the global logger
7
7
  def logger
8
- CaRuby::Log::instance.logger
8
+ CaRuby::Log.instance.logger
9
9
  end
10
10
 
11
11
  module CaRuby
@@ -50,7 +50,7 @@ module CaRuby
50
50
  shift_age = Options.get(:shift_age, options, 4)
51
51
  shift_size = Options.get(:shift_size, options, 16 * 1048576)
52
52
  @logger = MultilineLogger.new(dev, shift_age, shift_size)
53
- @logger.level = Options.get(:debug, options) ? Logger::DEBUG : Logger::INFO
53
+ @logger.level = Options.get(:debug, options, ENV['DEBUG']) ? Logger::DEBUG : Logger::INFO
54
54
  @logger.info('============================================')
55
55
  @logger.info('Logging started.')
56
56
  @dev = dev
@@ -83,8 +83,8 @@ module CaRuby
83
83
  log_ndx = ARGV.index("--log") || ARGV.index("-l")
84
84
  if log_ndx then
85
85
  ARGV[log_ndx + 1]
86
- elsif ENV.has_key?("CA_LOG") then
87
- ENV["CA_LOG"]
86
+ elsif ENV.has_key?("LOG") then
87
+ ENV["LOG"]
88
88
  elsif defined?(DEF_LOG_FILE)
89
89
  DEF_LOG_FILE
90
90
  else
@@ -1,34 +1,18 @@
1
1
  class Module
2
- # Returns the class or module with name in the parent module.
3
- # If parent is nil, then name is looked up in the global context.
4
- # Otherwise, this method returns {#module_with_name}.
5
- def self.module_with_name(parent, name)
6
- return parent.module_with_name(name) if parent
7
- begin
8
- constant = eval(name)
9
- rescue Exception
10
- return
11
- end
12
- constant if constant.is_a?(Module)
13
- end
14
-
15
- # Returns the class or module with name in this module.
16
- # name can qualified by parent modules, e.g. +MyApp::Person+.
2
+ # Returns the class or module with the given name defined in this module.
3
+ # The name can qualified by parent modules, e.g. +MyApp::Person+.
17
4
  # If name cannot be resolved as a Module, then this method returns nil.
5
+ #
6
+ # @param [String] the class name
7
+ # @return [Module, nil] the class or module defined in this module, or nil if none
18
8
  def module_with_name(name)
19
- begin
20
- constant = name.split('::').inject(parent) { |parent, name| parent.const_get(name) }
21
- rescue Exception
22
- return
23
- end
24
- constant if constant.is_a?(Module)
9
+ name.split('::').inject(self) { |parent, part| parent.const_get(part) } rescue nil
25
10
  end
26
-
27
- # Returns the class with name in this module.
28
- # name can qualified by parent modules, e.g. +MyApp::Person+.
29
- # If name cannot be resolved as a Class, then this method returns nil.
30
- def class_with_name
31
- mod = module_with_name
32
- mod if mod.is_a?(Class)
11
+
12
+ # @example
13
+ # A::B.parent_module #=> A
14
+ # @return [Module] this module's definition context
15
+ def parent_module
16
+ Kernel.module_with_name(name.split('::')[0..-2].join('::'))
33
17
  end
34
18
  end
@@ -9,7 +9,6 @@
9
9
  # module Queued
10
10
  # attr_reader :queue
11
11
  # def <=>(other)
12
- # raise TypeError.new("Comparison argument is not another Queued item") unless Queued === other
13
12
  # queue.index(self) <=> queue.index(other) if queue.equal?(other.queue)
14
13
  # end
15
14
  # end
@@ -19,18 +18,18 @@
19
18
  # b < c #=> nil
20
19
  module PartialOrder
21
20
  include Comparable
22
-
21
+
23
22
  Comparable.instance_methods(false).each do |m|
24
23
  define_method(m.to_sym) do |other|
25
24
  self <=> other ? super : nil
26
25
  end
27
-
28
- # Returns true if other is an instance of this object's class and other == self,
29
- # false otherwise.
30
- def eql?(other)
31
- self.class === other and super
32
- end
33
-
34
- alias :== :eql?
35
26
  end
27
+
28
+ # @return [Boolean] true if other is an instance of this object's class and other == self,
29
+ # false otherwise
30
+ def eql?(other)
31
+ self.class === other and super
32
+ end
33
+
34
+ alias :== :eql?
36
35
  end