jruby-scala-collections 0.1.6-java

Sign up to get free protection for your applications and to get access to all the features.
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: []