gravitext-util 1.6.b.0-java → 1.6.b.1-java

Sign up to get free protection for your applications and to get access to all the features.
data/History.rdoc CHANGED
@@ -1,3 +1,9 @@
1
+ === 1.6.b.1 (2012-2-7)
2
+ * Reworked UniMap Ruby extension: UniMap.is_a?( Hash ) with Hash
3
+ behavior including interop with string or symbol keys, to_json
4
+ support, improved performance.
5
+ * IOUtils, tests fixes for 1.9 mode
6
+
1
7
  === 1.6.b.0 (2012-1-29)
2
8
  * New jruby IOUtils, sample extension, and perf test for optimizing
3
9
  text-intensive interop.
data/Manifest.txt CHANGED
@@ -16,4 +16,4 @@ test/test_concurrent.rb
16
16
  test/test_ioutils.rb
17
17
  test/test_perftest.rb
18
18
  test/test_unimap.rb
19
- lib/gravitext-util/gravitext-util-1.6.b.0.jar
19
+ lib/gravitext-util/gravitext-util-1.6.b.1.jar
data/Rakefile CHANGED
@@ -4,4 +4,7 @@ require 'rubygems'
4
4
  require 'bundler/setup'
5
5
  require 'rjack-tarpit'
6
6
 
7
- RJack::TarPit.new( 'gravitext-util' ).define_tasks
7
+ RJack::TarPit.new( 'gravitext-util' ) do |tp|
8
+ tp.rdoc_destinations <<
9
+ 'dekellum@rubyforge.org:/var/www/gforge-projects/gravitext/gravitext-util'
10
+ end
@@ -14,22 +14,22 @@
14
14
  # permissions and limitations under the License.
15
15
  #++
16
16
 
17
- module Gravitext
17
+ require 'gravitext-util/version'
18
18
 
19
- module HTMap
19
+ # Magic loader hook -> HTMapService
20
+ require 'com/gravitext/jruby/HTMap'
20
21
 
21
- import 'com.gravitext.htmap.Key'
22
- import 'com.gravitext.htmap.UniMap'
22
+ module Gravitext::HTMap
23
23
 
24
- # Extension to com.gravitext.htmap.UniMap providing convenience
25
- # methods, including ruby accessors for keys registered in
26
- # UniMap::KEY_SPACE
27
- class UniMap
24
+ import 'com.gravitext.htmap.Key'
25
+ import 'com.gravitext.htmap.UniMap'
28
26
 
29
- # Types requiring explicit construction on set
30
- EXPLICIT_CTOR_TYPES = [ Java::java.lang.Integer,
31
- Java::java.lang.Double,
32
- Java::java.lang.Float ]
27
+ # Extension to com.gravitext.htmap.UniMap providing convenience
28
+ # methods, including ruby accessors for keys registered in
29
+ # UniMap::KEY_SPACE, and for ruby Hash and JSON compatibility.
30
+ class UniMap
31
+
32
+ class << self
33
33
 
34
34
  # Create a new key in UniMap::KEY_SPACE. Useful for ruby-only keys
35
35
  # or for keys passed as parameters to Java.
@@ -38,42 +38,199 @@ module Gravitext
38
38
  # :vtype<~java_class>:: Java class value type (default: java.lang.Object)
39
39
  # ==== Returns
40
40
  # com.gravitext.htmap.Key
41
- def self.create_key( name, vtype = Java::java.lang.Object )
41
+ def create_key( name, vtype = Java::java.lang.Object )
42
42
  KEY_SPACE.create_generic( name, vtype.java_class )
43
43
  end
44
44
 
45
- # Define accessors for each key currently in the KEY_SPACE. To
46
- # define accessors for keys defined in java, statically reference
47
- # the containing class before calling this method. As Ruby's
48
- # define_method is not likely thread safe, invoke during
49
- # initialization in advance of starting threaded execution. May
50
- # be called multiple times.
51
- def self.define_accessors
45
+ # Define class constants and accessors for each key currently in
46
+ # the KEY_SPACE.
47
+ #
48
+ # To define accessors for keys defined in java, statically
49
+ # reference the containing class before calling this method. As
50
+ # Ruby's define_method is not likely thread safe, invoke during
51
+ # initialization in advance of starting threaded execution.
52
+ # May be called multiple times.
53
+ def define_accessors
54
+
55
+ klist = []
56
+ khash = {}
52
57
  KEY_SPACE.keys.each do |key|
53
58
 
59
+ klist[ key.id ] = key.name.to_sym
60
+
61
+ khash[ key.name ] = key
62
+ khash[ key.name.to_sym ] = key
63
+
64
+ const = key.name.upcase
65
+ if const_defined?( const )
66
+ cval = const_get( const )
67
+ if cval != key
68
+ fail "Constant #{key} already set to incompatible value #{cval}"
69
+ end
70
+ else
71
+ const_set( const, key )
72
+ end
73
+
54
74
  getter = key.name.downcase
55
75
  unless method_defined?( getter )
56
- define_method( getter ) { get( key ) }
76
+ class_eval <<-RUBY
77
+ def #{getter}
78
+ get_k( #{const} )
79
+ end
80
+ RUBY
57
81
  end
58
82
 
59
83
  setter = getter + '='
60
84
  unless method_defined?( setter )
61
- vtype = key.value_type
62
- ctype = EXPLICIT_CTOR_TYPES.find { |ct| vtype == ct.java_class }
63
- if ctype
64
- define_method( setter ) do |value|
65
- set( key, ( ctype.new( value ) if value ) )
85
+ class_eval <<-RUBY
86
+ def #{setter}( value )
87
+ set_k( #{const}, value )
66
88
  end
67
- else
68
- define_method( setter ) do |value|
69
- set( key, value )
70
- end
71
- end
89
+ RUBY
72
90
  end
73
91
 
74
92
  end
93
+
94
+ @key_list = klist.freeze # key name symbols array indexed by key.id
95
+ @key_hash = khash.freeze # Hash of symbols,strings to Key
96
+ end
97
+
98
+ # Return cached symbol for the specified key (8bit optimized).
99
+ # Must have define_accessors for the key first.
100
+ def key_to_symbol( key )
101
+ @key_list.at( key.id )
102
+ end
103
+
104
+ # Return Key for specified string name or symbol (8bit optimized)
105
+ # Must have define_accessors for the key first.
106
+ def str_to_key( str )
107
+ @key_hash[ str ]
75
108
  end
76
109
 
110
+ # Recursive UniMap#deep_hash implementation
111
+ def deep_hash( m )
112
+ case m
113
+ when UniMap
114
+ m.inject( {} ) do |o, (k, v)|
115
+ o[ key_to_symbol( k ) ] = deep_hash( v )
116
+ o
117
+ end
118
+ when Array
119
+ m.map { |v| deep_hash( v ) }
120
+ else
121
+ m
122
+ end
123
+ end
124
+
125
+ end
126
+
127
+ # Set key to value, where key may be a Key, String, or Symbol.
128
+ # Returns prior value or nil.
129
+ def set( key, value )
130
+ unless key.is_a?( Key )
131
+ k = UniMap.str_to_key( key )
132
+ unless k
133
+ raise IndexError, "No Key named #{key.inspect} in UniMap.KEY_SPACE"
134
+ end
135
+ key = k
136
+ end
137
+ set_k( key, value )
138
+ end
139
+
140
+ # Set key<Key> to value, returning prior value or nil.
141
+ def set_k( key, value )
142
+ HTMapHelper.set_map( self, key, value )
143
+ end
144
+
145
+ alias :[]= :set
146
+
147
+ # Get key value or nil, where key may be a Key, String, or Symbol
148
+ def get( key )
149
+ key = UniMap.str_to_key( key ) unless key.is_a?( Key )
150
+ key && get_k( key )
151
+ end
152
+
153
+ # Get Key value or nil
154
+ def get_k( key )
155
+ HTMapHelper.get_map( self, key )
156
+ end
157
+
158
+ alias :[] :get
159
+
160
+ # Remove the specified key, where key may be a Key, String, or
161
+ # Symbol. Returning old value or nil.
162
+ def remove( key )
163
+ key = UniMap.str_to_key( key ) unless key.is_a?( Key )
164
+ key && HTMapHelper.remove_map( self, key )
165
+ end
166
+
167
+ alias :delete :remove
168
+
169
+ # Is this key set, not nil, where key may be a Key, String, or
170
+ # Symbol.
171
+ def has_key?( key )
172
+ key = UniMap.str_to_key( key ) unless key.is_a?( Key )
173
+ key && contains_key( key )
174
+ end
175
+
176
+ alias :include? :has_key?
177
+ alias :key? :has_key?
178
+ alias :member? :has_key?
179
+
180
+ # Calls block with (Key, value) for each non-nil value
181
+ def each( &block )
182
+ HTMapHelper.unimap_each( self, &block )
183
+ end
184
+
185
+ # Return self as array of [ key.to_sym, value ] arrays
186
+ def to_a
187
+ map { |key,val| [ UniMap.key_to_symbol( key ), val ] }
188
+ end
189
+
190
+ # Returns self as Hash, with symbols for keys
191
+ def to_hash
192
+ h = {}
193
+ each do |key,val|
194
+ h[ UniMap.key_to_symbol( key ) ] = val
195
+ end
196
+ h
197
+ end
198
+
199
+ # Like to_hash but converts all nested UniMaps to hashes as well.
200
+ def deep_hash
201
+ UniMap.deep_hash( self )
202
+ end
203
+
204
+ # Merge other (Hash or UniMap) and return new UniMap. Any nil
205
+ # values from other Hash will result in removing the associated
206
+ # key.
207
+ def merge( other )
208
+ clone.merge!( other )
209
+ end
210
+
211
+ # Merge other (Hash or UniMap) values to self. Any nil values from
212
+ # other Hash will result in removing key from self.
213
+ def merge!( other )
214
+ other.each do |k,v|
215
+ set( k, v )
216
+ end
217
+ self
218
+ end
219
+
220
+ # To JSON, in form supported by JSON module. Note that this only
221
+ # works if you also require 'json' yourself.
222
+ def to_json(*args)
223
+ to_hash.to_json(*args)
224
+ end
225
+
226
+ # Override: this is a Hash as well.
227
+ def kind_of?( klass )
228
+ ( klass == Hash ) || super
229
+ end
230
+
231
+ # Override: this is a Hash as well.
232
+ def is_a?( klass )
233
+ ( klass == Hash ) || super
77
234
  end
78
235
 
79
236
  end
@@ -16,7 +16,7 @@
16
16
 
17
17
  module Gravitext
18
18
  module Util
19
- VERSION = '1.6.b.0'
19
+ VERSION = '1.6.b.1'
20
20
 
21
21
  LIB_DIR = File.dirname(__FILE__) # :nodoc:
22
22
  end
data/pom.xml CHANGED
@@ -4,7 +4,7 @@
4
4
  <groupId>com.gravitext</groupId>
5
5
  <artifactId>gravitext-util</artifactId>
6
6
  <packaging>jar</packaging>
7
- <version>1.6.b.0</version>
7
+ <version>1.6.b.1</version>
8
8
  <name>Gravitext Utilities</name>
9
9
  <url>http://gravitext.com/oss/gravitext-util</url>
10
10
 
data/test/test_ioutils.rb CHANGED
@@ -35,14 +35,16 @@ class TestIOUtils < MiniTest::Unit::TestCase
35
35
 
36
36
  assert_instance_of( String, ts.string )
37
37
  # IF to UTF-8 bytes, will be longer than 300
38
- assert_operator( ts.string.length, :>, 300 )
38
+ assert_length( ts.string, 300 )
39
39
 
40
40
  assert_instance_of( String, ts.string_sequence )
41
- assert_operator( ts.string_sequence.length, :>, 300 )
41
+ assert_length( ts.string_sequence, 300 )
42
42
 
43
- if JRUBY_VERSION =~ /^1.7/
44
- assert_instance_of( String, ts.char_buffer )
45
- assert_instance_of( String, ts.char_buffer_sequence )
43
+ if JRUBY_VERSION =~ /^1.7/ && RUBY_VERSION =~ /^1.9/
44
+ # Skipping these due to changing nature (have seen these asserts
45
+ # work, and not)
46
+ # assert_instance_of( String, ts.char_buffer )
47
+ # assert_instance_of( String, ts.char_buffer_sequence )
46
48
  else
47
49
  # In Jruby < 1.7, CharBuffer isn't converted to String until
48
50
  # to_s
@@ -51,23 +53,24 @@ class TestIOUtils < MiniTest::Unit::TestCase
51
53
  assert_equal( 'java.nio.HeapCharBuffer',
52
54
  ts.char_buffer_sequence.java_class.name )
53
55
  end
54
- assert_operator( ts.char_buffer.to_s.length, :>, 300 )
55
- assert_operator( ts.char_buffer_sequence.to_s.length, :>, 300 )
56
+ assert_length( ts.char_buffer.to_s, 300 )
57
+ assert_length( ts.char_buffer_sequence.to_s, 300 )
56
58
 
57
- assert_operator( ts.byte_list.to_s.length, :>, 300 )
59
+ assert_length( ts.byte_list.to_s, 300 )
58
60
 
59
61
  s = String.from_java_bytes( ts.bytes )
60
62
  assert_instance_of( String, s )
61
- assert_operator( s.length, :>, 300 )
63
+ s.force_encoding( "UTF-8" ) if s.respond_to?( :force_encoding )
64
+ assert_length( s.to_s, 300 )
62
65
  end
63
66
 
64
67
  def test_ruby_sampler
65
68
  rs = RubySampler.new( 300, 2 )
66
69
  assert_instance_of( String, rs.char_buffer_to_ruby )
67
- assert_operator( rs.char_buffer_to_ruby.length, :>, 300 )
70
+ assert_length( rs.char_buffer_to_ruby, 300 )
68
71
 
69
72
  assert_instance_of( String, rs.string_to_ruby )
70
- assert_operator( rs.string_to_ruby.length, :>, 300 )
73
+ assert_length( rs.string_to_ruby, 300 )
71
74
  end
72
75
 
73
76
  def test_ruby_sample_helper
@@ -75,10 +78,19 @@ class TestIOUtils < MiniTest::Unit::TestCase
75
78
  rs = RubySampleHelper
76
79
 
77
80
  assert_instance_of( String, rs.char_buffer_to_ruby( ts ) )
78
- assert_operator( rs.char_buffer_to_ruby( ts ).length, :>, 300 )
81
+ assert_length( rs.char_buffer_to_ruby( ts ), 300 )
79
82
 
80
83
  assert_instance_of( String, rs.string_to_ruby( ts ) )
81
- assert_operator( rs.string_to_ruby( ts ).length, :>, 300 )
84
+ assert_length( rs.string_to_ruby( ts ), 300 )
85
+ end
86
+
87
+ def assert_length( str, char_length )
88
+ if RUBY_VERSION =~ /^1.9/
89
+ assert_operator( str.bytesize, :>, char_length )
90
+ assert_operator( str.length , :==, char_length )
91
+ else
92
+ assert_operator( str.length , :>, char_length )
93
+ end
82
94
  end
83
95
 
84
96
  end
data/test/test_unimap.rb CHANGED
@@ -20,17 +20,20 @@
20
20
  require File.join( File.dirname( __FILE__ ), "setup" )
21
21
 
22
22
  require 'gravitext-util'
23
+ require 'json'
23
24
 
24
25
  class TestUniMap < MiniTest::Unit::TestCase
25
26
  include Gravitext::HTMap
26
27
 
27
- TEST_KEYS = [ [ 'int_key', Java::java.lang.Integer, 33 ],
28
- [ 'str_key', Java::java.lang.String, "string" ],
29
- [ 'cseq_key', Java::java.lang.CharSequence, "other" ],
30
- [ 'list_key', Java::java.util.List, [ 1, 2, 3 ] ],
31
- [ 'date_key', Java::java.util.Date, Time.now ],
32
- [ 'dbl_key', Java::java.lang.Double, 3.1415 ],
33
- [ 'flt_key', Java::java.lang.Float, 1.5625 ] ] #exact
28
+ TEST_KEYS = [ [ 'int', Java::java.lang.Integer, 33 ],
29
+ [ 'str', Java::java.lang.String, "string" ],
30
+ [ 'cseq', Java::java.lang.CharSequence, "other" ],
31
+ [ 'date', Java::java.util.Date, Time.now ],
32
+ [ 'dbl', Java::java.lang.Double, 3.1415 ],
33
+ [ 'flt', Java::java.lang.Float, 1.5625 ], #exact
34
+ [ 'list', Java::java.util.List, [ 1, 2, 3 ] ],
35
+ [ 'sub', Java::com.gravitext.htmap.UniMap, UniMap.new ],
36
+ [ 'any', Java::java.lang.Object, { :foo => 'bar' } ] ]
34
37
 
35
38
  WRONG_TYPE_VALUE = Java::java.lang.RuntimeException.new
36
39
 
@@ -42,29 +45,34 @@ class TestUniMap < MiniTest::Unit::TestCase
42
45
 
43
46
  LOG = RJack::SLF4J[ name ]
44
47
 
48
+ def test_define_accessors
49
+ UniMap.define_accessors
50
+ pass( "define accessors can be called repeatedly." )
51
+ end
52
+
45
53
  ## Manual tests
46
54
 
47
55
  # Full integer test for demonstration
48
- def test_int_key
56
+ def test_int
49
57
  c = UniMap.new
50
- assert_nil( c.int_key )
51
- c.int_key = 7
52
- assert_equal( 7, c.int_key )
53
- c.int_key = nil
54
- assert_nil( c.int_key )
55
- assert_raises NameError, NativeException do
56
- c.int_key = WRONG_TYPE_VALUE
58
+ assert_nil( c.int )
59
+ c.int = 7
60
+ assert_equal( 7, c.int )
61
+ c.int = nil
62
+ assert_nil( c.int )
63
+ assert_raises( TypeError ) do
64
+ c.int = WRONG_TYPE_VALUE
57
65
  end
58
66
  end
59
67
 
60
68
  # Java.util.Date comparison is tricky
61
- def test_date_key
69
+ def test_date
62
70
  c = UniMap.new
63
- c.date_key = now = Time.now
64
- assert( c.date_key.equals( now ) )
71
+ c.date = now = Time.now
72
+ assert( c.date.equals( now ) )
65
73
  end
66
74
 
67
- # Define test_<type_key> for all not manually defined above
75
+ # Define test_<key> for all not manually defined above
68
76
  TEST_KEYS.each do |name, vtype, test_value, key|
69
77
  get = name
70
78
  set = name + '='
@@ -74,13 +82,14 @@ class TestUniMap < MiniTest::Unit::TestCase
74
82
  c = UniMap.new
75
83
  assert_nil( c.send( get ) )
76
84
  assert_nil( c.send( set, test_value ) )
85
+ assert_equal( test_value, c.set( key, test_value ) )
77
86
  assert_equal( test_value, c.send( get ) )
78
87
  assert_equal( test_value, c.get( key ) )
79
88
  assert_equal( test_value, c.send( set, nil ) )
80
89
  assert_nil( c.send( get ) )
81
- assert_raises NameError, NativeException do
90
+ assert_raises( TypeError ) do
82
91
  c.send( set, WRONG_TYPE_VALUE )
83
- end
92
+ end unless key.name == 'any'
84
93
  assert_nil( c.send( get ) )
85
94
  end
86
95
  end
@@ -92,4 +101,95 @@ class TestUniMap < MiniTest::Unit::TestCase
92
101
  c.methods.sort.select { |m| m =~ /[^=]=$/ }.join( " " ) )
93
102
  end
94
103
 
104
+ # Only tests below use this setup of a nested @sample structure.
105
+ def setup
106
+ @sample = UniMap.new
107
+ TEST_KEYS.each do |k,_,v|
108
+ @sample.send( "#{k}=", v ) if v
109
+ end
110
+ @sample.list = (1..2).map do |i|
111
+ UniMap.new.tap do |m|
112
+ m.int = i
113
+ m.str = i.to_s
114
+ end
115
+ end
116
+
117
+ @sample.sub = @sample.dup
118
+ end
119
+
120
+ def test_to_hash
121
+ h = @sample.to_hash
122
+
123
+ assert_equal( 33, h[ :int ], "to_hash should have symbol keys" )
124
+ assert_nil( h[ 'int' ], "to_hash should not have string keys" )
125
+ assert_equal( Hash[ @sample.to_a ], h, "to_a, to_hash agree" )
126
+ end
127
+
128
+ def test_is_a_hash
129
+ assert_kind_of( Hash, @sample )
130
+ assert( @sample.is_a?( Hash ) )
131
+ end
132
+
133
+ def test_membership
134
+ assert( @sample.has_key?( :int ) )
135
+ assert( @sample.include?( 'int' ) )
136
+ assert( @sample.key?( :str ) )
137
+ assert( @sample.member?( :str ) )
138
+ end
139
+
140
+ def test_unmapped_keys
141
+ refute( @sample.has_key?( :non_existing ) )
142
+ refute( @sample.has_key?( 'non_existing' ) )
143
+ assert_nil( @sample.remove( :non_existing ) )
144
+ assert_nil( @sample.get( :non_existing ) )
145
+ assert_raises( IndexError ) do
146
+ @sample.set( :non_existing, 'value' )
147
+ end
148
+ end
149
+
150
+ def test_brackets
151
+ assert_equal( 33, @sample[ 'int' ] )
152
+ assert_equal( 33, @sample[ :int ] )
153
+
154
+ assert_equal( 66, @sample[ :int ] = 66 )
155
+ assert_equal( 66, @sample[ :int ] )
156
+ end
157
+
158
+ def test_merge
159
+ m = @sample.merge( :int => 66, 'str' => "new" )
160
+ assert_equal( 33, @sample.int )
161
+ assert_equal( "string", @sample.str )
162
+ assert_equal( 66, m.int )
163
+ assert_equal( "new", m.str )
164
+
165
+ n = @sample.merge( m )
166
+ assert_equal( 66, n.int )
167
+ assert_equal( "new", n.str )
168
+ end
169
+
170
+ def test_merge_bang
171
+ @sample.merge!( :int => 66, :str => "new" )
172
+ assert_equal( 66, @sample.int )
173
+ assert_equal( "new", @sample.str )
174
+ end
175
+
176
+ def test_json
177
+
178
+ assert_equal( @sample.deep_hash.to_json, @sample.to_json )
179
+ refute_match( /int1/, @sample.to_json )
180
+
181
+ json = JSON.pretty_generate( @sample )
182
+ pass
183
+
184
+ LOG.debug { "JSON.pretty_generate:\n#{json}" }
185
+
186
+ s = @sample.clone
187
+ s.remove( :date ) #would otherwise roundtrip as string
188
+ s.delete( :sub ) #also has a date
189
+
190
+ assert_equal( s.deep_hash,
191
+ JSON.parse( s.to_json, :symbolize_names => true ) )
192
+
193
+ end
194
+
95
195
  end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: gravitext-util
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease: 4
5
- version: 1.6.b.0
5
+ version: 1.6.b.1
6
6
  platform: java
7
7
  authors:
8
8
  - David Kellum
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2012-01-30 00:00:00 Z
13
+ date: 2012-02-08 00:00:00 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rjack-slf4j
@@ -86,7 +86,7 @@ files:
86
86
  - test/test_ioutils.rb
87
87
  - test/test_perftest.rb
88
88
  - test/test_unimap.rb
89
- - lib/gravitext-util/gravitext-util-1.6.b.0.jar
89
+ - lib/gravitext-util/gravitext-util-1.6.b.1.jar
90
90
  homepage: http://gravitext.rubyforge.org
91
91
  licenses: []
92
92
 
@@ -114,7 +114,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
114
114
  requirements: []
115
115
 
116
116
  rubyforge_project:
117
- rubygems_version: 1.8.11
117
+ rubygems_version: 1.8.15
118
118
  signing_key:
119
119
  specification_version: 3
120
120
  summary: A collection of core java utilities, many with jruby adaptions.