activefacts 0.7.3 → 0.8.5
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/LICENSE +19 -0
- data/Manifest.txt +24 -2
- data/Rakefile +25 -3
- data/bin/afgen +1 -1
- data/bin/cql +13 -2
- data/css/offline.css +3 -0
- data/css/orm2.css +24 -0
- data/css/print.css +8 -0
- data/css/style-print.css +357 -0
- data/css/style.css +387 -0
- data/download.html +85 -0
- data/examples/CQL/Address.cql +3 -3
- data/examples/CQL/Blog.cql +13 -14
- data/examples/CQL/CompanyDirectorEmployee.cql +4 -4
- data/examples/CQL/Death.cql +3 -2
- data/examples/CQL/Genealogy.cql +13 -11
- data/examples/CQL/Marriage.cql +2 -2
- data/examples/CQL/Metamodel.cql +136 -93
- data/examples/CQL/MultiInheritance.cql +2 -2
- data/examples/CQL/OilSupply.cql +14 -10
- data/examples/CQL/Orienteering.cql +22 -19
- data/examples/CQL/PersonPlaysGame.cql +3 -2
- data/examples/CQL/SchoolActivities.cql +4 -2
- data/examples/CQL/SimplestUnary.cql +1 -1
- data/examples/CQL/SubtypePI.cql +6 -7
- data/examples/CQL/Warehousing.cql +16 -19
- data/examples/CQL/unit.cql +584 -0
- data/examples/index.html +276 -0
- data/examples/intro.html +497 -0
- data/examples/local.css +20 -0
- data/index.html +96 -0
- data/lib/activefacts/api/concept.rb +48 -46
- data/lib/activefacts/api/constellation.rb +43 -23
- data/lib/activefacts/api/entity.rb +2 -2
- data/lib/activefacts/api/instance.rb +6 -2
- data/lib/activefacts/api/instance_index.rb +5 -0
- data/lib/activefacts/api/value.rb +8 -2
- data/lib/activefacts/api/vocabulary.rb +15 -10
- data/lib/activefacts/cql/CQLParser.treetop +109 -88
- data/lib/activefacts/cql/Concepts.treetop +32 -10
- data/lib/activefacts/cql/Context.treetop +34 -0
- data/lib/activefacts/cql/Expressions.treetop +9 -9
- data/lib/activefacts/cql/FactTypes.treetop +30 -31
- data/lib/activefacts/cql/Language/English.treetop +50 -0
- data/lib/activefacts/cql/LexicalRules.treetop +2 -1
- data/lib/activefacts/cql/Terms.treetop +117 -0
- data/lib/activefacts/cql/ValueTypes.treetop +152 -0
- data/lib/activefacts/cql/compiler.rb +1718 -0
- data/lib/activefacts/cql/parser.rb +124 -57
- data/lib/activefacts/generate/absorption.rb +1 -1
- data/lib/activefacts/generate/cql.rb +111 -100
- data/lib/activefacts/generate/cql/html.rb +5 -5
- data/lib/activefacts/generate/oo.rb +3 -3
- data/lib/activefacts/generate/ordered.rb +51 -19
- data/lib/activefacts/generate/ruby.rb +10 -8
- data/lib/activefacts/generate/sql/mysql.rb +14 -10
- data/lib/activefacts/generate/sql/server.rb +29 -24
- data/lib/activefacts/input/cql.rb +9 -1264
- data/lib/activefacts/input/orm.rb +213 -200
- data/lib/activefacts/persistence/columns.rb +11 -10
- data/lib/activefacts/persistence/index.rb +15 -18
- data/lib/activefacts/persistence/reference.rb +17 -17
- data/lib/activefacts/persistence/tables.rb +50 -51
- data/lib/activefacts/version.rb +1 -1
- data/lib/activefacts/vocabulary/extensions.rb +79 -8
- data/lib/activefacts/vocabulary/metamodel.rb +183 -114
- data/spec/absorption_ruby_spec.rb +99 -0
- data/spec/absorption_spec.rb +3 -4
- data/spec/api/constellation.rb +1 -1
- data/spec/api/entity_type.rb +3 -1
- data/spec/api/instance.rb +4 -2
- data/spec/api/roles.rb +8 -6
- data/spec/api_spec.rb +1 -2
- data/spec/cql/context_spec.rb +71 -0
- data/spec/cql/samples_spec.rb +154 -0
- data/spec/cql/unit_spec.rb +375 -0
- data/spec/cql_cql_spec.rb +31 -21
- data/spec/cql_mysql_spec.rb +70 -0
- data/spec/cql_parse_spec.rb +15 -9
- data/spec/cql_ruby_spec.rb +27 -13
- data/spec/cql_sql_spec.rb +42 -16
- data/spec/cql_symbol_tables_spec.rb +2 -3
- data/spec/cqldump_spec.rb +7 -7
- data/spec/helpers/file_matcher.rb +39 -0
- data/spec/norma_cql_spec.rb +20 -12
- data/spec/norma_ruby_spec.rb +6 -3
- data/spec/norma_sql_spec.rb +6 -3
- data/spec/norma_tables_spec.rb +6 -4
- data/spec/spec_helper.rb +27 -8
- data/status.html +69 -0
- data/why.html +60 -0
- metadata +34 -11
- data/lib/activefacts/cql/DataTypes.treetop +0 -81
- data/spec/cql_unit_spec.rb +0 -330
@@ -9,9 +9,21 @@
|
|
9
9
|
# As we build ActiveFacts objects to match, we index those in @by_id[].
|
10
10
|
# Both these hashes may be looked up by any of the ref="..." values in the file.
|
11
11
|
#
|
12
|
-
require '
|
12
|
+
require 'nokogiri'
|
13
13
|
require 'activefacts/vocabulary'
|
14
14
|
|
15
|
+
module Nokogiri
|
16
|
+
module XML
|
17
|
+
class Node
|
18
|
+
def elements
|
19
|
+
children.select{|n|
|
20
|
+
Nokogiri::XML::Element === n
|
21
|
+
}
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
15
27
|
module ActiveFacts
|
16
28
|
module Input
|
17
29
|
# Compile a NORMA (.orm) file to an ActiveFacts vocabulary.
|
@@ -38,22 +50,23 @@ module ActiveFacts
|
|
38
50
|
public
|
39
51
|
def read #:nodoc:
|
40
52
|
begin
|
41
|
-
@document =
|
53
|
+
@document = Nokogiri::XML(@file)
|
42
54
|
rescue => e
|
43
55
|
puts "Failed to parse XML in #{@filename}: #{e.inspect}"
|
44
56
|
end
|
45
57
|
|
46
58
|
# Find the Vocabulary and do some setup:
|
47
|
-
root = @document.
|
48
|
-
|
49
|
-
|
59
|
+
root = @document.root
|
60
|
+
#p((root.methods-0.methods).sort.grep(/name/))
|
61
|
+
if root.name == "ORM2" && root.namespace.prefix == "ormRoot"
|
62
|
+
x_models = root.xpath('orm:ORMModel')
|
50
63
|
throw "No vocabulary found" unless x_models.size == 1
|
51
64
|
@x_model = x_models[0]
|
52
65
|
elsif root.name == "ORMModel"
|
53
|
-
|
66
|
+
p @document.children.map(&:name)
|
67
|
+
@x_model = @document.children[0]
|
54
68
|
else
|
55
|
-
|
56
|
-
throw "NORMA vocabulary not found in file"
|
69
|
+
throw "NORMA model not found in #{@filename}"
|
57
70
|
end
|
58
71
|
|
59
72
|
read_vocabulary
|
@@ -64,12 +77,13 @@ module ActiveFacts
|
|
64
77
|
|
65
78
|
def read_vocabulary
|
66
79
|
@constellation = ActiveFacts::API::Constellation.new(ActiveFacts::Metamodel)
|
67
|
-
|
80
|
+
vocabulary_name = @x_model['Name']
|
81
|
+
@vocabulary = @constellation.Vocabulary(@x_model['Name'])
|
68
82
|
|
69
83
|
# Find all elements having an "id" attribute and index them
|
70
|
-
x_identified = @x_model.
|
84
|
+
x_identified = @x_model.xpath(".//*[@id]")
|
71
85
|
@x_by_id = x_identified.inject({}){|h, x|
|
72
|
-
id = x
|
86
|
+
id = x['id']
|
73
87
|
h[id] = x
|
74
88
|
h
|
75
89
|
}
|
@@ -91,24 +105,23 @@ module ActiveFacts
|
|
91
105
|
def read_entity_types
|
92
106
|
# get and process all the entity types:
|
93
107
|
entity_types = []
|
94
|
-
x_entity_types = @x_model.
|
108
|
+
x_entity_types = @x_model.xpath("orm:Objects/orm:EntityType")
|
95
109
|
x_entity_types.each{|x|
|
96
|
-
id = x
|
97
|
-
name = x
|
110
|
+
id = x['id']
|
111
|
+
name = x['Name'] || ""
|
98
112
|
name.gsub!(/\s/,'')
|
99
113
|
name = nil if name.size == 0
|
100
|
-
# puts "EntityType #{name} is #{id}"
|
101
114
|
entity_types <<
|
102
115
|
@by_id[id] =
|
103
116
|
entity_type =
|
104
117
|
@constellation.EntityType(@vocabulary, name)
|
105
|
-
independent = x
|
118
|
+
independent = x['IsIndependent']
|
106
119
|
entity_type.is_independent = true if independent && independent == 'true'
|
107
|
-
personal = x
|
120
|
+
personal = x['IsPersonal']
|
108
121
|
entity_type.pronoun = 'personal' if personal && personal == 'true'
|
109
|
-
# x_pref = x.
|
122
|
+
# x_pref = x.xpath("orm:PreferredIdentifier")[0]
|
110
123
|
# if x_pref
|
111
|
-
# pi_id = x_pref
|
124
|
+
# pi_id = x_pref['ref']
|
112
125
|
# @pref_id_for[pi_id] = x
|
113
126
|
# end
|
114
127
|
}
|
@@ -117,20 +130,20 @@ module ActiveFacts
|
|
117
130
|
def read_value_types
|
118
131
|
# Now the value types:
|
119
132
|
value_types = []
|
120
|
-
x_value_types = @x_model.
|
133
|
+
x_value_types = @x_model.xpath("orm:Objects/orm:ValueType")
|
121
134
|
#pp x_value_types
|
122
135
|
x_value_types.each{|x|
|
123
|
-
id = x
|
124
|
-
name = x
|
136
|
+
id = x['id']
|
137
|
+
name = x['Name'] || ""
|
125
138
|
name.gsub!(/\s/,'')
|
126
139
|
name = nil if name.size == 0
|
127
140
|
|
128
|
-
cdt = x.
|
129
|
-
scale = cdt
|
141
|
+
cdt = x.xpath('orm:ConceptualDataType')[0]
|
142
|
+
scale = cdt['Scale']
|
130
143
|
scale = scale != "" && scale.to_i
|
131
|
-
length = cdt
|
144
|
+
length = cdt['Length']
|
132
145
|
length = length != "" && length.to_i
|
133
|
-
base_type = @x_by_id[cdt
|
146
|
+
base_type = @x_by_id[cdt['ref']]
|
134
147
|
type_name = "#{base_type.name}"
|
135
148
|
type_name.sub!(/^orm:/,'')
|
136
149
|
type_name.sub!(/DataType\Z/,'')
|
@@ -139,21 +152,20 @@ module ActiveFacts
|
|
139
152
|
length = 32 if type_name =~ /Integer\Z/ && length.to_i == 0 # Set default integer length
|
140
153
|
|
141
154
|
# REVISIT: Need to handle standard types better here:
|
142
|
-
|
155
|
+
value_super_type = type_name != name ? @constellation.ValueType(@vocabulary, type_name) : nil
|
143
156
|
|
144
|
-
# puts "ValueType #{name} is #{id}"
|
145
157
|
value_types <<
|
146
158
|
@by_id[id] =
|
147
159
|
vt = @constellation.ValueType(@vocabulary, name)
|
148
|
-
vt.supertype =
|
160
|
+
vt.supertype = value_super_type
|
149
161
|
vt.length = length if length
|
150
162
|
vt.scale = scale if scale
|
151
|
-
independent = x
|
163
|
+
independent = x['IsIndependent']
|
152
164
|
vt.is_independent = true if independent && independent == 'true'
|
153
|
-
personal = x
|
165
|
+
personal = x['IsPersonal']
|
154
166
|
vt.pronoun = 'personal' if personal && personal == 'true'
|
155
167
|
|
156
|
-
x_ranges = x.
|
168
|
+
x_ranges = x.xpath("orm:ValueRestriction/orm:ValueConstraint/orm:ValueRanges/orm:ValueRange")
|
157
169
|
next if x_ranges.size == 0
|
158
170
|
vt.value_restriction = @constellation.ValueRestriction(:new)
|
159
171
|
x_ranges.each{|x_range|
|
@@ -164,35 +176,24 @@ module ActiveFacts
|
|
164
176
|
end
|
165
177
|
|
166
178
|
def value_range(x_range)
|
167
|
-
min = x_range
|
168
|
-
max = x_range
|
169
|
-
|
170
|
-
|
171
|
-
when ""; nil
|
172
|
-
when /[^0-9\.]/; q+min+q
|
173
|
-
when /\./; Float(min)
|
174
|
-
else Integer(min)
|
175
|
-
end
|
176
|
-
max = case max
|
177
|
-
when ""; nil
|
178
|
-
when /[^0-9\.]/; q+max+q
|
179
|
-
when /\./; Float(max)
|
180
|
-
else Integer(max)
|
181
|
-
end
|
179
|
+
min = x_range['MinValue']
|
180
|
+
max = x_range['MaxValue']
|
181
|
+
|
182
|
+
strings = is_a_string(min) || is_a_string(max)
|
182
183
|
# ValueRange takes a minimum and/or a maximum Bound, each takes value and whether inclusive
|
183
184
|
@constellation.ValueRange(
|
184
|
-
min ? [min
|
185
|
-
max ? [max
|
185
|
+
min && min != '' ? [[min, strings, nil], true] : nil,
|
186
|
+
max && max != '' ? [[max, strings, nil], true] : nil
|
186
187
|
)
|
187
188
|
end
|
188
189
|
|
189
190
|
def read_fact_types
|
190
191
|
# Handle the fact types:
|
191
192
|
facts = []
|
192
|
-
@x_facts = @x_model.
|
193
|
+
@x_facts = @x_model.xpath("orm:Facts/orm:Fact")
|
193
194
|
@x_facts.each{|x|
|
194
|
-
id = x
|
195
|
-
name = x
|
195
|
+
id = x['id']
|
196
|
+
name = x['Name'] || x['_Name']
|
196
197
|
name = "<unnamed>" if !name
|
197
198
|
name.gsub!(/\s/,'')
|
198
199
|
name = "" if !name || name.size == 0
|
@@ -206,29 +207,30 @@ module ActiveFacts
|
|
206
207
|
def read_subtypes
|
207
208
|
# Handle the subtype fact types:
|
208
209
|
facts = []
|
209
|
-
@x_subtypes = @x_model.
|
210
|
-
|
210
|
+
@x_subtypes = @x_model.xpath("orm:Facts/orm:SubtypeFact")
|
211
|
+
if @document.namespaces['xmlns:oialtocdb']
|
212
|
+
oialtocdb = @document.xpath("ormRoot:ORM2/oialtocdb:MappingCustomization")
|
213
|
+
@x_mappings = oialtocdb.xpath(".//oialtocdb:AssimilationMappings/oialtocdb:AssimilationMapping/oialtocdb:FactType")
|
214
|
+
else
|
215
|
+
@x_mappings = []
|
216
|
+
end
|
211
217
|
|
212
218
|
@x_subtypes.each{|x|
|
213
|
-
id = x
|
214
|
-
name = x
|
219
|
+
id = x['id']
|
220
|
+
name = x['Name'] || x['_Name'] || ''
|
215
221
|
name.gsub!(/\s/,'')
|
216
222
|
name = nil if name.size == 0
|
217
223
|
# puts "FactType #{name || id}"
|
218
224
|
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
x_subtype_role = x.elements['orm:FactRoles/orm:SubtypeMetaRole']
|
223
|
-
subtype_role_id = x_subtype_role.attributes['id']
|
224
|
-
subtype_id = x_subtype_role.elements['orm:RolePlayer'].attributes['ref']
|
225
|
+
x_subtype_role = x.xpath('orm:FactRoles/orm:SubtypeMetaRole')[0]
|
226
|
+
subtype_role_id = x_subtype_role['id']
|
227
|
+
subtype_id = x_subtype_role.xpath('orm:RolePlayer')[0]['ref']
|
225
228
|
subtype = @by_id[subtype_id]
|
226
|
-
subtype.is_independent = true if mapping_choice == 'Separate'
|
227
229
|
# REVISIT: Provide a way in the metamodel of handling Partition, (and mapping choices that vary for each supertype?)
|
228
230
|
|
229
|
-
x_supertype_role = x.
|
230
|
-
supertype_role_id = x_supertype_role
|
231
|
-
supertype_id = x_supertype_role.
|
231
|
+
x_supertype_role = x.xpath('orm:FactRoles/orm:SupertypeMetaRole')[0]
|
232
|
+
supertype_role_id = x_supertype_role['id']
|
233
|
+
supertype_id = x_supertype_role.xpath('orm:RolePlayer')[0]['ref']
|
232
234
|
supertype = @by_id[supertype_id]
|
233
235
|
|
234
236
|
throw "For Subtype fact #{name}, the supertype #{supertype_id} was not found" if !supertype
|
@@ -237,29 +239,33 @@ module ActiveFacts
|
|
237
239
|
|
238
240
|
inheritance_fact = @constellation.TypeInheritance(subtype, supertype)
|
239
241
|
inheritance_fact.fact_type_id = :new
|
240
|
-
if x
|
241
|
-
x
|
242
|
+
if x["IsPrimary"] == "true" or # Old way
|
243
|
+
x["PreferredIdentificationPath"] == "true" # Newer
|
242
244
|
# $stderr.puts "#{supertype.name} is primary supertype of #{subtype.name}"
|
243
245
|
inheritance_fact.provides_identification = true
|
244
246
|
end
|
247
|
+
mapping = @x_mappings.detect{ |m| m['ref'] == id }
|
248
|
+
mapping_choice = mapping ? mapping.parent['AbsorptionChoice'] : 'Absorbed'
|
249
|
+
inheritance_fact.assimilation = mapping_choice.downcase.sub(/partition/, 'partitioned') if mapping_choice != 'Absorbed'
|
245
250
|
facts << @by_id[id] = inheritance_fact
|
246
251
|
|
247
252
|
# Create the new Roles so we can find constraints on them:
|
248
|
-
subtype_role = @by_id[subtype_role_id] = @constellation.Role(inheritance_fact, 0, subtype)
|
249
|
-
supertype_role = @by_id[supertype_role_id] = @constellation.Role(inheritance_fact, 1, supertype)
|
253
|
+
subtype_role = @by_id[subtype_role_id] = @constellation.Role(inheritance_fact, 0, :concept => subtype)
|
254
|
+
supertype_role = @by_id[supertype_role_id] = @constellation.Role(inheritance_fact, 1, :concept => supertype)
|
250
255
|
|
251
256
|
# Create readings, so constraints can be verbalised for example:
|
252
257
|
rs = @constellation.RoleSequence(:new)
|
253
|
-
@constellation.RoleRef(rs, 0
|
254
|
-
@constellation.RoleRef(rs, 1
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
258
|
+
@constellation.RoleRef(rs, 0, :role => subtype_role)
|
259
|
+
@constellation.RoleRef(rs, 1, :role => supertype_role)
|
260
|
+
@constellation.Reading(inheritance_fact, 0, :role_sequence => rs, :text => "{0} is a kind of {1}")
|
261
|
+
@constellation.Reading(inheritance_fact, 1, :role_sequence => rs, :text => "{0} is a subtype of {1}")
|
262
|
+
|
263
|
+
rs2 = @constellation.RoleSequence(:new)
|
264
|
+
@constellation.RoleRef(rs2, 0, :role => supertype_role)
|
265
|
+
@constellation.RoleRef(rs2, 1, :role => subtype_role)
|
266
|
+
n = 'aeiouh'.include?(subtype_role.concept.name.downcase[0]) ? 1 : 0
|
267
|
+
@constellation.Reading(inheritance_fact, 2+n, :role_sequence => rs2, :text => "{0} is a {1}")
|
268
|
+
@constellation.Reading(inheritance_fact, 3-n, :role_sequence => rs2, :text => "{0} is an {1}")
|
263
269
|
|
264
270
|
# The required uniqueness constraints are already present in the NORMA file, don't duplicate them
|
265
271
|
=begin
|
@@ -295,17 +301,17 @@ module ActiveFacts
|
|
295
301
|
# We'll ignore the fact roles (and constraints) that implied objectifications have.
|
296
302
|
# This happens for all ternaries and higher order facts
|
297
303
|
nested_types = []
|
298
|
-
x_nested_types = @x_model.
|
304
|
+
x_nested_types = @x_model.xpath("orm:Objects/orm:ObjectifiedType")
|
299
305
|
x_nested_types.each{|x|
|
300
|
-
id = x
|
301
|
-
name = x
|
306
|
+
id = x['id']
|
307
|
+
name = x['Name'] || ""
|
302
308
|
name.gsub!(/\s/,'')
|
303
309
|
name = nil if name.size == 0
|
304
310
|
|
305
|
-
x_fact_type = x.
|
306
|
-
is_implied = x_fact_type
|
311
|
+
x_fact_type = x.xpath('orm:NestedPredicate')[0]
|
312
|
+
is_implied = x_fact_type['IsImplied'] == "true"
|
307
313
|
|
308
|
-
fact_id = x_fact_type
|
314
|
+
fact_id = x_fact_type['ref']
|
309
315
|
fact_type = @by_id[fact_id]
|
310
316
|
throw "Nested fact #{fact_id} not found" if !fact_type
|
311
317
|
|
@@ -325,67 +331,67 @@ module ActiveFacts
|
|
325
331
|
|
326
332
|
def read_roles
|
327
333
|
@x_facts.each{|x|
|
328
|
-
id = x
|
334
|
+
id = x['id']
|
329
335
|
fact_type = @by_id[id]
|
330
|
-
fact_name = x
|
336
|
+
fact_name = x['Name'] || x['_Name'] || ''
|
331
337
|
fact_name.gsub!(/\s/,'')
|
332
338
|
fact_name = nil if fact_name == ''
|
333
339
|
|
334
|
-
x_fact_roles = x.
|
335
|
-
x_reading_orders = x.
|
340
|
+
x_fact_roles = x.xpath('orm:FactRoles/*')
|
341
|
+
x_reading_orders = x.xpath('orm:ReadingOrders/*')
|
336
342
|
|
337
343
|
# Deal with FactRoles (Roles):
|
338
344
|
x_fact_roles.each{|x|
|
339
|
-
name = x
|
345
|
+
name = x['Name'] || ""
|
340
346
|
name.gsub!(/\s/,'')
|
341
347
|
name = nil if name.size == 0
|
342
348
|
|
343
|
-
# _IsMandatory = x
|
344
|
-
# _Multiplicity = x
|
345
|
-
id = x
|
346
|
-
ref = x.
|
349
|
+
# _IsMandatory = x['_IsMandatory']
|
350
|
+
# _Multiplicity = x['_Multiplicity]
|
351
|
+
id = x['id']
|
352
|
+
ref = x.xpath('orm:RolePlayer')[0]['ref']
|
347
353
|
|
348
354
|
# Find the concept that plays the role:
|
349
355
|
concept = @by_id[ref]
|
350
|
-
throw "RolePlayer for #{name
|
356
|
+
throw "RolePlayer for '#{name}' #{ref} was not found" if !concept
|
351
357
|
|
352
358
|
# Skip implicit roles added by NORMA to make unaries into binaries.
|
353
359
|
# This would make constraints over the deleted roles impossible,
|
354
360
|
# so as a SPECIAL CASE we index the unary role by the id of the
|
355
361
|
# implicit role. That means care is needed when handling unary FTs.
|
356
|
-
if (ox = @x_by_id[ref]) && ox
|
357
|
-
x_other_role = x.parent.
|
362
|
+
if (ox = @x_by_id[ref]) && ox['IsImplicitBooleanValue']
|
363
|
+
x_other_role = x.parent.xpath('orm:Role').reject{|x_role|
|
358
364
|
x_role == x
|
359
365
|
}[0]
|
360
|
-
other_role_id = x_other_role
|
366
|
+
other_role_id = x_other_role["id"]
|
361
367
|
other_role = @by_id[other_role_id]
|
362
368
|
# puts "Indexing unary FT role #{other_role_id} by implicit boolean role #{id}"
|
363
369
|
@by_id[id] = other_role
|
364
370
|
|
365
371
|
# The role name of the ignored role is the one that applies:
|
366
|
-
role_name = x
|
372
|
+
role_name = x['Name']
|
367
373
|
other_role.role_name = role_name if role_name && role_name != ''
|
368
374
|
|
369
|
-
concept.
|
375
|
+
concept.deny # Delete our object for the implicit boolean ValueType
|
370
376
|
@by_id.delete(ref) # and de-index it from our list
|
371
377
|
next
|
372
378
|
end
|
373
379
|
|
374
|
-
#puts "#{@vocabulary}, Name=#{x
|
380
|
+
#puts "#{@vocabulary}, Name=#{x['Name']}, concept=#{concept}"
|
375
381
|
throw "Role is played by #{concept.class} not Concept" if !(@constellation.vocabulary.concept(:Concept) === concept)
|
376
382
|
|
377
|
-
name = x
|
383
|
+
name = x['Name'] || ''
|
378
384
|
name.gsub!(/\s/,'')
|
379
385
|
name = nil if name.size == 0
|
380
386
|
#puts "Creating role #{name} nr#{fact_type.all_role.size} of #{fact_type.fact_type_id} played by #{concept.name}"
|
381
387
|
|
382
|
-
role = @by_id[id] = @constellation.Role(fact_type, fact_type.all_role.size, concept)
|
388
|
+
role = @by_id[id] = @constellation.Role(fact_type, fact_type.all_role.size, :concept => concept)
|
383
389
|
role.role_name = name if name
|
384
|
-
# puts "Fact #{fact_name} (id #{fact_type.fact_type_id.object_id}) role #{x
|
390
|
+
# puts "Fact #{fact_name} (id #{fact_type.fact_type_id.object_id}) role #{x['Name']} is played by #{concept.name}, role is #{role.object_id}"
|
385
391
|
|
386
|
-
x_vr = x.
|
392
|
+
x_vr = x.xpath("orm:ValueRestriction")
|
387
393
|
x_vr.each{|vr|
|
388
|
-
x_ranges = vr.
|
394
|
+
x_ranges = vr.xpath("orm:RoleValueConstraint/orm:ValueRanges/orm:ValueRange")
|
389
395
|
next if x_ranges.size == 0
|
390
396
|
role.role_value_restriction = @constellation.ValueRestriction(:new)
|
391
397
|
x_ranges.each{|x_range|
|
@@ -401,11 +407,11 @@ module ActiveFacts
|
|
401
407
|
|
402
408
|
# Deal with Readings:
|
403
409
|
x_reading_orders.each{|x|
|
404
|
-
x_role_sequence = x.
|
405
|
-
x_readings = x.
|
410
|
+
x_role_sequence = x.xpath('orm:RoleSequence/*')
|
411
|
+
x_readings = x.xpath('orm:Readings/orm:Reading/orm:Data')
|
406
412
|
|
407
413
|
# Build an array of the Roles needed:
|
408
|
-
role_array = x_role_sequence.map{|x| @by_id[x
|
414
|
+
role_array = x_role_sequence.map{|x| @by_id[x['ref']] }
|
409
415
|
|
410
416
|
# puts "Reading #{x_readings.map(&:text).inspect}"
|
411
417
|
role_sequence = get_role_sequence(role_array)
|
@@ -418,14 +424,14 @@ module ActiveFacts
|
|
418
424
|
reading = @constellation.Reading(fact_type, fact_type.all_reading.size)
|
419
425
|
reading.role_sequence = role_sequence
|
420
426
|
# REVISIT: The downcase here only needs to be the initial letter of each word, but be safe:
|
421
|
-
reading.
|
427
|
+
reading.text = extract_adjectives(x.text, role_sequence).downcase
|
422
428
|
}
|
423
429
|
}
|
424
430
|
}
|
425
431
|
# @vocabulary.fact_types.each{|ft| puts ft }
|
426
432
|
end
|
427
433
|
|
428
|
-
def extract_adjectives(
|
434
|
+
def extract_adjectives(text, role_sequence)
|
429
435
|
all_role_refs = role_sequence.all_role_ref.sort_by{|rr| rr.ordinal}
|
430
436
|
(0...all_role_refs.size).each{|i|
|
431
437
|
role_ref = all_role_refs[i]
|
@@ -437,22 +443,22 @@ module ActiveFacts
|
|
437
443
|
role_with_adjectives_re =
|
438
444
|
%r| ?#{leading_adjectives_re}?\{#{i}\}#{trailing_adjectives_re}? ?|
|
439
445
|
|
440
|
-
|
446
|
+
text.gsub!(role_with_adjectives_re) {
|
441
447
|
la = [[$1]*"", [$2]*""]*" ".gsub(/\s+/, ' ').sub(/\s+\Z/,'').strip
|
442
448
|
ta = [[$1]*"", [$2]*""]*" ".gsub(/\s+/, ' ').sub(/\A\s+/,'').strip
|
443
|
-
#puts "Setting leading adj #{la.inspect} from #{
|
449
|
+
#puts "Setting leading adj #{la.inspect} from #{text.inspect} for #{role_ref.role.concept.name}" if la != ""
|
444
450
|
# REVISIT: Dunno what's up here, but removing the "if" test makes this chuck exceptions:
|
445
451
|
role_ref.leading_adjective = la if la != ""
|
446
452
|
role_ref.trailing_adjective = ta if ta != ""
|
447
453
|
|
448
|
-
#puts "Reading '#{
|
454
|
+
#puts "Reading '#{text}' has role #{i} adjectives '#{la}' '#{ta}'" if la != "" || ta != ""
|
449
455
|
|
450
456
|
" {#{i}} "
|
451
457
|
}
|
452
458
|
}
|
453
|
-
|
454
|
-
|
455
|
-
|
459
|
+
text.sub!(/\A /, '')
|
460
|
+
text.sub!(/ \Z/, '')
|
461
|
+
text
|
456
462
|
end
|
457
463
|
|
458
464
|
def get_role_sequence(role_array)
|
@@ -478,18 +484,18 @@ module ActiveFacts
|
|
478
484
|
|
479
485
|
def map_roles(x_roles, why = nil)
|
480
486
|
role_array = x_roles.map{|x|
|
481
|
-
id = x
|
487
|
+
id = x['ref']
|
482
488
|
role = @by_id[id]
|
483
489
|
if (why && !role)
|
484
490
|
# We didn't make Implied objects, so some constraints are unconnectable
|
485
491
|
x_role = @x_by_id[id]
|
486
|
-
x_player = x_role.
|
487
|
-
x_object = @x_by_id[x_player
|
492
|
+
x_player = x_role.xpath('orm:RolePlayer')[0]
|
493
|
+
x_object = @x_by_id[x_player['ref']]
|
488
494
|
x_nests = nil
|
489
495
|
if (x_object.name.to_s == 'ObjectifiedType')
|
490
|
-
x_nests = x_object.
|
491
|
-
implied = x_nests
|
492
|
-
x_fact = @x_by_id[x_nests
|
496
|
+
x_nests = x_object.xpath('orm:NestedPredicate')[0]
|
497
|
+
implied = x_nests['IsImplied']
|
498
|
+
x_fact = @x_by_id[x_nests['ref']]
|
493
499
|
end
|
494
500
|
|
495
501
|
# This might have been a role of an ImpliedFact, which makes it safe to ignore.
|
@@ -526,38 +532,38 @@ module ActiveFacts
|
|
526
532
|
end
|
527
533
|
|
528
534
|
def read_mandatory_constraints
|
529
|
-
x_mandatory_constraints = @x_model.
|
535
|
+
x_mandatory_constraints = @x_model.xpath("orm:Constraints/orm:MandatoryConstraint")
|
530
536
|
@mandatory_constraints_by_rs = {}
|
531
537
|
@mandatory_constraint_rs_by_id = {}
|
532
538
|
x_mandatory_constraints.each{|x|
|
533
|
-
name = x
|
539
|
+
name = x["Name"] || ''
|
534
540
|
name.gsub!(/\s/,'')
|
535
541
|
name = nil if name.size == 0
|
536
542
|
|
537
543
|
# As of Feb 2008, all NORMA ValueTypes have an implied mandatory constraint.
|
538
|
-
if x.
|
544
|
+
if x.xpath("orm:ImpliedByObjectType").size > 0
|
539
545
|
# $stderr.puts "Skipping ImpliedMandatoryConstraint #{name} over #{roles}"
|
540
546
|
next
|
541
547
|
end
|
542
548
|
|
543
|
-
x_roles = x.
|
549
|
+
x_roles = x.xpath("orm:RoleSequence/orm:Role")
|
544
550
|
roles = map_roles(x_roles, "mandatory constraint #{name}")
|
545
551
|
next if !roles
|
546
552
|
|
547
553
|
# If X-OR mandatory, the Exclusion is accessed by:
|
548
|
-
# x_exclusion = (ex = x.
|
549
|
-
# @x_by_id[ex
|
550
|
-
# puts "Mandatory #{name}(#{roles}) is paired with exclusive #{x_exclusion
|
554
|
+
# x_exclusion = (ex = x.xpath("orm:ExclusiveOrExclusionConstraint")[0]) &&
|
555
|
+
# @x_by_id[ex['ref']]
|
556
|
+
# puts "Mandatory #{name}(#{roles}) is paired with exclusive #{x_exclusion['Name']}" if x_exclusion
|
551
557
|
|
552
558
|
@mandatory_constraints_by_rs[roles] = x
|
553
|
-
@mandatory_constraint_rs_by_id[x
|
559
|
+
@mandatory_constraint_rs_by_id[x['id']] = roles
|
554
560
|
}
|
555
561
|
end
|
556
562
|
|
557
563
|
def read_residual_mandatory_constraints
|
558
564
|
@mandatory_constraints_by_rs.each { |roles, x|
|
559
565
|
# Create a simply-mandatory PresenceConstraint for each mandatory constraint
|
560
|
-
name = x
|
566
|
+
name = x["Name"] || ''
|
561
567
|
name.gsub!(/\s/,'')
|
562
568
|
name = nil if name.size == 0
|
563
569
|
#puts "Residual Mandatory #{name}: #{roles.to_s}"
|
@@ -576,14 +582,14 @@ module ActiveFacts
|
|
576
582
|
end
|
577
583
|
|
578
584
|
def read_uniqueness_constraints
|
579
|
-
x_uniqueness_constraints = @x_model.
|
585
|
+
x_uniqueness_constraints = @x_model.xpath("orm:Constraints/orm:UniquenessConstraint")
|
580
586
|
x_uniqueness_constraints.each{|x|
|
581
|
-
name = x
|
587
|
+
name = x["Name"] || ''
|
582
588
|
name.gsub!(/\s/,'')
|
583
589
|
name = nil if name.size == 0
|
584
|
-
id = x
|
585
|
-
x_pi = x.
|
586
|
-
pi = x_pi ? @by_id[eref = x_pi
|
590
|
+
id = x["id"]
|
591
|
+
x_pi = x.xpath("orm:PreferredIdentifierFor")[0]
|
592
|
+
pi = x_pi ? @by_id[eref = x_pi['ref']] : nil
|
587
593
|
|
588
594
|
# Skip uniqueness constraints on implied concepts
|
589
595
|
if x_pi && !pi
|
@@ -594,34 +600,36 @@ module ActiveFacts
|
|
594
600
|
# A uniqueness constraint on a fact having an implied objectification isn't preferred:
|
595
601
|
# if pi &&
|
596
602
|
# (x_pi_for = @x_by_id[eref]) &&
|
597
|
-
# (np = x_pi_for.
|
598
|
-
# np
|
603
|
+
# (np = x_pi_for.xpath('orm:NestedPredicate')[0]) &&
|
604
|
+
# np['IsImplied']
|
599
605
|
# pi = nil
|
600
606
|
# end
|
601
607
|
|
602
608
|
# Get the RoleSequence:
|
603
|
-
x_roles = x.
|
609
|
+
x_roles = x.xpath("orm:RoleSequence/orm:Role")
|
604
610
|
next if x_roles.size == 0
|
605
611
|
roles = map_roles(x_roles, "uniqueness constraint #{name}")
|
606
612
|
next if !roles
|
607
613
|
|
608
614
|
# There is an implicit uniqueness constraint when any object plays a unary. Skip it.
|
609
615
|
if (x_roles.size == 1 &&
|
610
|
-
(id = x_roles[0]
|
616
|
+
(id = x_roles[0]['ref']) &&
|
611
617
|
(x_role = @x_by_id[id]) &&
|
612
|
-
x_role.parent.elements.size == 2 &&
|
613
|
-
(sibling =
|
614
|
-
|
618
|
+
(nodes = x_role.parent.elements).size == 2 &&
|
619
|
+
(sibling = nodes[1]) &&
|
620
|
+
# x_role.parent.children.size == 2 &&
|
621
|
+
# (sibling = x_role.parent.children[1]) &&
|
622
|
+
(ib_id = sibling.elements[0]['ref']) &&
|
615
623
|
(ib = @x_by_id[ib_id]) &&
|
616
|
-
ib
|
624
|
+
ib['IsImplicitBooleanValue'])
|
617
625
|
unary_identifier = true
|
618
626
|
end
|
619
627
|
|
620
628
|
if (mc = @mandatory_constraints_by_rs[roles])
|
621
629
|
# Remove absorbed mandatory constraints, leaving residual ones.
|
622
|
-
# puts "Absorbing MC #{mc
|
630
|
+
# puts "Absorbing MC #{mc['Name']}"
|
623
631
|
@mandatory_constraints_by_rs.delete(roles)
|
624
|
-
@mandatory_constraint_rs_by_id.delete(mc
|
632
|
+
@mandatory_constraint_rs_by_id.delete(mc['id'])
|
625
633
|
end
|
626
634
|
|
627
635
|
# A UC that spans more than one Role of a fact will be a Preferred Id for the implied object
|
@@ -656,18 +664,18 @@ module ActiveFacts
|
|
656
664
|
end
|
657
665
|
|
658
666
|
def read_exclusion_constraints
|
659
|
-
x_exclusion_constraints = @x_model.
|
667
|
+
x_exclusion_constraints = @x_model.xpath("orm:Constraints/orm:ExclusionConstraint")
|
660
668
|
x_exclusion_constraints.each{|x|
|
661
|
-
name = x
|
669
|
+
name = x["Name"] || ''
|
662
670
|
name.gsub!(/\s/,'')
|
663
671
|
name = nil if name.size == 0
|
664
|
-
x_mandatory = (m = x.
|
665
|
-
@x_by_id[mc_id = m
|
672
|
+
x_mandatory = (m = x.xpath("orm:ExclusiveOrMandatoryConstraint")[0]) &&
|
673
|
+
@x_by_id[mc_id = m['ref']]
|
666
674
|
role_sequences =
|
667
|
-
x.
|
668
|
-
x_role_refs = x_rs.
|
675
|
+
x.xpath("orm:RoleSequences/orm:RoleSequence").map{|x_rs|
|
676
|
+
x_role_refs = x_rs.xpath("orm:Role")
|
669
677
|
map_roles(
|
670
|
-
x_role_refs , # .map{|xr| @x_by_id[xr
|
678
|
+
x_role_refs , # .map{|xr| @x_by_id[xr['ref']] },
|
671
679
|
"exclusion constraint #{name}"
|
672
680
|
)
|
673
681
|
}
|
@@ -690,16 +698,16 @@ module ActiveFacts
|
|
690
698
|
end
|
691
699
|
|
692
700
|
def read_equality_constraints
|
693
|
-
x_equality_constraints = @x_model.
|
701
|
+
x_equality_constraints = @x_model.xpath("orm:Constraints/orm:EqualityConstraint")
|
694
702
|
x_equality_constraints.each{|x|
|
695
|
-
name = x
|
703
|
+
name = x["Name"] || ''
|
696
704
|
name.gsub!(/\s/,'')
|
697
705
|
name = nil if name.size == 0
|
698
706
|
role_sequences =
|
699
|
-
x.
|
700
|
-
x_role_refs = x_rs.
|
707
|
+
x.xpath("orm:RoleSequences/orm:RoleSequence").map{|x_rs|
|
708
|
+
x_role_refs = x_rs.xpath("orm:Role")
|
701
709
|
map_roles(
|
702
|
-
x_role_refs , # .map{|xr| @x_by_id[xr
|
710
|
+
x_role_refs , # .map{|xr| @x_by_id[xr['ref']] },
|
703
711
|
"equality constraint #{name}"
|
704
712
|
)
|
705
713
|
}
|
@@ -715,16 +723,16 @@ module ActiveFacts
|
|
715
723
|
end
|
716
724
|
|
717
725
|
def read_subset_constraints
|
718
|
-
x_subset_constraints = @x_model.
|
726
|
+
x_subset_constraints = @x_model.xpath("orm:Constraints/orm:SubsetConstraint")
|
719
727
|
x_subset_constraints.each{|x|
|
720
|
-
name = x
|
728
|
+
name = x["Name"] || ''
|
721
729
|
name.gsub!(/\s/,'')
|
722
730
|
name = nil if name.size == 0
|
723
731
|
role_sequences =
|
724
|
-
x.
|
725
|
-
x_role_refs = x_rs.
|
732
|
+
x.xpath("orm:RoleSequences/orm:RoleSequence").map{|x_rs|
|
733
|
+
x_role_refs = x_rs.xpath("orm:Role")
|
726
734
|
map_roles(
|
727
|
-
x_role_refs , # .map{|xr| @x_by_id[xr
|
735
|
+
x_role_refs , # .map{|xr| @x_by_id[xr['ref']] },
|
728
736
|
"equality constraint #{name}"
|
729
737
|
)
|
730
738
|
}
|
@@ -739,12 +747,12 @@ module ActiveFacts
|
|
739
747
|
end
|
740
748
|
|
741
749
|
def read_ring_constraints
|
742
|
-
x_ring_constraints = @x_model.
|
750
|
+
x_ring_constraints = @x_model.xpath("orm:Constraints/orm:RingConstraint")
|
743
751
|
x_ring_constraints.each{|x|
|
744
|
-
name = x
|
752
|
+
name = x["Name"] || ''
|
745
753
|
name.gsub!(/\s/,'')
|
746
754
|
name = nil if name.size == 0
|
747
|
-
type = x
|
755
|
+
type = x["Type"]
|
748
756
|
# begin
|
749
757
|
# # Convert the RingConstraint name to a number:
|
750
758
|
# type_num = eval("::ActiveFacts::RingConstraint::#{type}")
|
@@ -752,8 +760,8 @@ module ActiveFacts
|
|
752
760
|
# throw "RingConstraint type #{type} isn't known"
|
753
761
|
# end
|
754
762
|
|
755
|
-
from, to = *x.
|
756
|
-
@by_id[xr
|
763
|
+
from, to = *x.xpath("orm:RoleSequence/orm:Role").map{|xr|
|
764
|
+
@by_id[xr['ref']]
|
757
765
|
}
|
758
766
|
rc = @constellation.RingConstraint(:new)
|
759
767
|
rc.vocabulary = @vocabulary
|
@@ -766,7 +774,7 @@ module ActiveFacts
|
|
766
774
|
end
|
767
775
|
|
768
776
|
def read_frequency_constraints
|
769
|
-
x_frequency_constraints = @x_model.
|
777
|
+
x_frequency_constraints = @x_model.xpath("orm:Constraints/orm:FrequencyConstraint")
|
770
778
|
# REVISIT: FrequencyConstraints not handled yet
|
771
779
|
end
|
772
780
|
|
@@ -775,39 +783,39 @@ module ActiveFacts
|
|
775
783
|
|
776
784
|
# Value instances first, then entities then facts:
|
777
785
|
|
778
|
-
x_values = @x_model.
|
779
|
-
#pp x_values.map{|v| [ v.parent
|
786
|
+
x_values = @x_model.xpath("orm:Objects/orm:ValueType/orm:Instances/orm:ValueTypeInstance/orm:Value")
|
787
|
+
#pp x_values.map{|v| [ v.parent['id'], v.text ] }
|
780
788
|
x_values.each{|v|
|
781
|
-
id = v.parent
|
789
|
+
id = v.parent['id']
|
782
790
|
# Get details of the ValueType:
|
783
791
|
xvt = v.parent.parent.parent
|
784
|
-
vt_id = xvt
|
785
|
-
vtname = xvt
|
792
|
+
vt_id = xvt['id']
|
793
|
+
vtname = xvt['Name'] || ''
|
786
794
|
vtname.gsub!(/\s/,'')
|
787
795
|
vtname = nil if name.size == 0
|
788
796
|
vt = @by_id[vt_id]
|
789
797
|
throw "ValueType #{vtname} not found" unless vt
|
790
798
|
|
791
|
-
i = Instance.new(vt, v.text)
|
799
|
+
i = Instance.new(vt, [v.text, is_a_string(v.text), nil])
|
792
800
|
@by_id[id] = i
|
793
801
|
# show_xmlobj(v)
|
794
802
|
}
|
795
803
|
|
796
804
|
# Use the "id" attribute of EntityTypeInstance
|
797
|
-
x_entities = @x_model.
|
805
|
+
x_entities = @x_model.xpath("orm:Objects/orm:EntityType/orm:Instances/orm:EntityTypeInstance")
|
798
806
|
#pp x_entities
|
799
807
|
# x_entities.each{|v| show_xmlobj(v) }
|
800
808
|
last_et_id = nil
|
801
809
|
last_et = nil
|
802
810
|
et = nil
|
803
811
|
x_entities.each{|v|
|
804
|
-
id = v
|
812
|
+
id = v['id']
|
805
813
|
|
806
814
|
# Get details of the EntityType:
|
807
815
|
xet = v.parent.parent
|
808
|
-
et_id = xet
|
816
|
+
et_id = xet['id']
|
809
817
|
if (et_id != last_et_id)
|
810
|
-
etname = xet
|
818
|
+
etname = xet['Name'] || ''
|
811
819
|
etname.gsub!(/\s/,'')
|
812
820
|
etname = nil if name.size == 0
|
813
821
|
last_et = et = @by_id[et_id]
|
@@ -815,7 +823,7 @@ module ActiveFacts
|
|
815
823
|
throw "EntityType #{etname} not found" unless et
|
816
824
|
end
|
817
825
|
|
818
|
-
instance = Instance.new(et)
|
826
|
+
instance = Instance.new(et, nil)
|
819
827
|
@by_id[id] = instance
|
820
828
|
# puts "Made new EntityType #{etname}"
|
821
829
|
}
|
@@ -825,19 +833,19 @@ module ActiveFacts
|
|
825
833
|
entity_count = 0
|
826
834
|
pi_fact_count = 0
|
827
835
|
x_entities.each{|v|
|
828
|
-
id = v
|
836
|
+
id = v['id']
|
829
837
|
instance = @by_id[id]
|
830
|
-
et = @by_id[v.parent.parent
|
838
|
+
et = @by_id[v.parent.parent['id']]
|
831
839
|
next unless (preferred_id = et.preferred_identifier)
|
832
840
|
|
833
841
|
# puts "Create identifying facts using #{preferred_id}"
|
834
842
|
|
835
843
|
# Collate the referenced objects by role:
|
836
|
-
role_instances = v.elements[
|
837
|
-
etri = @x_by_id[v
|
838
|
-
x_role_id = etri.parent.parent
|
844
|
+
role_instances = v.elements[0].elements.inject({}){|h, v|
|
845
|
+
etri = @x_by_id[v['ref']]
|
846
|
+
x_role_id = etri.parent.parent['id']
|
839
847
|
role = @by_id[x_role_id]
|
840
|
-
object = @by_id[object_id = etri
|
848
|
+
object = @by_id[object_id = etri['ref']]
|
841
849
|
h[role] = object
|
842
850
|
h
|
843
851
|
}
|
@@ -862,14 +870,14 @@ module ActiveFacts
|
|
862
870
|
# puts "Created #{pi_fact_count} facts to identify #{entity_count} entities"
|
863
871
|
|
864
872
|
# Use the "ref" attribute of FactTypeRoleInstance:
|
865
|
-
x_fact_roles = @x_model.
|
873
|
+
x_fact_roles = @x_model.xpath("orm:Facts/orm:Fact/orm:Instances/orm:FactTypeInstance/orm:RoleInstances/orm:FactTypeRoleInstance")
|
866
874
|
|
867
875
|
last_id = nil
|
868
876
|
last_fact_type = nil
|
869
877
|
fact_roles = []
|
870
878
|
x_fact_roles.each{|v|
|
871
|
-
fact_type_id = v.parent.parent.parent.parent
|
872
|
-
id = v.parent.parent
|
879
|
+
fact_type_id = v.parent.parent.parent.parent['id']
|
880
|
+
id = v.parent.parent['id']
|
873
881
|
fact_type = @by_id[fact_type_id]
|
874
882
|
throw "Fact type #{fact_type_id} not found" unless fact_type
|
875
883
|
|
@@ -884,11 +892,11 @@ module ActiveFacts
|
|
884
892
|
#show_xmlobj(v)
|
885
893
|
|
886
894
|
last_id = id
|
887
|
-
x_role_instance = @x_by_id[v
|
888
|
-
x_role_id = x_role_instance.parent.parent
|
895
|
+
x_role_instance = @x_by_id[v['ref']]
|
896
|
+
x_role_id = x_role_instance.parent.parent['id']
|
889
897
|
role = @by_id[x_role_id]
|
890
898
|
throw "Role not found for instance #{x_role_id}" unless role
|
891
|
-
instance_id = x_role_instance
|
899
|
+
instance_id = x_role_instance['ref']
|
892
900
|
instance = @by_id[instance_id]
|
893
901
|
throw "Instance not found for FactRole #{instance_id}" unless instance
|
894
902
|
fact_roles << FactRole.new(role, instance)
|
@@ -901,20 +909,25 @@ module ActiveFacts
|
|
901
909
|
|
902
910
|
end
|
903
911
|
|
912
|
+
# Detect numeric data and denote it as a string:
|
913
|
+
def is_a_string(value)
|
914
|
+
value =~ /[^ \d.]/
|
915
|
+
end
|
916
|
+
|
904
917
|
def read_rest
|
905
918
|
puts "Reading Implied Facts (not yet)"
|
906
919
|
=begin
|
907
|
-
x_implied_facts = @x_model.
|
920
|
+
x_implied_facts = @x_model.xpath("orm:Facts/orm:ImpliedFact")
|
908
921
|
pp x_implied_facts
|
909
922
|
=end
|
910
923
|
puts "Reading Data Types (not yet)"
|
911
924
|
=begin
|
912
|
-
x_datatypes = @x_model.
|
925
|
+
x_datatypes = @x_model.xpath("orm:DataTypes/*")
|
913
926
|
pp x_datatypes
|
914
927
|
=end
|
915
928
|
puts "Reading Reference Mode Kinds (not yet)"
|
916
929
|
=begin
|
917
|
-
x_refmodekinds = @x_model.
|
930
|
+
x_refmodekinds = @x_model.xpath("orm:ReferenceModeKinds/*")
|
918
931
|
pp x_refmodekinds
|
919
932
|
=end
|
920
933
|
end
|
@@ -931,9 +944,9 @@ module ActiveFacts
|
|
931
944
|
parentage.each{|p|
|
932
945
|
next if REXML::Document === p
|
933
946
|
puts "#{indent}\t#{p.name}#{
|
934
|
-
}#{(n = p
|
935
|
-
}#{(id = p
|
936
|
-
}#{(ref = p
|
947
|
+
}#{(n = p['Name']) ? " Name='#{n}'" : ""
|
948
|
+
}#{(id = p['id']) ? " #{id}" : ""
|
949
|
+
}#{(ref = p['ref']) ? " -> #{ref}" : ""
|
937
950
|
}#{/\S/ === ((text = p.text)) ? " "+text.inspect : ""
|
938
951
|
}"
|
939
952
|
show_xmlobj(@x_by_id[ref], "\t#{indent}") if ref
|