Add all Ruby Hash methods to a Java Map by "add_ruby_methods"
-------------------------------------------------------------

                 Key: JRUBY-4528
                 URL: http://jira.codehaus.org/browse/JRUBY-4528
             Project: JRuby
          Issue Type: Wish
          Components: Java Integration
    Affects Versions: JRuby 1.5
            Reporter: Yoko Harada
         Attachments: add_ruby_methods.patch, AddHashMethodsToMap.java

Attached patch enables to use "add_ruby_methods" method to proxied all Java Map 
type objects. The new method adds all Ruby Hash methods to a Map type object. 
This patch and the new method will resolve the filed bug, JRUBY-4223, and 
alters my proposal, JRUBY-4314.

With this new method, we can directly manipulate Java Map objects, which is 
useful especially for embedders. For example, we can use merge! method against 
ConcurrentHashMap as in below:
{noformat}
ScriptingContainer container = new 
ScriptingContainer(LocalContextScope.SINGLETHREAD);
ConcurrentHashMap map1 = new ConcurrentHashMap();
map1.put("a", 100);
map1.put("b", 200);
Map map2 = new HashMap();
map2.put("b", 254);
map2.put("c", 300);
container.put("h1", map1);
container.put("h2", map2);
container.put("num", 0);
String script = 
    "rh = h1.add_ruby_methods\n" +
    "puts \"num: #{num}\"\n" +
    "rh.merge!(h2.add_ruby_methods) {|k,o,n| num += 1; o+n }";
container.runScriptlet(script);
Set<Map.Entry> entries = map1.entrySet();
for (Map.Entry entry : entries) {
    System.out.print(entry.getKey() + ": " + entry.getValue() + ", ");
}
{noformat}
The code produces values in ConcurrentHashMap:
{noformat}
b: 454, a: 100, c: 300,
{noformat}

Also, we can use the add_ruby_methods method on interpreter:
{noformat}
irb(main):004:0> require 'java'
=> true
irb(main):005:0> jhash = java.util.HashMap.new
=> {}
irb(main):006:0> jhash.put("1", 100)
=> nil
irb(main):007:0> jhash.put("2", 200)
=> nil
irb(main):008:0> jhash.inspect
=> "{2=200, 1=100}"
irb(main):009:0> rhash = jhash.add_ruby_methods
=> {"2"=>200, "1"=>100}
irb(main):010:0> rhash.inspect
=> "{\"2\"=>200, \"1\"=>100}"
irb(main):011:0> p rhash.values
[200, 100]
=> nil
irb(main):012:0> rhash.merge!({"2"=>222, "3"=>333}) 
=> {"3"=>333, "2"=>222, "1"=>100}
irb(main):013:0> jhash.inspect
=> "{3=333, 2=222, 1=100}"
{noformat}

To make this happen, I made small changes on org.jruby.RubyHash so that other 
class can override some methods. Tentatively, JavaHash class is located under 
org.jruby.embed.ji package, but probably, org.jruby.javasupport might be a 
better place since we can also apply the method to a Java object created in 
Ruby code.

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: 
http://jira.codehaus.org/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira

        

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply via email to