Class: Module

Inherits:
Object show all
Defined in:
lib/jinx/import/java.rb,
lib/jinx/helpers/module.rb,
lib/jinx/helpers/pretty_print.rb

Constant Summary collapse

OBJ_INST_MTHDS =
Object.instance_methods

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.to_ruby(mod) ⇒ Module

Returns the Ruby module for the given argument, as follows:

  • If the argument is a primitive Java type, then return the corresponding JRuby wrapper.

  • If the argument is a Ruby module, then return that module.

  • If the argument is an unwrapped Java class or interface, then return the JRuby wrapper for the class string.

  • If the argument is a String, then return the JRuby wrapper for the Java class designated by that String.

Examples:

Java.to_ruby(Java::java.lang.Boolean) #=> Java::JavaLang::Boolean
Java.to_ruby(Java::boolean) #=> Java::JavaLang::Boolean
Java.to_ruby('boolean') #=> Java::JavaLang::Boolean

Parameters:

  • mod (Module, String)

    the Ruby module or unwrapped Java class, interface or name

Returns:

  • (Module)

    the corresponding Ruby class



226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
# File 'lib/jinx/import/java.rb', line 226

def self.to_ruby(mod)
  if mod.respond_to?(:java_class) then
    # A primitive Java type has an empty name and non-capitalized java_class name.
    jname = mod.name.blank? ? mod.java_class.name : mod.name
    if jname.blank? then
      raise ArgumentError.new("Cannot convert the anonymous Java class #{mod} to a JRuby class")
    end
    if jname =~ /^[a-z]+$/ then
      # The effective Java type is the Java wrapper class.
      to_ruby('java.lang.' + jname.capitalize)
    elsif Module === mod then
      mod
    else
      to_ruby(jname)
    end
  elsif Module === mod then
    mod
  elsif String === mod then 
    eval "Java::#{mod}"
  else
    raise ArgumentError.new("Cannot convert a #{mod.class} to a JRuby module")
  end
end

Instance Method Details

#abstract?Boolean

Returns whether this is a wrapper for an abstract Java class.

Returns:

  • (Boolean)

    whether this is a wrapper for an abstract Java class



251
252
253
# File 'lib/jinx/import/java.rb', line 251

def abstract?
  java_class? and Java::JavaLangReflect::Modifier.isAbstract(java_class.modifiers)
end

#java_class?Boolean

Returns whether this is a Ruby wrapper for a Java class or interface.

Returns:

  • (Boolean)


206
207
208
# File 'lib/jinx/import/java.rb', line 206

def java_class?
  respond_to?(:java_class)
end

#module_with_name(name) ⇒ Module?

Returns the class or module with the given name defined in this module. The name can qualified by parent modules, e.g. MyApp::Person. If name cannot be resolved as a Module, then this method returns nil.

Parameters:

Returns:

  • (Module, nil)

    the class or module defined in this module, or nil if none



8
9
10
# File 'lib/jinx/helpers/module.rb', line 8

def module_with_name(name)
  name.split('::').inject(self) { |parent, part| parent.const_get(part) } rescue nil
end

#parent_moduleModule

Returns this module’s definition context.

Examples:

A::B.parent_module #=> A

Returns:

  • (Module)

    this module’s definition context



15
16
17
# File 'lib/jinx/helpers/module.rb', line 15

def parent_module
  module_with_name(name.split('::')[0..-2].join('::'))
end

#property_descriptors(hierarchy = true) ⇒ Object

Returns this class’s readable and writable Java PropertyDescriptors, or an empty Array if none. If the hierarchy flag is set to false, then only this class’s properties will be introspected.



269
270
271
272
273
# File 'lib/jinx/import/java.rb', line 269

def property_descriptors(hierarchy=true)
  return Array::EMPTY_ARRAY unless java_class?
  info = hierarchy ? Java::JavaBeans::Introspector.getBeanInfo(java_class) : Java::JavaBeans::Introspector.getBeanInfo(java_class, java_class.superclass)
  info.propertyDescriptors.select { |pd| pd.write_method and property_read_method(pd) }
end

#property_read_method(pd) ⇒ Symbol

Returns the property descriptor pd introspected or discovered Java read Method.

Returns:

  • (Symbol)

    the property descriptor pd introspected or discovered Java read Method

Technology idiosyncracy:

  • Java

    java.lang.Boolean isname is not introspected as a read method, since the type must be primitive, i.e. boolean isname. The work-around is to explicitly look for the isname method in the case of a java.lang.Boolean property rather than rely on the Java introspector.



331
332
333
334
335
336
337
# File 'lib/jinx/import/java.rb', line 331

def property_read_method(pd)
  return pd.read_method if pd.read_method
  return unless pd.get_property_type == Java::JavaLang::Boolean.java_class
  rdr = java_class.java_method("is#{pd.name.capitalize_first}") rescue nil
  logger.debug { "Discovered #{qp} #{pd.name} property non-introspected reader method #{rdr.name}." } if rdr
  rdr
end

#qpString

Returns the demodulized name.

Returns:

  • (String)

    the demodulized name



106
107
108
# File 'lib/jinx/helpers/pretty_print.rb', line 106

def qp
  name[/\w+$/]
end

#transient?(pd) ⇒ Boolean

Returns whether the given PropertyDescriptor pd corresponds to a transient field in this class, or nil if there is no such field.

Returns:

  • (Boolean)


256
257
258
259
260
261
262
263
264
# File 'lib/jinx/import/java.rb', line 256

def transient?(pd)
  begin
    field = java_class.declared_field(pd.name)
  rescue Exception
    # should occur only if a property is not a field; not an error
    return
  end
  Java::JavaLangReflect::Modifier.isTransient(field.modifiers) if field
end

#unocclude_reserved_method(pd) ⇒ Object

Redefines the reserved method corresponding to the given Java property descriptor back to the Object implementation, if necessary. If both this class and Object define a method with the given property name, then a new method is defined with the same body as the previous method. Returns the new method symbol, or nil if the property name is not an occluded Object instance method.

This method undoes the JRuby clobbering of Object methods by Java property method wrappers. The method is renamed as follows:

  • id is changed to :identifier

  • type is prefixed by the underscore subject class name, e.g. Specimen.type => :specimen_type, If the property name is type and the subject class name ends in ‘Type’, then the property symbol is the underscore subject class name, e.g. HistologicType.type => :histologic_type.

Raises ArgumentError if symbol is not an Object method.



290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
# File 'lib/jinx/import/java.rb', line 290

def unocclude_reserved_method(pd)
  oldname = pd.name.underscore
  return unless OBJ_INST_MTHDS.include?(oldname)
  oldsym = oldname.to_sym
  undeprecated = case oldsym
    when :id then :object_id
    when :type then :class
    else oldsym
  end
  rsvd_mth = Object.instance_method(undeprecated)
  base = self.qp.underscore
  newname = if oldname == 'id' then
    'identifier'
  elsif base[-oldname.length..-1] == oldname then
    base
  else
    "#{base}_#{oldname}"
  end
  newsym = newname.to_sym
  rdr = property_read_method(pd).name.to_sym
  alias_method(newsym, rdr)
  # alias the writers
  wtr = pd.write_method.name.to_sym
  alias_method("#{newsym}=".to_sym, wtr)
  # alias a camel-case Java-style method if necessary
  altname = newname.camelize
  unless altname == newname then
    alias_method(altname.to_sym, oldsym)
    alias_method("#{altname}=".to_sym, wtr)
  end
  # restore the old method to Object
  define_method(oldsym) { |*args| rsvd_mth.bind(self).call(*args) }
  newsym
end