gravitext-util 1.6.b.0-java → 1.6.b.1-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.
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.