Class: Jinx::JavaProperty

Inherits:
Property show all
Defined in:
lib/jinx/metadata/java_property.rb

Overview

The attribute metadata for an introspected Java property.

Constant Summary

Constants inherited from Property

Property::SUPPORTED_FLAGS

Instance Attribute Summary collapse

Attributes inherited from Property

#accessors, #attribute, #declarer, #flags, #type

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Property

#clear_inverse, #deep_copy, #dependent_flag_set, #derived_inverse, #dup_content, #flag_supported?, #inverse, #inverse=, #inverse_property, #owner_flag_set, #qualify, #reader, #restrict, #restrict_flags, #restriction?, #set_flag, #set_restricted_declarer, #to_s, #writer

Methods included from PropertyCharacteristics

#bidirectional?, #bidirectional_java_association?, #collection?, #dependent?, #derived?, #disjoint?, #domain?, #independent?, #java_property?, #mandatory?, #many_to_many?, #nondomain?, #owner?, #restriction?, #unidirectional?, #unidirectional_java_dependent?

Constructor Details

#initialize(pd, declarer, restricted_type = nil) ⇒ JavaProperty

Creates a Ruby Property symbol corresponding to the given Ruby Java class wrapper klazz and Java property_descriptor.

The property name is the lower-case, underscore property descriptor name with the alterations described in to_attribute_symbol and Class#unocclude_reserved_method.

The property type is inferred as follows:

  • If the property descriptor return type is a primitive Java type, then that type is returned.
  • If the return type is a parameterized collection, then the parameter type is returned.
  • If the return type is an unparameterized collection, then this method infers the type from the property name, e.g. +StudyProtocolCollection+type is inferred as StudyProtocol by stripping the Collection suffix, capitalizing the prefix and looking for a class of that name in the Metadata#domain_module.
  • Otherwise, this method returns Java::Javalang::Object.

The optional restricted_type argument restricts the property to a subclass of the declared property type.

Raises:

  • (ArgumentError)


34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/jinx/metadata/java_property.rb', line 34

def initialize(pd, declarer, restricted_type=nil)
  symbol = create_standard_attribute_symbol(pd, declarer)
  super(symbol, declarer, restricted_type)
  @property_descriptor = pd
  # deficient Java introspector does not recognize 'is' prefix for a Boolean property
  rm = declarer.property_read_method(pd)
  raise ArgumentError.new("Property does not have a read method: #{declarer.qp}.#{pd.name}") unless rm
  rdr = rm.name.to_sym
  unless declarer.method_defined?(rdr) then
    rdr = "is#{rdr.to_s.capitalize_first}".to_sym
    unless declarer.method_defined?(rdr) then
      raise ArgumentError.new("Reader method not found for #{declarer} property #{pd.name}")
    end
  end
  unless pd.write_method then
    raise ArgumentError.new("Property does not have a write method: #{declarer.qp}.#{pd.name}")
  end
  wtr = pd.write_method.name.to_sym
  unless declarer.method_defined?(wtr) then
    raise ArgumentError.new("Writer method not found for #{declarer} property #{pd.name}")
  end
  @java_accessors = [rdr, wtr]
  @java_wrapper_class = Class.to_ruby(pd.property_type)
  qualify(:collection) if collection_java_class?
  @type = infer_type
end

Instance Attribute Details

#java_accessorsObject (readonly)

This property's Java property [reader, writer] accessors, e.g. [:getActivityStatus, :setActivityStatus].



15
16
17
# File 'lib/jinx/metadata/java_property.rb', line 15

def java_accessors
  @java_accessors
end

#java_wrapper_classObject (readonly)

This property's Java property descriptor type JRuby class wrapper.



9
10
11
# File 'lib/jinx/metadata/java_property.rb', line 9

def java_wrapper_class
  @java_wrapper_class
end

#property_descriptorObject (readonly)

This property's Java property descriptor.



12
13
14
# File 'lib/jinx/metadata/java_property.rb', line 12

def property_descriptor
  @property_descriptor
end

Class Method Details

.to_attribute_symbol(property_name) ⇒ Object

Returns a lower-case, underscore symbol for the given property_name. A name ending in 'Collection' is changed to a pluralization.

Examples:

JavaProperty.to_attribute_symbol('specimenEventCollection') #=> :specimen_events


76
77
78
79
80
81
82
83
# File 'lib/jinx/metadata/java_property.rb', line 76

def self.to_attribute_symbol(property_name)
  name = if property_name =~ /(.+)Collection$/ then
    property_name[0...-'Collection'.length].pluralize.underscore
  else
    property_name.underscore
  end
  name.to_sym
end

Instance Method Details

#collection_java_class?Boolean (private)

Returns whether this property's Java type is Iterable.

Returns:

  • (Boolean)

    whether this property's Java type is Iterable



103
104
105
106
# File 'lib/jinx/metadata/java_property.rb', line 103

def collection_java_class?
  # Test whether the JRuby wrapper class or module is an Iterable.
  @java_wrapper_class < Java::JavaLang::Iterable
end

#create_standard_attribute_symbol(pd, klass) ⇒ String (private)

Returns the lower-case, underscore symbol for the given property descriptor.

Parameters:

  • pd

    the Java property descriptor

  • klass (Class)

    the declarer

Returns:

  • (String)

    the lower-case, underscore symbol for the given property descriptor



90
91
92
93
94
95
96
97
98
99
100
# File 'lib/jinx/metadata/java_property.rb', line 90

def create_standard_attribute_symbol(pd, klass)
  propname = pd.name
  name = propname.underscore
  renamed = klass.unocclude_reserved_method(pd)
  if renamed then
    logger.debug { "Renamed #{klass.qp} reserved Ruby method #{name} to #{renamed}." }
    renamed
  else
    JavaProperty.to_attribute_symbol(propname)
  end
end

#generic_parameter_typeClass? (private)

Returns the domain type of this property's property descriptor Collection generic type argument, or nil if none.

Returns:

  • (Class, nil)

    the domain type of this property's property descriptor Collection generic type argument, or nil if none



124
125
126
127
128
129
130
131
132
133
134
# File 'lib/jinx/metadata/java_property.rb', line 124

def generic_parameter_type
  method = @property_descriptor.readMethod || return
  gtype = method.genericReturnType
  return unless Java::JavaLangReflect::ParameterizedType === gtype
  atypes = gtype.actualTypeArguments
  return unless atypes.size == 1
  atype = atypes[0]
  klass = Class.to_ruby(atype)
  logger.debug { "Inferred #{declarer.qp} #{self} domain type #{klass.qp} from generic parameter #{atype.name}." } if klass
  klass
end

#infer_collection_typeClass (private)

Returns the domain type for this property's Java Collection property descriptor. If the property type is parameterized by a single domain class, then that generic type argument is the domain type. Otherwise, the type is inferred from the property name as described in #infer_collection_type_from_name.

Returns:

  • (Class)

    this property's Ruby type



118
119
120
# File 'lib/jinx/metadata/java_property.rb', line 118

def infer_collection_type
   generic_parameter_type or infer_collection_type_from_name or Java::JavaLang::Object
end

#infer_collection_type_from_nameClass (private)

Returns the domain type for this property's collection Java property descriptor name. By convention, Jinx domain collection propertys often begin with a domain type name and end in 'Collection'. This method strips the Collection suffix and checks whether the prefix is a domain class.

For example, the type of the property named distributionProtocolCollection is inferred as DistributionProtocol by stripping the Collection suffix, capitalizing the prefix and looking for a class of that name in this classifier's domain_module.

Returns:

  • (Class)

    the collection item type



147
148
149
150
151
152
153
154
155
156
# File 'lib/jinx/metadata/java_property.rb', line 147

def infer_collection_type_from_name
  # the property name
  pname = @property_descriptor.name
  # The potential class name is the capitalized property name without a 'Collection' suffix.
  cname = pname.capitalize_first.sub(/Collection$/, '')
  jname = [@declarer.parent_module, cname].join('::')
  klass = eval jname rescue nil
  if klass then logger.debug { "Inferred #{declarer.qp} #{self} collection domain type #{klass.qp} from the property name." } end
  klass
end

#infer_typeClass (private)

Returns the type for the specified klass property descriptor pd as described in #initialize.

Returns:

  • (Class)

    the type for the specified klass property descriptor pd as described in #initialize



109
110
111
# File 'lib/jinx/metadata/java_property.rb', line 109

def infer_type
  collection? ? infer_collection_type : @java_wrapper_class
end

#java_readerSymbol

Returns the JRuby wrapper method for the Java property reader.

Returns:

  • (Symbol)

    the JRuby wrapper method for the Java property reader



62
63
64
# File 'lib/jinx/metadata/java_property.rb', line 62

def java_reader
  java_accessors.first
end

#java_writerSymbol

Returns the JRuby wrapper method for the Java property writer.

Returns:

  • (Symbol)

    the JRuby wrapper method for the Java property writer



67
68
69
# File 'lib/jinx/metadata/java_property.rb', line 67

def java_writer
  java_accessors.last
end