caruby-core 1.4.9 → 1.5.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 (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