jruby-scala-collections 0.1.6-java

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 372437a75c45941268de8f6588b6925010105c57
4
+ data.tar.gz: 371dd0e796a9325e3c6ab6f7d3dc71ec6f7b5527
5
+ SHA512:
6
+ metadata.gz: 62c17f12c3772b26acb757041c2ae6e649afa5bba641b6212b7855a11b49cd062feea6e69a55ce0bd062fbef8da30c526757c235441d9091f92c14969259fd41
7
+ data.tar.gz: 3e67e2f4ae14c626342cc3b266d0eea983dcf0fb079d351763d745980544fbdc4a55eaaca80b23be6987b4d4604a240648e0da30f7c7d9f4300e4bd7cabbf25d
data/README.md ADDED
@@ -0,0 +1,83 @@
1
+ ## What is it?
2
+
3
+ A tiny interoperability library for passing JRuby/Scala collections back
4
+ and forth.
5
+
6
+ https://rubygems.org/gems/jruby-scala-collections
7
+
8
+ ## Installation
9
+
10
+ $ gem install jruby-scala-collections
11
+
12
+ With bundler:
13
+
14
+ ```gem "jruby-scala-collections", ">=0.1.1", require: "jruby/scala_support"```
15
+
16
+ Beware that you have to have ```scala-library.jar``` loaded before you
17
+ load ```jruby/scala_support```. In Rails this generally means it loading in ```config/boot.rb```.
18
+
19
+ ## How do you use it?
20
+
21
+ Each ```Object``` has two methods: ```#to_scala``` and ```#from_scala```.
22
+ These can be used to wrap JRuby/Scala collections.
23
+
24
+ Example:
25
+
26
+ gem 'jruby-scala-collections'
27
+ require 'jruby/scala_support'
28
+
29
+ r_arr = [1,2,3,4]
30
+ scala_arr = scala_object.do_stuff(r_arr.to_scala)
31
+ scala_arr.from_scala
32
+
33
+ * ```Array#to_scala``` becomes ```scala.collection.mutable.Buffer```
34
+ * ```Hash#to_scala``` becomes ```scala.collection.mutable.Map```
35
+ * ```Set#to_scala``` becomes ```scala.collection.mutable.Set```
36
+
37
+ Take node that even collections inside collections are wrapped:
38
+
39
+ > a = [1,[2,3],{4=>5}].to_scala
40
+ => #<Java::JrubyCollection::ListWrapper:0x768bdb>
41
+ > a.apply(1)
42
+ => #<Java::JrubyCollection::ListWrapper:0x884ab9>
43
+ > a.apply(2)
44
+ => #<Java::JrubyCollection::MapWrapper:0x1bb605>
45
+
46
+ From Scala side Ruby primitives are converted using default JRuby conversions
47
+ that are listed in https://github.com/jruby/jruby/wiki/CallingJavaFromJRuby section
48
+ "Conversion of Types".
49
+
50
+ So if you expect Array of Fixnums coming to your scala method, it should accept:
51
+
52
+ // Either
53
+ def scalaMethod(args: collection.mutable.Buffer[Long])
54
+ // Or
55
+ def scalaMethod(args: collection.Seq[Long])
56
+
57
+ It also adds ```#Some``` and ```None``` so you could pass values to Scala
58
+ methods:
59
+
60
+ scala_object.set(Some(3))
61
+ scala_object.get(None)
62
+
63
+ ## Disclaimer
64
+
65
+ This library was written by Artūras 'arturaz' Šlajus for personal
66
+ usage.
67
+
68
+ ## Contributing
69
+ ```#to_scala``` should work pretty well, however Ruby wrappers
70
+ in ```#from_scala``` may be missing methods. Patches are welcome.
71
+ jruby-scala-collections uses rubyspec and mspec to test that the behaviour
72
+ of the Ruby wrappers is correct.
73
+ Currently only a part of those tests pass. You can contribute by grabbing
74
+ any of the tests marked as `fails` in `rubyspec/tags/**/*_tags.txt`, marking it as
75
+ `focus` and implement the needed behaviour.
76
+ Guard is configured so that `bundle exec guard` runs all tests that have the focus tag.
77
+ If you want to run all tests that should be working, use `bundle exec mspec -G fails rubyspec`.
78
+ If you have implemented functionality, run `bundle exec mspec tag rubyspec` to update the list
79
+ of failing tests and check with a `git diff` that you haven't broken other functionality.
80
+
81
+ ### Development environment
82
+ In order to compile and package the project, an existing [SBT](http://www.scala-sbt.org/) installation must be available. Then just go to the
83
+ `ext` directory and execute `sbt dist`. Then go back to the upper directory and execute `gem build jruby-scala-collections.gemspec`
Binary file
@@ -0,0 +1,479 @@
1
+ require 'jruby'
2
+ require 'set'
3
+ require 'ext/collections.jar'
4
+
5
+ module JRuby::ScalaSupport
6
+ class ImmutableException < StandardError; end
7
+
8
+ module Common
9
+ include Enumerable
10
+
11
+ # Fake _target_ identity. This extends #is_a?, #kind_of?, #instance_of? on
12
+ # _target_ and #=== on _pretended_klass_.
13
+ #
14
+ # Example: fake_identity YourCustomHash, Hash
15
+ #
16
+ # Beware that #<, #<= and #ancestors on _target_ will still return that
17
+ # _target_ is not _pretended_klass_.
18
+ #
19
+ # @param [Class] target class that is being given fake identity
20
+ # @param [Class] pretended_klass class that target is pretending to be
21
+ def self.fake_identity(target, pretended_klass)
22
+ target.instance_eval do
23
+ [:is_a?, :kind_of?, :instance_of?].each do |method|
24
+ define_method(method) do |klass|
25
+ klass == pretended_klass ? true : super(klass)
26
+ end
27
+ end
28
+ end
29
+
30
+ (class << pretended_klass; self; end).instance_eval do
31
+ define_method(:===) do |object|
32
+ if object.is_a?(target)
33
+ true
34
+ else
35
+ super(object)
36
+ end
37
+ end
38
+ end
39
+ end
40
+
41
+ def initialize(raw)
42
+ @raw = raw
43
+ end
44
+
45
+ def scala_collection
46
+ @raw
47
+ end
48
+
49
+ def empty?
50
+ @raw.isEmpty
51
+ end
52
+
53
+ def size
54
+ @raw.size
55
+ end
56
+ end
57
+
58
+ module Map
59
+ module Common
60
+ include JRuby::ScalaSupport::Common
61
+
62
+ def [](key)
63
+ value = @raw.get(key)
64
+ if value == None
65
+ nil
66
+ else
67
+ value.get.from_scala
68
+ end
69
+ end
70
+
71
+ def keys
72
+ @raw.keys.toSeq.from_scala.to_a
73
+ end
74
+
75
+ def values
76
+ @raw.values.toSeq.from_scala.to_a
77
+ end
78
+
79
+ def value?(v)
80
+ values.include?(v)
81
+ end
82
+
83
+ alias_method :has_value?, :value?
84
+
85
+ def has_key?(key)
86
+ @raw.contains(key)
87
+ end
88
+
89
+ alias_method :key?, :has_key?
90
+ alias_method :member?, :has_key?
91
+ alias_method :include?, :has_key?
92
+
93
+ def key(val)
94
+ kv = find {|_,v| v == val }
95
+ kv && kv.first
96
+ end
97
+
98
+ def each
99
+ if block_given?
100
+ @raw.foreach do |tuple|
101
+ yield tuple._1.from_scala, tuple._2.from_scala
102
+ end
103
+ else
104
+ iterator = @raw.iterator
105
+
106
+ Enumerator.new do |yielder|
107
+ while iterator.hasNext
108
+ tuple = iterator.next
109
+ yielder << [tuple._1.from_scala, tuple._2.from_scala]
110
+ end
111
+ end
112
+ end
113
+ end
114
+
115
+ alias_method :each_pair, :each
116
+
117
+ def to_s
118
+ first = true
119
+ each_with_object("{") do |(key, value), str|
120
+ first ? first = false : str << ", "
121
+ str << "#{key.inspect}=>#{value.inspect}"
122
+ end << "}"
123
+ end
124
+
125
+ alias_method :inspect, :to_s
126
+
127
+ def as_json(options=nil)
128
+ each_with_object({}) do |(key, value), hash|
129
+ hash[key.as_json(options)] = value.as_json(options)
130
+ end
131
+ end
132
+
133
+ def eql?(other)
134
+ return true if self.equal? other
135
+
136
+ unless other.kind_of? Hash
137
+ return false unless other.respond_to? :to_hash
138
+ return other.eql?(self)
139
+ end
140
+
141
+ return false unless other.size == size
142
+
143
+ other.each do |k,v|
144
+
145
+ return false unless (entry = real_map.send(:findEntry,k)) && (entry.key.from_scala.eql?(k)) && (item = entry.value)
146
+
147
+ # Order of the comparison matters! We must compare our value with
148
+ # the other Hash's value and not the other way around.
149
+ return false unless item.eql?(v)
150
+ end
151
+
152
+ true
153
+ end
154
+
155
+ alias_method :==, :eql?
156
+
157
+ alias_method :length, :size
158
+
159
+ private
160
+ def real_map
161
+ case @raw
162
+ when scala.collection.Map::WithDefault then @raw.send(:underlying)
163
+ else @raw
164
+ end
165
+ end
166
+ end
167
+
168
+ class Immutable
169
+ include Common
170
+ JRuby::ScalaSupport::Common.fake_identity self, Hash
171
+
172
+ def []=(key, value)
173
+ raise ImmutableException,
174
+ "Cannot change #{key} on #{self} because it is immutable!"
175
+ end
176
+ end
177
+
178
+ class Mutable
179
+ include Common
180
+ JRuby::ScalaSupport::Common.fake_identity self, Hash
181
+
182
+ class << self
183
+ alias_method :previous_new, :new
184
+
185
+ def [](*args)
186
+ hash = new
187
+ if args.size == 1
188
+ obj = args.first
189
+ case obj
190
+ when Array, Hash then obj.each {|k,v| hash[k] = v}
191
+ else
192
+ raise "Don't yet know what to do with a #{obj.inspect}"
193
+ end
194
+ return hash
195
+ end
196
+
197
+ return new if args.empty?
198
+
199
+ if args.size & 1 == 1
200
+ raise ArgumentError, "Expected an even number, got #{args.length}"
201
+ end
202
+
203
+ i = 0
204
+ total = args.size
205
+
206
+ while i < total
207
+ hash[args[i]] = args[i+1]
208
+ i += 2
209
+ end
210
+
211
+ hash
212
+ end
213
+
214
+ def new(default_value=nil, &default_block)
215
+ raise ArgumentError, "You can only provide either a default value or a block" if default_value && default_block
216
+ h = scala.collection.mutable.HashMap.new
217
+ if default_block
218
+ h = h.with_default {|k| default_block.call(h,k) }
219
+ end
220
+ h = h.with_default_value(default_value) if default_value
221
+ previous_new(h)
222
+ end
223
+ end
224
+
225
+ def []=(key, value)
226
+ @raw.update(key, value.to_scala)
227
+ end
228
+ end
229
+ end
230
+
231
+ module Seq
232
+ module Common
233
+ include JRuby::ScalaSupport::Common
234
+
235
+ def [](index)
236
+ if index < 0
237
+ @raw.apply(size + index).from_scala
238
+ elsif index >= size
239
+ nil
240
+ else
241
+ @raw.apply(index).from_scala
242
+ end
243
+ end
244
+
245
+ def each
246
+ if block_given?
247
+ @raw.foreach do |item|
248
+ yield item.from_scala
249
+ end
250
+ else
251
+ iterator = @raw.iterator
252
+
253
+ Enumerator.new do |yielder|
254
+ yielder << iterator.next.from_scala while iterator.hasNext
255
+ end
256
+ end
257
+ end
258
+
259
+ def to_s
260
+ first = true
261
+ each_with_object("[") do |item, str|
262
+ first ? first = false : str << ", "
263
+ str << item.to_s
264
+ end << "]"
265
+ end
266
+ end
267
+
268
+ class Immutable
269
+ include Common
270
+ JRuby::ScalaSupport::Common.fake_identity self, Array
271
+
272
+ def []=(index, value)
273
+ raise ImmutableException,
274
+ "Cannot assign #{value} to index #{index} on #{self
275
+ }: collection immutable"
276
+ end
277
+ end
278
+
279
+ class Mutable
280
+ include Common
281
+ JRuby::ScalaSupport::Common.fake_identity self, Array
282
+
283
+ def []=(index, value)
284
+ if index < 0
285
+ @raw.update(size + index, value.to_scala)
286
+ elsif index >= size
287
+ (index - size + 1).times { @raw.send(:"+=", nil) }
288
+ self[index] = value
289
+ else
290
+ @raw.update(index, value.to_scala)
291
+ end
292
+ end
293
+ end
294
+ end
295
+
296
+ module Set
297
+ module Common
298
+ include JRuby::ScalaSupport::Common
299
+
300
+ def +(o)
301
+ (@raw + o).from_scala
302
+ end
303
+
304
+ def -(o)
305
+ (@raw - o).from_scala
306
+ end
307
+
308
+ def each
309
+ if block_given?
310
+ @raw.foreach { |item| yield item.from_scala }
311
+ else
312
+ Enumerator.new do |yielder|
313
+ each { |item| yielder << item }
314
+ end
315
+ end
316
+ end
317
+
318
+ def to_s
319
+ first = true
320
+ each_with_object("#<Set: {") do |item, str|
321
+ first ? first = false : str << ", "
322
+ str << item.to_s
323
+ end << "}>"
324
+ end
325
+ end
326
+
327
+ class Immutable
328
+ include Common
329
+ JRuby::ScalaSupport::Common.fake_identity self, Set
330
+
331
+ def add(o)
332
+ raise ImmutableException,
333
+ "Cannot add #{o} to #{self}: immutable collection"
334
+ end
335
+
336
+ def delete(o)
337
+ raise ImmutableException,
338
+ "Cannot delete #{o} from #{self}: immutable collection"
339
+ end
340
+ end
341
+
342
+ class Mutable
343
+ include Common
344
+ JRuby::ScalaSupport::Common.fake_identity self, Set
345
+
346
+ def add(o)
347
+ @raw.send(:"+=", o.to_scala)
348
+ self
349
+ end
350
+
351
+ def delete(o)
352
+ @raw.send(:"-=", o.to_scala)
353
+ self
354
+ end
355
+ end
356
+ end
357
+
358
+ class Tuple
359
+ include Common
360
+ Common.fake_identity self, Array
361
+
362
+ def initialize(raw, size)
363
+ super(raw)
364
+ @size = size
365
+ end
366
+
367
+ def size
368
+ @size
369
+ end
370
+
371
+ def empty?
372
+ false
373
+ end
374
+
375
+ def each
376
+ if block_given?
377
+ (0...size).each do |index|
378
+ yield self[index]
379
+ end
380
+ self
381
+ else
382
+ Enumerator.new do |yielder|
383
+ self.each { |item| yielder << item }
384
+ end
385
+ end
386
+ end
387
+
388
+ def to_s
389
+ first = true
390
+ each_with_object("[") do |item, str|
391
+ first ? first = false : str << ","
392
+ str << item.to_s
393
+ end << "]"
394
+ end
395
+
396
+ def [](index)
397
+ if index < 0
398
+ @raw.send("_#{size + index + 1}").from_scala
399
+ elsif index >= size
400
+ nil
401
+ else
402
+ @raw.send("_#{index + 1}").from_scala
403
+ end
404
+ end
405
+
406
+ def []=(index, value)
407
+ raise ImmutableException,
408
+ "Cannot assign #{value} to index #{index} on #{self
409
+ }: collection immutable"
410
+ end
411
+ end
412
+ end
413
+
414
+ # Scala <-> Ruby interoperability.
415
+ class Object
416
+ def to_scala
417
+ case self
418
+ when JRuby::ScalaSupport::Common
419
+ self.scala_collection
420
+ when Hash
421
+ Java::jruby.collection.MapWrapper.new(self)
422
+ when Set
423
+ Java::jruby.collection.SetWrapper.new(self)
424
+ when Array
425
+ Java::jruby.collection.ListWrapper.new(self)
426
+ when Symbol
427
+ Java::scala.Symbol.apply(to_s)
428
+ else
429
+ self.to_java
430
+ end
431
+ end
432
+
433
+ def from_scala
434
+ case self
435
+ when Java::jruby.collection.MapWrapper
436
+ self.rubyHash
437
+ when Java::scala.collection.mutable.Map
438
+ JRuby::ScalaSupport::Map::Mutable.new(self)
439
+ when Java::scala.collection.Map, Java::scala.collection.immutable.Map
440
+ JRuby::ScalaSupport::Map::Immutable.new(self)
441
+ when Java::jruby.collection.ListWrapper
442
+ self.rubyArray
443
+ when Java::scala.collection.mutable.Seq
444
+ JRuby::ScalaSupport::Seq::Mutable.new(self)
445
+ when Java::scala.collection.Seq, Java::scala.collection.immutable.Seq
446
+ JRuby::ScalaSupport::Seq::Immutable.new(self)
447
+ when Java::scala.Product
448
+ # Sometimes tuples have some wraping classes, like "#<Class:...>" on top
449
+ # of them. Some magic is needed to find actual tuple name.
450
+ match = nil
451
+ self.class.ancestors.find do |klass|
452
+ match = klass.to_s.match(/^Java::Scala::Tuple(\d+)$/)
453
+ ! match.nil?
454
+ end
455
+
456
+ if match
457
+ size = match[1].to_i
458
+ JRuby::ScalaSupport::Tuple.new(self, size)
459
+ else
460
+ self
461
+ end
462
+ when Java::jruby.collection.SetWrapper
463
+ self.rubySet
464
+ when Java::scala.collection.mutable.Set
465
+ JRuby::ScalaSupport::Set::Mutable.new(self)
466
+ when Java::scala.collection.Set, Java::scala.collection.immutable.Set,
467
+ JRuby::ScalaSupport::Set::Immutable.new(self)
468
+ when Java::scala.Symbol
469
+ self.name.to_sym
470
+ else
471
+ self
472
+ end
473
+ end
474
+ end
475
+
476
+ module Kernel
477
+ def Some(value); Java::scala.Some.new(value); end
478
+ None = Java::jruby.collection.Utils.None
479
+ end
metadata ADDED
@@ -0,0 +1,129 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jruby-scala-collections
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.6
5
+ platform: java
6
+ authors:
7
+ - Artūras Šlajus
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-01-09 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ version_requirements: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ requirement: !ruby/object:Gem::Requirement
21
+ requirements:
22
+ - - '>='
23
+ - !ruby/object:Gem::Version
24
+ version: '0'
25
+ prerelease: false
26
+ type: :development
27
+ - !ruby/object:Gem::Dependency
28
+ name: mspec
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ requirement: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - '>='
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
39
+ prerelease: false
40
+ type: :development
41
+ - !ruby/object:Gem::Dependency
42
+ name: guard
43
+ version_requirements: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ requirement: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - '>='
51
+ - !ruby/object:Gem::Version
52
+ version: '0'
53
+ prerelease: false
54
+ type: :development
55
+ - !ruby/object:Gem::Dependency
56
+ name: guard-rspec-jruby
57
+ version_requirements: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ requirement: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - '>='
65
+ - !ruby/object:Gem::Version
66
+ version: '0'
67
+ prerelease: false
68
+ type: :development
69
+ - !ruby/object:Gem::Dependency
70
+ name: guard-bundler
71
+ version_requirements: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ requirement: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - '>='
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ prerelease: false
82
+ type: :development
83
+ - !ruby/object:Gem::Dependency
84
+ name: guard-shell
85
+ version_requirements: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ requirement: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - '>='
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ prerelease: false
96
+ type: :development
97
+ description: Interoperability layer for passing JRuby & Scala collections back and forth. See README.md for more info.
98
+ email: arturas.slajus@gmail.com
99
+ executables: []
100
+ extensions: []
101
+ extra_rdoc_files: []
102
+ files:
103
+ - lib/ext/collections.jar
104
+ - lib/jruby/scala_support.rb
105
+ - README.md
106
+ homepage: http://github.com/arturaz/jruby-scala-collections
107
+ licenses: []
108
+ metadata: {}
109
+ post_install_message:
110
+ rdoc_options: []
111
+ require_paths:
112
+ - lib
113
+ required_ruby_version: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ required_rubygems_version: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - '>='
121
+ - !ruby/object:Gem::Version
122
+ version: '0'
123
+ requirements: []
124
+ rubyforge_project:
125
+ rubygems_version: 2.1.9
126
+ signing_key:
127
+ specification_version: 4
128
+ summary: Compiled against JRuby 1.7.4/Scala 2.10.2
129
+ test_files: []