jinx 2.1.1 → 2.1.2
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.md +4 -0
- data/lib/jinx.rb +0 -1
- data/lib/jinx/cli/application.rb +3 -3
- data/lib/jinx/cli/command.rb +1 -1
- data/lib/jinx/helpers/array.rb +3 -3
- data/lib/jinx/helpers/associative.rb +41 -0
- data/lib/jinx/helpers/collections.rb +0 -1
- data/lib/jinx/helpers/enumerable.rb +5 -2
- data/lib/jinx/helpers/hash.rb +1 -1
- data/lib/jinx/helpers/hashable.rb +1 -7
- data/lib/jinx/helpers/inflector.rb +1 -1
- data/lib/jinx/helpers/log.rb +63 -11
- data/lib/jinx/helpers/math.rb +20 -11
- data/lib/jinx/helpers/options.rb +4 -4
- data/lib/jinx/helpers/pretty_print.rb +0 -1
- data/lib/jinx/helpers/transitive_closure.rb +1 -1
- data/lib/jinx/helpers/uniquifier.rb +50 -17
- data/lib/jinx/helpers/visitor.rb +3 -3
- data/lib/jinx/import/java.rb +1 -1
- data/lib/jinx/importer.rb +3 -2
- data/lib/jinx/metadata/attribute_enumerator.rb +1 -1
- data/lib/jinx/metadata/dependency.rb +3 -3
- data/lib/jinx/metadata/introspector.rb +46 -42
- data/lib/jinx/metadata/inverse.rb +17 -1
- data/lib/jinx/metadata/java_property.rb +10 -10
- data/lib/jinx/metadata/propertied.rb +19 -16
- data/lib/jinx/metadata/property.rb +11 -11
- data/lib/jinx/resource.rb +86 -14
- data/lib/jinx/resource/match_visitor.rb +7 -5
- data/lib/jinx/resource/merge_visitor.rb +3 -10
- data/lib/jinx/resource/mergeable.rb +16 -16
- data/lib/jinx/resource/reference_enumerator.rb +0 -1
- data/lib/jinx/resource/reference_path_visitor.rb +1 -1
- data/lib/jinx/resource/reference_visitor.rb +5 -6
- data/lib/jinx/resource/unique.rb +1 -1
- data/lib/jinx/version.rb +1 -1
- data/test/lib/jinx/helpers/associative_test.rb +26 -0
- data/test/lib/jinx/helpers/collections_test.rb +14 -2
- data/test/lib/jinx/helpers/uniquifier_test.rb +11 -0
- metadata +9 -8
- data/Gemfile.lock +0 -27
- data/lib/jinx/helpers/error.rb +0 -15
- data/lib/jinx/helpers/key_transformer_hash.rb +0 -43
data/lib/jinx/helpers/visitor.rb
CHANGED
@@ -196,7 +196,7 @@ module Jinx
|
|
196
196
|
# @yieldparam children the nodes slated by this Visitor to visit next
|
197
197
|
# @raise [ArgumentError] if a block is not given to this method
|
198
198
|
def filter
|
199
|
-
|
199
|
+
raise ArgumentError.new("A filter block is not given to the visitor filter method") unless block_given?
|
200
200
|
Visitor.new(@options) { |node| yield(node, node_children(node)) }
|
201
201
|
end
|
202
202
|
|
@@ -319,7 +319,7 @@ module Jinx
|
|
319
319
|
def visit(*nodes)
|
320
320
|
if nodes.size == 1 then
|
321
321
|
nodes = nodes.first
|
322
|
-
|
322
|
+
raise ArgumentError.new("Sync visitor requires a pair of entry nodes") unless nodes.size == 2
|
323
323
|
end
|
324
324
|
super(nodes)
|
325
325
|
end
|
@@ -331,7 +331,7 @@ module Jinx
|
|
331
331
|
def to_enum(*nodes)
|
332
332
|
if nodes.size == 1 then
|
333
333
|
nodes = nodes.first
|
334
|
-
|
334
|
+
raise ArgumentError.new("Sync visitor requires a pair of entry nodes") unless nodes.size == 2
|
335
335
|
end
|
336
336
|
super(nodes)
|
337
337
|
end
|
data/lib/jinx/import/java.rb
CHANGED
@@ -91,7 +91,7 @@ module Java
|
|
91
91
|
# merge return a new collection.
|
92
92
|
def merge(other)
|
93
93
|
return self if other.nil?
|
94
|
-
|
94
|
+
raise ArgumentError.new("Merge argument must be enumerable: #{other}") unless Enumerable === other
|
95
95
|
other.each { |item| self << item }
|
96
96
|
self
|
97
97
|
end
|
data/lib/jinx/importer.rb
CHANGED
@@ -69,6 +69,7 @@ module Jinx
|
|
69
69
|
|
70
70
|
# @param [String] the module name to resolve in the context of this module
|
71
71
|
# @return [Module] the corresponding module
|
72
|
+
# @raise [NameError] if the name cannot be resolved
|
72
73
|
def module_for_name(name)
|
73
74
|
begin
|
74
75
|
# Incrementally resolve the module.
|
@@ -97,7 +98,7 @@ module Jinx
|
|
97
98
|
begin
|
98
99
|
eval "java_package Java::#{pkg}"
|
99
100
|
rescue Exception => e
|
100
|
-
|
101
|
+
raise ArgumentError.new("#{self} Java package #{pkg} not found - #{$!}")
|
101
102
|
end
|
102
103
|
end
|
103
104
|
# The introspected classes.
|
@@ -221,7 +222,7 @@ module Jinx
|
|
221
222
|
mod = klass.parent_module
|
222
223
|
klass.each_property do |prop|
|
223
224
|
ref = prop.type
|
224
|
-
if ref.nil? then
|
225
|
+
if ref.nil? then raise MetadataError.new("#{self} #{prop} domain type is unknown.") end
|
225
226
|
unless @introspected.include?(ref) or ref.parent_module != mod then
|
226
227
|
logger.debug { "Introspecting #{qp} #{prop} reference #{ref.qp}..." }
|
227
228
|
add_metadata(ref)
|
@@ -10,7 +10,7 @@ module Jinx
|
|
10
10
|
# @yieldparam [Property] the metadata for the standard attribute
|
11
11
|
# @raise [ArgumentError] if a parameter is missing
|
12
12
|
def initialize(hash, &filter)
|
13
|
-
|
13
|
+
raise ArgumentError.new("Attribute filter missing hash argument") if hash.nil?
|
14
14
|
@hash = hash
|
15
15
|
@filter = block_given? ? filter : Proc.new { true }
|
16
16
|
end
|
@@ -115,11 +115,11 @@ module Jinx
|
|
115
115
|
# @raise [ValidationError] if the inverse is nil
|
116
116
|
def add_owner(klass, inverse, attribute=nil)
|
117
117
|
if inverse.nil? then
|
118
|
-
|
118
|
+
raise ValidationError.new("Owner #{klass.qp} missing dependent attribute for dependent #{qp}")
|
119
119
|
end
|
120
120
|
logger.debug { "Adding #{qp} owner #{klass.qp}#{' attribute ' + attribute.to_s if attribute} with inverse #{inverse}..." }
|
121
121
|
if @owner_prop_hash then
|
122
|
-
|
122
|
+
raise MetadataError.new("Can't add #{qp} owner #{klass.qp} after dependencies have been accessed")
|
123
123
|
end
|
124
124
|
|
125
125
|
# detect the owner attribute, if necessary
|
@@ -175,7 +175,7 @@ module Jinx
|
|
175
175
|
if hash.include?(otype) then
|
176
176
|
oa = hash[otype]
|
177
177
|
unless oa.nil? then
|
178
|
-
|
178
|
+
raise MetadataError.new("Cannot set #{qp} owner attribute to #{attribute} since it is already set to #{oa}")
|
179
179
|
end
|
180
180
|
hash[otype] = prop
|
181
181
|
else
|
@@ -2,6 +2,7 @@ require 'jinx/helpers/module'
|
|
2
2
|
require 'jinx/import/java'
|
3
3
|
require 'jinx/metadata/propertied'
|
4
4
|
require 'jinx/metadata/java_property'
|
5
|
+
require 'jinx/helpers/math'
|
5
6
|
|
6
7
|
module Jinx
|
7
8
|
# Meta-data mix-in to infer attribute meta-data from Java properties.
|
@@ -77,68 +78,71 @@ module Jinx
|
|
77
78
|
return
|
78
79
|
end
|
79
80
|
# the standard underscore lower-case attributes
|
80
|
-
|
81
|
+
prop = add_java_property(pd)
|
81
82
|
# delegate the standard attribute accessors to the attribute accessors
|
82
|
-
alias_property_accessors(
|
83
|
+
alias_property_accessors(prop)
|
83
84
|
# add special wrappers
|
84
|
-
wrap_java_property(
|
85
|
+
wrap_java_property(prop)
|
85
86
|
# create Ruby alias for boolean, e.g. alias :empty? for :empty
|
86
87
|
if pd.property_type.name[/\w+$/].downcase == 'boolean' then
|
87
|
-
#
|
88
|
-
aliaz =
|
89
|
-
|
88
|
+
# Strip the leading is_, if any, before appending a question mark.
|
89
|
+
aliaz = prop.to_s[/^(is_)?(\w+)/, 2] << '?'
|
90
|
+
delegate_to_property(aliaz, prop)
|
90
91
|
end
|
91
92
|
end
|
92
93
|
|
93
|
-
# Adds a filter to the
|
94
|
-
def wrap_java_property(
|
94
|
+
# Adds a filter to the given property access methods if it is a String or Date.
|
95
|
+
def wrap_java_property(property)
|
96
|
+
pd = property.property_descriptor
|
95
97
|
if pd.property_type == Java::JavaLang::String.java_class then
|
96
|
-
|
98
|
+
wrap_java_string_property(property)
|
97
99
|
elsif pd.property_type == Java::JavaUtil::Date.java_class then
|
98
|
-
|
100
|
+
wrap_java_date_property(property)
|
99
101
|
end
|
100
102
|
end
|
101
103
|
|
102
|
-
# Adds a
|
103
|
-
def
|
104
|
+
# Adds a number -> string filter to the given String property Ruby access methods.
|
105
|
+
def wrap_java_string_property(property)
|
106
|
+
ra, wa = property.accessors
|
107
|
+
jra, jwa = property.java_accessors
|
104
108
|
# filter the attribute writer
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
stdval = value.to_s unless value.nil_or_empty?
|
109
|
-
send(pwtr, stdval)
|
109
|
+
define_method(wa) do |value|
|
110
|
+
stdval = Math.numeric?(value) ? value.to_s : value
|
111
|
+
send(jwa, stdval)
|
110
112
|
end
|
111
|
-
logger.debug { "Filtered #{qp} #{
|
113
|
+
logger.debug { "Filtered #{qp} #{wa} method with non-String -> String converter." }
|
112
114
|
end
|
113
115
|
|
114
|
-
# Adds a
|
115
|
-
|
116
|
+
# Adds a Java-Ruby Date filter to the given Date property Ruby access methods.
|
117
|
+
# The reader returns a Ruby date. The writer sets a Java date.
|
118
|
+
def wrap_java_date_property(property)
|
119
|
+
ra, wa = property.accessors
|
120
|
+
jra, jwa = property.java_accessors
|
121
|
+
|
116
122
|
# filter the attribute reader
|
117
|
-
|
118
|
-
|
119
|
-
value = send(prdr)
|
123
|
+
define_method(ra) do
|
124
|
+
value = send(jra)
|
120
125
|
Java::JavaUtil::Date === value ? value.to_ruby_date : value
|
121
126
|
end
|
122
127
|
|
123
128
|
# filter the attribute writer
|
124
|
-
|
125
|
-
pwtr = pd.write_method.name.to_sym
|
126
|
-
define_method(awtr) do |value|
|
129
|
+
define_method(wa) do |value|
|
127
130
|
value = Java::JavaUtil::Date.from_ruby_date(value) if ::Date === value
|
128
|
-
send(
|
131
|
+
send(jwa, value)
|
129
132
|
end
|
130
133
|
|
131
|
-
logger.debug { "Filtered #{qp} #{
|
134
|
+
logger.debug { "Filtered #{qp} #{ra} and #{wa} methods with Java Date <-> Ruby Date converter." }
|
132
135
|
end
|
133
136
|
|
134
|
-
# Aliases the
|
135
|
-
#
|
136
|
-
|
137
|
+
# Aliases the given Ruby property reader and writer to its underlying Java property reader and writer, resp.
|
138
|
+
#
|
139
|
+
# @param [Property] property the property to alias
|
140
|
+
def alias_property_accessors(property)
|
141
|
+
# the Java reader and writer accessor method symbols
|
142
|
+
jra, jwa = property.java_accessors
|
137
143
|
# strip the Java reader and writer is/get/set prefix and make a symbol
|
138
|
-
|
139
|
-
alias_method(
|
140
|
-
writer = "#{aliaz}=".to_sym
|
141
|
-
alias_method(writer, pwtr)
|
144
|
+
alias_method(property.reader, jra)
|
145
|
+
alias_method(property.writer, jwa)
|
142
146
|
end
|
143
147
|
|
144
148
|
# Makes a standard attribute for the given property descriptor.
|
@@ -154,7 +158,7 @@ module Jinx
|
|
154
158
|
pa = prop.attribute
|
155
159
|
# the Java property name as an attribute symbol
|
156
160
|
ja = pd.name.to_sym
|
157
|
-
|
161
|
+
delegate_to_property(ja, prop) unless prop.reader == ja
|
158
162
|
prop
|
159
163
|
end
|
160
164
|
|
@@ -168,12 +172,12 @@ module Jinx
|
|
168
172
|
# _attribute=_ accessor methods, resp.
|
169
173
|
# Calling rather than aliasing the attribute accessor allows the aliaz accessor to
|
170
174
|
# reflect a change to the attribute accessor.
|
171
|
-
def
|
172
|
-
|
173
|
-
|
174
|
-
define_method(aliaz) { send(
|
175
|
-
define_method("#{aliaz}=".to_sym) { |value| send(
|
176
|
-
register_property_alias(aliaz, attribute)
|
175
|
+
def delegate_to_property(aliaz, property)
|
176
|
+
ra, wa = property.accessors
|
177
|
+
if aliaz == ra then raise MetadataError.new("Cannot delegate #{self} #{aliaz} to itself.") end
|
178
|
+
define_method(aliaz) { send(ra) }
|
179
|
+
define_method("#{aliaz}=".to_sym) { |value| send(wa, value) }
|
180
|
+
register_property_alias(aliaz, property.attribute)
|
177
181
|
end
|
178
182
|
end
|
179
183
|
end
|
@@ -56,7 +56,7 @@ module Jinx
|
|
56
56
|
end
|
57
57
|
# This class must be the same as or a subclass of the inverse attribute type.
|
58
58
|
unless self <= inv_prop.type then
|
59
|
-
|
59
|
+
raise TypeError.new("Cannot set #{qp}.#{pa} inverse to #{prop.type.qp}.#{pa} with incompatible type #{inv_prop.type.qp}")
|
60
60
|
end
|
61
61
|
# Set the inverse in the attribute metadata.
|
62
62
|
prop.inverse = inverse
|
@@ -70,6 +70,22 @@ module Jinx
|
|
70
70
|
end
|
71
71
|
logger.debug { "Set #{qp}.#{pa} inverse to #{inverse}." }
|
72
72
|
end
|
73
|
+
|
74
|
+
# Clears the property inverse, if there is one.
|
75
|
+
def clear_inverse(property)
|
76
|
+
# the inverse property
|
77
|
+
ip = property.inverse_property || return
|
78
|
+
# If the property is a collection and the inverse is not, then delegate to
|
79
|
+
# the inverse.
|
80
|
+
if property.collection? then
|
81
|
+
return ip.declarer.clear_inverse(ip) unless ip.collection?
|
82
|
+
else
|
83
|
+
# Restore the property reader and writer to the Java reader and writer, resp.
|
84
|
+
alias_property_accessors(property)
|
85
|
+
end
|
86
|
+
# Unset the inverse.
|
87
|
+
property.inverse = nil
|
88
|
+
end
|
73
89
|
|
74
90
|
# Detects an unambiguous attribute which refers to the given referencing class.
|
75
91
|
# If there is exactly one attribute with the given return type, then that attribute is chosen.
|
@@ -9,7 +9,7 @@ module Jinx
|
|
9
9
|
attr_reader :property_descriptor
|
10
10
|
|
11
11
|
# This property's Java property [reader, writer] accessors, e.g. +[:getActivityStatus, :setActivityStatus]+.
|
12
|
-
attr_reader :
|
12
|
+
attr_reader :java_accessors
|
13
13
|
|
14
14
|
# Creates a Ruby Property symbol corresponding to the given Ruby Java class wrapper klazz
|
15
15
|
# and Java property_descriptor.
|
@@ -34,34 +34,34 @@ module Jinx
|
|
34
34
|
@property_descriptor = pd
|
35
35
|
# deficient Java introspector does not recognize 'is' prefix for a Boolean property
|
36
36
|
rm = declarer.property_read_method(pd)
|
37
|
-
|
37
|
+
raise ArgumentError.new("Property does not have a read method: #{declarer.qp}.#{pd.name}") unless rm
|
38
38
|
reader = rm.name.to_sym
|
39
39
|
unless declarer.method_defined?(reader) then
|
40
40
|
reader = "is#{reader.to_s.capitalize_first}".to_sym
|
41
41
|
unless declarer.method_defined?(reader) then
|
42
|
-
|
42
|
+
raise ArgumentError.new("Reader method not found for #{declarer} property #{pd.name}")
|
43
43
|
end
|
44
44
|
end
|
45
45
|
unless pd.write_method then
|
46
|
-
|
46
|
+
raise ArgumentError.new("Property does not have a write method: #{declarer.qp}.#{pd.name}")
|
47
47
|
end
|
48
48
|
writer = pd.write_method.name.to_sym
|
49
49
|
unless declarer.method_defined?(writer) then
|
50
|
-
|
50
|
+
raise ArgumentError.new("Writer method not found for #{declarer} property #{pd.name}")
|
51
51
|
end
|
52
|
-
@
|
52
|
+
@java_accessors = [reader, writer]
|
53
53
|
qualify(:collection) if collection_java_class?
|
54
54
|
@type = infer_type
|
55
55
|
end
|
56
56
|
|
57
57
|
# @return [Symbol] the JRuby wrapper method for the Java property reader
|
58
|
-
def
|
59
|
-
|
58
|
+
def java_reader
|
59
|
+
java_accessors.first
|
60
60
|
end
|
61
61
|
|
62
62
|
# @return [Symbol] the JRuby wrapper method for the Java property writer
|
63
|
-
def
|
64
|
-
|
63
|
+
def java_writer
|
64
|
+
java_accessors.last
|
65
65
|
end
|
66
66
|
|
67
67
|
# Returns a lower-case, underscore symbol for the given property_name.
|
@@ -15,13 +15,10 @@ module Jinx
|
|
15
15
|
|
16
16
|
# Returns whether this class has an attribute with the given symbol.
|
17
17
|
#
|
18
|
-
# @param [Symbol]
|
18
|
+
# @param [String, Symbol] name the potential attribute
|
19
19
|
# @return [Boolean] whether there is a corresponding attribute
|
20
|
-
def property_defined?(
|
21
|
-
|
22
|
-
Jinx.fail(ArgumentError, "Property argument #{symbol.qp} of type #{symbol.class.qp} is not a symbol")
|
23
|
-
end
|
24
|
-
!!@alias_std_prop_map[symbol.to_sym]
|
20
|
+
def property_defined?(name)
|
21
|
+
!!@alias_std_prop_map[name.to_sym]
|
25
22
|
end
|
26
23
|
|
27
24
|
# Adds the given attribute to this Class.
|
@@ -80,7 +77,8 @@ module Jinx
|
|
80
77
|
@prop_hash.each_value(&block)
|
81
78
|
end
|
82
79
|
|
83
|
-
# @
|
80
|
+
# @param [Symbol] attribute the property attribute symbol or alias
|
81
|
+
# @return [Property] the corresponding property
|
84
82
|
# @raise [NameError] if the attribute is not recognized
|
85
83
|
def property(attribute)
|
86
84
|
# Simple and predominant case is that the attribute is a standard attribute.
|
@@ -88,7 +86,7 @@ module Jinx
|
|
88
86
|
prop = @prop_hash[attribute] || @prop_hash[standard_attribute(attribute)]
|
89
87
|
# If not found, then raise a NameError.
|
90
88
|
if prop.nil? then
|
91
|
-
|
89
|
+
raise NameError.new("#{name.demodulize} attribute not found: #{attribute}")
|
92
90
|
end
|
93
91
|
prop
|
94
92
|
end
|
@@ -116,9 +114,9 @@ module Jinx
|
|
116
114
|
# @raise [NameError] if the attribute is not found
|
117
115
|
def standard_attribute(name_or_alias)
|
118
116
|
if name_or_alias.nil? then
|
119
|
-
|
117
|
+
raise ArgumentError.new("#{qp} standard attribute call is missing the attribute name/alias parameter")
|
120
118
|
end
|
121
|
-
@alias_std_prop_map[name_or_alias.to_sym] or
|
119
|
+
@alias_std_prop_map[name_or_alias.to_sym] or raise NameError.new("#{self} attribute not found: #{name_or_alias}")
|
122
120
|
end
|
123
121
|
|
124
122
|
## Metadata ATTRIBUTE FILTERS ##
|
@@ -217,10 +215,15 @@ module Jinx
|
|
217
215
|
# @return [AttributeEnumerator] a new attribute enumerator
|
218
216
|
def attribute_filter(attributes=nil, &filter)
|
219
217
|
# make the attribute filter
|
220
|
-
raise MetadataError.new("#{self} has not been introspected")
|
218
|
+
raise MetadataError.new("#{self} has not been introspected") unless introspected?
|
221
219
|
ph = attributes ? attributes.to_compact_hash { |pa| @prop_hash[pa] } : @prop_hash
|
222
220
|
AttributeEnumerator.new(ph, &filter)
|
223
221
|
end
|
222
|
+
|
223
|
+
# @return [Boolean] whether this class's metadata has been introspected
|
224
|
+
def introspected?
|
225
|
+
!!@prop_hash
|
226
|
+
end
|
224
227
|
|
225
228
|
protected
|
226
229
|
|
@@ -296,7 +299,7 @@ module Jinx
|
|
296
299
|
# @param [Symbol] attribute the attribute to alias
|
297
300
|
def alias_attribute(aliaz, attribute)
|
298
301
|
if property_defined?(attribute) then
|
299
|
-
|
302
|
+
delegate_to_property(aliaz, property(attribute))
|
300
303
|
register_property_alias(aliaz, attribute)
|
301
304
|
else
|
302
305
|
super
|
@@ -368,7 +371,7 @@ module Jinx
|
|
368
371
|
prop.restrict(self, :type => klass)
|
369
372
|
logger.debug { "Restricted #{prop.declarer.qp}.#{attribute}(#{prop.type.qp}) to #{qp} with return type #{klass.qp}." }
|
370
373
|
else
|
371
|
-
|
374
|
+
raise ArgumentError.new("Cannot reset #{qp}.#{attribute} type #{prop.type.qp} to incompatible #{klass.qp}")
|
372
375
|
end
|
373
376
|
end
|
374
377
|
|
@@ -416,7 +419,7 @@ module Jinx
|
|
416
419
|
prop = @local_prop_hash.delete(std_prop)
|
417
420
|
if prop then
|
418
421
|
# clear the inverse, if any
|
419
|
-
prop
|
422
|
+
clear_inverse(prop)
|
420
423
|
# remove from the mandatory attributes, if necessary
|
421
424
|
@local_mndty_flt.delete(std_prop)
|
422
425
|
# remove from the attribute => metadata hash
|
@@ -443,7 +446,7 @@ module Jinx
|
|
443
446
|
# @param (see #alias_attribute)
|
444
447
|
def register_property_alias(aliaz, attribute)
|
445
448
|
std = standard_attribute(attribute)
|
446
|
-
|
449
|
+
raise ArgumentError.new("#{self} attribute not found: #{attribute}") if std.nil?
|
447
450
|
@local_std_prop_hash[aliaz.to_sym] = std
|
448
451
|
end
|
449
452
|
|
@@ -457,7 +460,7 @@ module Jinx
|
|
457
460
|
return enum unless Class === self and superclass.parent_module == parent_module
|
458
461
|
anc_enum = yield superclass
|
459
462
|
if anc_enum.nil? then
|
460
|
-
|
463
|
+
raise MetadataError.new("#{qp} superclass #{superclass.qp} does not have required metadata")
|
461
464
|
end
|
462
465
|
enum.union(anc_enum)
|
463
466
|
end
|
@@ -121,13 +121,13 @@ module Jinx
|
|
121
121
|
begin
|
122
122
|
@inv_prop = type.property(attribute)
|
123
123
|
rescue NameError => e
|
124
|
-
|
124
|
+
raise MetadataError.new("#{@declarer.qp}.#{self} inverse attribute #{type.qp}.#{attribute} not found")
|
125
125
|
end
|
126
126
|
# the inverse of the inverse
|
127
127
|
inv_inv_prop = @inv_prop.inverse_property
|
128
128
|
# If the inverse of the inverse is already set to a different attribute, then raise an exception.
|
129
129
|
if inv_inv_prop and not (inv_inv_prop == self or inv_inv_prop.restriction?(self))
|
130
|
-
|
130
|
+
raise MetadataError.new("Cannot set #{type.qp}.#{attribute} inverse attribute to #{@declarer.qp}.#{self}@#{object_id} since it conflicts with existing inverse #{inv_inv_prop.declarer.qp}.#{inv_inv_prop}@#{inv_inv_prop.object_id}")
|
131
131
|
end
|
132
132
|
# Set the inverse of the inverse to this attribute.
|
133
133
|
@inv_prop.inverse = @attribute
|
@@ -270,10 +270,10 @@ module Jinx
|
|
270
270
|
rtype = opts[:type] || @type
|
271
271
|
rinv = opts[:inverse] || inverse
|
272
272
|
unless declarer < @declarer then
|
273
|
-
|
273
|
+
raise ArgumentError.new("Cannot restrict #{@declarer.qp}.#{self} to an incompatible declarer type #{declarer.qp}")
|
274
274
|
end
|
275
275
|
unless rtype <= @type then
|
276
|
-
|
276
|
+
raise ArgumentError.new("Cannot restrict #{@declarer.qp}.#{self}({@type.qp}) to an incompatible return type #{rtype.qp}")
|
277
277
|
end
|
278
278
|
# Copy this attribute and its instance variables minus the restrictions and make a deep copy of the flags.
|
279
279
|
rst = deep_copy
|
@@ -318,7 +318,7 @@ module Jinx
|
|
318
318
|
# @param [Class] klass the declaring class of this restriction attribute
|
319
319
|
def set_restricted_declarer(klass)
|
320
320
|
if @declarer and not klass < @declarer then
|
321
|
-
|
321
|
+
raise MetadataError.new("Cannot reset #{declarer.qp}.#{self} declarer to #{type.qp}")
|
322
322
|
end
|
323
323
|
@declarer = klass
|
324
324
|
@declarer.add_restriction(self)
|
@@ -350,11 +350,11 @@ module Jinx
|
|
350
350
|
return unless @inv_prop
|
351
351
|
logger.debug { "Clearing #{@declarer.qp}.#{self} inverse #{type.qp}.#{inverse}..." }
|
352
352
|
# Capture the inverse before unsetting it.
|
353
|
-
|
353
|
+
ip = @inv_prop
|
354
354
|
# Unset the inverse.
|
355
355
|
@inv_prop = nil
|
356
356
|
# Clear the inverse of the inverse.
|
357
|
-
|
357
|
+
ip.inverse = nil
|
358
358
|
logger.debug { "Cleared #{@declarer.qp}.#{self} inverse." }
|
359
359
|
end
|
360
360
|
|
@@ -363,7 +363,7 @@ module Jinx
|
|
363
363
|
def set_flag(flag)
|
364
364
|
return if @flags.include?(flag)
|
365
365
|
unless flag_supported?(flag) then
|
366
|
-
|
366
|
+
raise ArgumentError.new("Property #{declarer.name}.#{self} flag not supported: #{flag.qp}")
|
367
367
|
end
|
368
368
|
@flags << flag
|
369
369
|
case flag
|
@@ -379,11 +379,11 @@ module Jinx
|
|
379
379
|
# @raise [MetadataError] if this attribute is dependent or an inverse could not be inferred
|
380
380
|
def owner_flag_set
|
381
381
|
if dependent? then
|
382
|
-
|
382
|
+
raise MetadataError.new("#{declarer.qp}.#{self} cannot be set as a #{type.qp} owner since it is already defined as a #{type.qp} dependent")
|
383
383
|
end
|
384
384
|
inv_attr = type.dependent_attribute(@declarer)
|
385
385
|
if inv_attr.nil? then
|
386
|
-
|
386
|
+
raise MetadataError.new("#{@declarer.qp} owner attribute #{self} does not have a #{type.qp} dependent inverse")
|
387
387
|
end
|
388
388
|
logger.debug { "#{declarer.qp}.#{self} inverse is the #{type.qp} dependent attribute #{inv_attr}." }
|
389
389
|
self.inverse = inv_attr
|
@@ -394,7 +394,7 @@ module Jinx
|
|
394
394
|
# @raise [MetadataError] if this is an owner attribute
|
395
395
|
def dependent_flag_set
|
396
396
|
if owner? then
|
397
|
-
|
397
|
+
raise MetadataError.new("#{declarer.qp}.#{self} cannot be set as a #{type.qp} dependent since it is already defined as a #{type.qp} owner")
|
398
398
|
end
|
399
399
|
end
|
400
400
|
end
|