![]() |
|
|||||||||||
|
Update: 9 June 2007:
At long last, the first (real) beta version of
Cheri, the successor to JRBuilder,
has been released. You can download it from its new home at
RubyForge, or just type Update: 6 Mar 2007: JRuby 0.9.8 has been released! Get it now at the download page. I ended up incorporating pretty much all of the extended Java array features from the Cheri Java preview into JRuby 0.9.8 itself, though in a slightly different form, so download JRuby 0.9.8 and you'll have it. Cheri remains the new name of the JRBuilder/Bindery project, but I've been too busy the past few weeks to get new features out. Once I wrap up one more project for JRuby (a new and improved sprintf), I'll get back to it, so stay tuned to this space! Cheri is the new project name for the JRBuilder project, a builder for hierarchically-structured applications, especially (though not exclusively) geared towards use with JRuby. JRBuilder includes a Groovy-like SwingBuilder tool, as well as a proof-of-concept implementation of data binding called Bindery. Cheri (which I pronounce 'cherry', for reasons I'll explain below, but you may say 'sher-EE' if you prefer) is a major reworking and expansion of the JRBuilder code, opening up the architecture (if JRBuilder can be said to have any at all) to make it easy to add and extend features. While retaining its emphasis on Java-Ruby integration in the JRuby environment, Cheri aims to be a more broadly useful tool. While some pieces of Cheri/JRBuilder remain in scattered clumps on my garage floor as I finish rebuilding the engine (now where did I put that dang part?), other components are usable now. One of them I offer you today. One area that remains under-addressed in JRuby-Java integration is array creation and conversion. (This is a topical issue; just moments ago [as I write this] I ran across a post by Charles Oliver Nutter on jruby-dev that briefly mentioned needed array support, in the context of a broader discussion of Java integration in JRuby).
The Cheri::Java module
(download preview)
provides an easy-to-use and (I think) natural, Rubyesque solution to array creation and conversion.
It adds
The
Cheri accepts simple names for common types, such as
The conversion methods (
Much of Cheri's array/type functionality may (and should) eventually be implemented in JRuby directly, if not necessarily in the same form (though I hope Cheri's approach will serve at least as an inspiration, if not a model, for JRuby's implementation). Until then, it is available today in Cheri, so download it and give it a try! Stay tuned for Cheri's full builder platform release, coming out (possibly in stages) over the next couple of weeks. About the name Cheri: I originally (about a month ago) came up with the name Cherry, which I thought was clever because it's catchy, ala Groovy, and because it's in more or less same color family as Ruby, and because fruit names are all the rage these days (see Hpricot). A search for 'cherry ruby' on Google turned up no conflicting uses, just some wines and (of course) rubies. (I searched 'cherry java' as well, with the same lack of results.) It appeared to be a safe choice. Then, a couple of days ago, I started thinking about building a Gem, and headed over to RubyForge. Sure enough, they already had a Cherry (an XML parser with templating, sounds cool, though I haven't had a chance to try it). Well, by now I'm too invested in the name to let it go completely (the Cheri incarnation of JRBuilder's Bindery is B'ing), not to mention all those hours slaving over GIMP to create logos, though I had to redo some. So Cheri it is. (I looked it up; it is the Middle English spelling of Cherry.)
Please feel free to contact me with comments or suggestions. My email address is in
the download (in the code and the LICENSE file).
|
require 'cheri_java_preview' # Create a new, empty array of java.lang.Object, # length 10 arr = Array.java_array 10 => #<#<Class:01x111bfbc>:0x4310d0 @java_object=[Ljava.lang.Object;@1700391> # Set the first value to a java.lang.Byte, value 5 arr[0] = 5.java_byte => #<Cheri::Java::JByte:0xf894ce @java_object=5> # Create a 5 x 5 array of Java doubles, initialized to PI arr = Array.java_array :double, [5,5], 3.14159 => #<#<Class:01xdfcb47>:0x2d7440 @java_object=[[D@272961> arr[3][3] => 3.14159 # Create a Java primitive byte array from a Ruby array arr = [1,2,3,4,5,6,7,8].java_array :byte => #<#<Class:01xff9053>:0x15f157b @java_object=[B@497904> arr[5] => 6 # Set the first value to a Java primitive byte arr[0] = 99.java_byte => #<Cheri::Java::JByte:0x8d0b0f @java_object=99> # Create a 2-dimensional java.math.BigDecimal array from # a Ruby array arr = [[1,2,3],[4,5,6],[7,8,9]].java_array :decimal => #<#<Class:01xe33e18>:0x1d686c1 @java_object=[[Ljava.math.BigDecimal;@164b9b6> arr[2][2] => #<Cheri::Java::JBigDecimal:0x128edf2 @java_object=9> # Change the value at [1][1] to (java.math.BigDecimal) 99.99 arr[1][1] = 99.99.java_decimal => #<Cheri::Java::JBigDecimal:0x7b4703 @java_object=99.99> # Create an n-dimensional array from an irregular Ruby array arr = [1,[2,[3,[4,[5,[6,[7]]]]]]].java_array :string => #<#<Class:01x1a5af9f>:0x1b09282 @java_object=[[[[[[[Ljava.lang.String;@8ab08f> arr[0][0][0][0][0][0][0] => "1" # Supply a custom converter inline (silly example, just squares the values) JInteger = java.lang.Integer arr = [1,2,3].java_array(:Int) {|val| JInteger.new(val*val) } => #<#<Class:01x1c45731>:0x107f742 @java_object=[Ljava.lang.Integer;@171120a> arr[2] => 9 # Create a custom String->Date converter and add it to # Cheri's type-converter table, with a custom symbol JDate = java.util.Date # if we end up delegating to Cheri, we'll need the class name SDate = 'java.util.Date'.to_sym SimpleDateFormat = java.text.SimpleDateFormat format = SimpleDateFormat.new('yyyy-MM-dd') # create the proc, could use lambda{} as well, or Method.to_proc date_converter = Proc.new { |val| date = nil if val.kind_of?(String) begin date = format.parse(val) rescue end end if date date else # Not a (valid) date string, let Cheri try to handle it Cheri::Java::Types.convert_to_type(SDate,val) end } # add the proc to Cheri's type-converter table, with our custom symbol Cheri.add_type_converter(JDate,date_converter,:my_date) # now use it arr = ['2007-02-14','2000-09-18','1983-04-13'].java_array :my_date => #<#<Class:01x1956391>:0x1d382ab @java_object=[Ljava.util.Date;@643edd> arr[1] => #<JDate:0x127e2ee @java_object=Mon Sep 18 00:00:00 PST 2000> # You could also create the proc and add it in a single step: Cheri.add_type_converter(JDate, :my_date) do |val| date = nil if val.kind_of?(String) begin date = format.parse(val) rescue end end if date date else # Not a (valid) date string, let Cheri try to handle it Cheri::Java::Types.convert_to_type(SDate,val) end end arr = ['2007-02-14','2000-09-18','1983-04-13'].java_array :my_date # Some additional examples of creating/converting arrays # A new 5x5 String array arr = Array.java_array java.lang.String,5,5 arr = Array.java_array 'java.lang.String',[5,5] arr = Array.java_array :string,[5,5],99.99 # supplies a fill value # Convert various arrays # convert to java.lang.Object array of [Double,String,Boolean,Date] arr = [0.0,'hello',true,Time.now].java_array ruby_array = [ [ [1.0,2.0,3.0], [4.0,5.0,6.0] ], [ [1.1,2.1,3.1], [4.1,5.1,6.1] ], [ [1.2,2.2,3.2], [4.2,5.2,6.2] ] ] # 3x2x3 array of Java primitive float java_array = ruby_array.java_array :float # 3x2x3 array of java.lang.String java_array = ruby_array.java_array :string # 3x2x3 array of java.math.BigDecimal java_array = ruby_array.java_array :decimal # 4x3x3 array of java.math.BigDecimal, new space filled with 98.6 java_array = ruby_array.java_array :decimal, [4,3,3], 98.6 # The resulting java.math.BigDecimal array will look like this: [ [ [1.0,2.0,3.0], [4.0,5.0,6.0], [98.6,98.6,98.6] ], [ [1.1,2.1,3.1], [4.1,5.1,6.1], [98.6,98.6,98.6] ], [ [1.2,2.2,3.2], [4.2,5.2,6.2], [98.6,98.6,98.6] ], [ [98.6,98.6,98.6], [98.6,98.6,98.6], [98.6,98.6,98.6] ] ] |
| Copyright © 2007 Bill Dortch |