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. StudyProtocolCollectiontype 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