activefacts 0.7.3 → 0.8.5
Sign up to get free protection for your applications and to get access to all the features.
- 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
|