rtm 0.1.6 → 0.2.0
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/DISCLAIMER +10 -33
- data/LICENSE +201 -0
- data/README +3 -3
- data/lib/rtm.rb +148 -74
- data/lib/rtm/axes.rb +295 -0
- data/lib/rtm/axes/association.rb +76 -0
- data/lib/rtm/axes/associations.rb +96 -0
- data/lib/rtm/axes/assocs_names_occs.rb +56 -0
- data/lib/rtm/axes/characteristic.rb +68 -0
- data/lib/rtm/axes/characteristics.rb +93 -0
- data/lib/rtm/axes/string.rb +76 -0
- data/lib/rtm/axes/strings.rb +87 -0
- data/lib/rtm/axes/topic.rb +233 -0
- data/lib/rtm/axes/topics.rb +280 -0
- data/lib/rtm/{backward_compatibility.rb → deprecated/index_property_set.rb} +3 -0
- data/lib/rtm/engine.rb +58 -0
- data/lib/rtm/extensions.rb +11 -1
- data/lib/rtm/{locator_helpers.rb → helpers/locator.rb} +15 -4
- data/lib/rtm/{helpers.rb → helpers/no_output.rb} +3 -0
- data/lib/rtm/helpers/uri.rb +13 -0
- data/lib/rtm/io.rb +18 -0
- data/lib/rtm/io/from_xtm2_libxml.rb +2 -1
- data/lib/rtm/io/ontopia_io.rb +25 -0
- data/lib/rtm/io/tmapix.rb +234 -0
- data/lib/rtm/io/to_hash.rb +116 -0
- data/lib/rtm/io/to_jtm.rb +53 -103
- data/lib/rtm/io/to_rdf.rb +30 -0
- data/lib/rtm/io/to_string.rb +8 -6
- data/lib/rtm/io/to_xtm1.rb +6 -4
- data/lib/rtm/io/to_xtm2.rb +10 -8
- data/lib/rtm/io/to_yaml.rb +29 -98
- data/lib/rtm/navigation.rb +37 -0
- data/lib/rtm/navigation/association/players.rb +25 -0
- data/lib/rtm/navigation/name/atomify.rb +19 -0
- data/lib/rtm/navigation/name/characteristics.rb +33 -0
- data/lib/rtm/navigation/occurrence/atomify.rb +19 -0
- data/lib/rtm/navigation/occurrence/characteristics.rb +33 -0
- data/lib/rtm/navigation/topic/characteristics.rb +33 -0
- data/lib/rtm/navigation/topic/indicators.rb +31 -0
- data/lib/rtm/navigation/topic/items.rb +31 -0
- data/lib/rtm/navigation/topic/locators.rb +31 -0
- data/lib/rtm/navigation/topic/players.rb +27 -0
- data/lib/rtm/navigation/topic/supertypes.rb +162 -0
- data/lib/rtm/navigation/topic/traverse.rb +51 -0
- data/lib/rtm/navigation/topic/types.rb +107 -0
- data/lib/rtm/psi.rb +33 -2
- data/lib/rtm/sugar.rb +34 -0
- data/lib/rtm/sugar/association/hash_access.rb +46 -0
- data/lib/rtm/sugar/occurrence/dynamic_value.rb +75 -0
- data/lib/rtm/{pimp_my_api.rb → sugar/occurrence/externalize.rb} +3 -0
- data/lib/rtm/sugar/role/counterparts.rb +133 -46
- data/lib/rtm/sugar/topic/characteristics.rb +126 -12
- data/lib/rtm/sugar/topic/counterparts.rb +130 -7
- data/lib/rtm/sugar/topic/hash_access.rb +140 -30
- data/lib/rtm/sugar/topic/scoped.rb +65 -0
- data/lib/rtm/sugar/topic/topic_ref.rb +35 -0
- data/lib/rtm/sugar/topic/typed.rb +159 -0
- data/lib/rtm/sugar/typed/types.rb +38 -0
- data/lib/rtm/validation.rb +8 -5
- data/lib/rtm/version.rb +18 -0
- data/spec/helpers/spec_exampleexamplegroup.rb +14 -0
- data/spec/rtm/axes/association_spec.rb +88 -0
- data/spec/rtm/axes/associations_spec.rb +60 -0
- data/spec/rtm/axes/assocs_names_occs_spec.rb +9 -0
- data/spec/rtm/axes/characteristic_spec.rb +90 -0
- data/spec/rtm/axes/characteristics_spec.rb +85 -0
- data/spec/rtm/axes/string_spec.rb +145 -0
- data/spec/rtm/axes/strings_spec.rb +168 -0
- data/spec/rtm/axes/topic_spec.rb +124 -0
- data/spec/rtm/axes/topics_spec.rb +103 -0
- data/spec/rtm/base_spec.rb +32 -0
- data/spec/rtm/io/tmapix_spec.rb +85 -0
- data/spec/rtm/navigation/association/players_spec.rb +58 -0
- data/spec/rtm/navigation/association_spec.rb +52 -0
- data/spec/rtm/navigation/name/atomify_spec.rb +27 -0
- data/spec/rtm/navigation/name/characteristics_spec.rb +34 -0
- data/spec/rtm/navigation/name_spec.rb +52 -0
- data/spec/rtm/navigation/occurrence/atomify_spec.rb +27 -0
- data/spec/rtm/navigation/occurrence/characteristics_spec.rb +34 -0
- data/spec/rtm/navigation/occurrence_spec.rb +52 -0
- data/spec/rtm/navigation/string_spec.rb +51 -0
- data/spec/rtm/navigation/topic/characteristics_spec.rb +55 -0
- data/spec/rtm/navigation/topic/indicators_spec.rb +43 -0
- data/spec/rtm/navigation/topic/items_spec.rb +44 -0
- data/spec/rtm/navigation/topic/locators_spec.rb +44 -0
- data/spec/rtm/navigation/topic/players_spec.rb +48 -0
- data/spec/rtm/navigation/topic/scope_spec.rb +41 -0
- data/spec/rtm/navigation/topic/supertypes_spec.rb +376 -0
- data/spec/rtm/navigation/topic/traverse_spec.rb +64 -0
- data/spec/rtm/navigation/topic/types_spec.rb +195 -0
- data/spec/rtm/navigation/topic_spec.rb +153 -0
- data/spec/rtm/sugar/association/hash_access_spec.rb +55 -0
- data/spec/rtm/sugar/occurrence/dynamic_value_spec.rb +16 -0
- data/spec/rtm/sugar/role/counterparts_spec.rb +191 -0
- data/spec/rtm/sugar/topic/characteristics_spec.rb +318 -0
- data/spec/rtm/sugar/topic/counterparts_spec.rb +184 -0
- data/spec/rtm/sugar/topic/hash_access_spec.rb +234 -0
- data/spec/rtm/sugar/topic/scoped_spec.rb +131 -0
- data/spec/rtm/sugar/topic/topic_ref_spec.rb +44 -0
- data/spec/rtm/sugar/topic/typed_spec.rb +155 -0
- data/spec/rtm/sugar/typed/types_spec.rb +24 -0
- data/spec/rtm/tmapi/core/association_spec.rb +169 -0
- data/spec/rtm/tmapi/core/construct_spec.rb +25 -0
- data/spec/rtm/tmapi/core/name_spec.rb +85 -0
- data/spec/rtm/tmapi/core/occurrence_spec.rb +96 -0
- data/spec/rtm/tmapi/core/reifiable_spec.rb +168 -0
- data/spec/rtm/tmapi/core/role_spec.rb +73 -0
- data/spec/rtm/tmapi/core/scoped_spec.rb +403 -0
- data/spec/rtm/tmapi/core/topic_map_spec.rb +648 -0
- data/spec/rtm/tmapi/core/topic_spec.rb +992 -0
- data/spec/rtm/tmapi/core/typed_spec.rb +112 -0
- data/spec/rtm/tmapi/core/variant_spec.rb +52 -0
- data/spec/rtm/tmapi/ext/java_util_set_spec.rb +34 -0
- data/spec/rtm/tmapi_spec.rb +44 -0
- data/spec/rtm/utils/sparql_spec.rb +26 -0
- data/spec/rtm_spec.rb +94 -0
- data/spec/spec_helper.rb +23 -0
- data/test/base_unit_test.rb +161 -0
- data/test/{base_test.rb → base_unit_test_tmapi.rb} +46 -43
- metadata +122 -66
- data/COPYRIGHT +0 -4
- data/lib/Rakefile.rb +0 -42
- data/lib/activetopicmaps.rb +0 -278
- data/lib/rtm/backend/active_record.rb +0 -58
- data/lib/rtm/backend/active_record/001_initial_schema.rb +0 -116
- data/lib/rtm/backend/active_record/association_and_role.rb +0 -33
- data/lib/rtm/backend/active_record/locators.rb +0 -55
- data/lib/rtm/backend/active_record/name_variant_occurrence.rb +0 -45
- data/lib/rtm/backend/active_record/quaaxtm2rtm.rb +0 -113
- data/lib/rtm/backend/active_record/quaaxtm2rtmviews.rb +0 -134
- data/lib/rtm/backend/active_record/set_wrapper.rb +0 -98
- data/lib/rtm/backend/active_record/tm_construct.rb +0 -62
- data/lib/rtm/backend/active_record/tm_delegator.rb +0 -345
- data/lib/rtm/backend/active_record/tm_set_delegator.rb +0 -195
- data/lib/rtm/backend/active_record/tmdm.rb +0 -298
- data/lib/rtm/backend/active_record/topic.rb +0 -87
- data/lib/rtm/backend/active_record/topic_map.rb +0 -314
- data/lib/rtm/backend/active_record/traverse_associations.rb +0 -87
- data/lib/rtm/base.rb +0 -92
- data/lib/rtm/connect.rb +0 -92
- data/lib/rtm/core_ext.rb +0 -6
- data/lib/rtm/io/from_xtm2.rb +0 -263
- data/lib/rtm/merging/merging.rb +0 -307
- data/lib/rtm/sugar/topic/identifier_direct.rb +0 -11
- data/lib/rtm/sugar/topic/predefined_associations.rb +0 -42
- data/lib/run_main_project.rb +0 -16
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
module RTM::AR
|
|
2
|
-
module TraverseAssociations
|
|
3
|
-
# defines methods to traverse a specific assocation for all topics
|
|
4
|
-
def define_association(prop, options={})
|
|
5
|
-
r = options[:rule]
|
|
6
|
-
module_eval(<<-EOS, "(__AR_DELEGATOR_DEFINE_ASSOCIATION__)", 1)
|
|
7
|
-
def direct_#{prop}_roles
|
|
8
|
-
# prefetch typing topics
|
|
9
|
-
rtype = @ips_#{prop}_rtype ||= self.topic_map.get("#{r[:role_type]}")
|
|
10
|
-
atype = @ips_#{prop}_atype ||= self.topic_map.get("#{r[:association_type]}")
|
|
11
|
-
otype = @ips_#{prop}_otype ||= self.topic_map.get("#{r[:other_role_type]}")
|
|
12
|
-
# return nothing if any of the typing topics does not exist
|
|
13
|
-
return [] unless rtype && atype && otype
|
|
14
|
-
# we do that only here and not earlier because some might me nil
|
|
15
|
-
rtype = rtype.id
|
|
16
|
-
atype = atype.id
|
|
17
|
-
otype = otype.id
|
|
18
|
-
self.__getobj__.roles.map{|r|
|
|
19
|
-
r.ttype_id != nil &&
|
|
20
|
-
r.ttype_id == rtype &&
|
|
21
|
-
r.parent.roles.size == #{r[:association_arity]} &&
|
|
22
|
-
r.parent != nil &&
|
|
23
|
-
r.parent.ttype_id == atype &&
|
|
24
|
-
(r2 = r.parent.roles.select{|r2| r2.ttype_id != nil &&
|
|
25
|
-
r2.ttype_id == otype}.first) &&
|
|
26
|
-
r2}.select{|r2| r2}.map{|r2| AssociationRole.wrap(r2)}
|
|
27
|
-
end
|
|
28
|
-
def direct_#{prop}
|
|
29
|
-
direct_#{prop}_roles.map{|r2| r2.player}.uniq
|
|
30
|
-
end
|
|
31
|
-
EOS
|
|
32
|
-
|
|
33
|
-
if r[:transitive]
|
|
34
|
-
module_eval(<<-EOS, "(__AR_DELEGATOR_DEFINE_ASSOCIATION2__)", 1)
|
|
35
|
-
def #{prop}
|
|
36
|
-
d = todo = self.direct_#{prop}
|
|
37
|
-
while todo.size > 0
|
|
38
|
-
todo = todo.map{|dt| dt.direct_#{prop}}.flatten.uniq - d
|
|
39
|
-
d += todo
|
|
40
|
-
end
|
|
41
|
-
d
|
|
42
|
-
#d2 = self.direct_#{prop}.map {|dt| dt.#{prop}}.flatten
|
|
43
|
-
#(d+d2).uniq
|
|
44
|
-
end
|
|
45
|
-
EOS
|
|
46
|
-
else
|
|
47
|
-
if r[:infer] && r[:infer_other] # this part is not testet at all!
|
|
48
|
-
module_eval(<<-EOS, "(__AR_DELEGATOR_DEFINE_ASSOCIATION3a__)", 1)
|
|
49
|
-
def #{prop}
|
|
50
|
-
dps = (self + self.#{r[:infer]}).flatten.uniq
|
|
51
|
-
dcps = dps.map{|d2| d2.direct_#{prop}}
|
|
52
|
-
(dcps + dcps.map{|d2| d2.#{r[:infer_other]}}).flatten.uniq
|
|
53
|
-
end
|
|
54
|
-
EOS
|
|
55
|
-
elsif r[:infer]
|
|
56
|
-
module_eval(<<-EOS, "(__AR_DELEGATOR_DEFINE_ASSOCIATION3__)", 1)
|
|
57
|
-
def #{prop}
|
|
58
|
-
(self.direct_#{prop} + self.#{r[:infer]}.map{|d2| d2.direct_#{prop}}).flatten.uniq
|
|
59
|
-
end
|
|
60
|
-
EOS
|
|
61
|
-
elsif r[:infer_other]
|
|
62
|
-
module_eval(<<-EOS, "(__AR_DELEGATOR_DEFINE_ASSOCIATION4__)", 1)
|
|
63
|
-
def #{prop}
|
|
64
|
-
d = self.direct_#{prop}
|
|
65
|
-
(d + d.map{|d2| d2.#{r[:infer_other]}}).flatten.uniq
|
|
66
|
-
end
|
|
67
|
-
EOS
|
|
68
|
-
end
|
|
69
|
-
end
|
|
70
|
-
if r[:add]
|
|
71
|
-
module_eval(<<-EOS, "(__AR_DELEGATOR_DEFINE_ASSOCIATION_ADD_REMOVE__)", 1)
|
|
72
|
-
def add_#{r[:add]}(t)
|
|
73
|
-
a = self.topic_map.create_association("#{r[:association_type]}")
|
|
74
|
-
a.create_role self, "#{r[:role_type]}"
|
|
75
|
-
a.create_role t, "#{r[:other_role_type]}"
|
|
76
|
-
a
|
|
77
|
-
# TODO add_x in define_association needs to trigger reload of the topics somewhere
|
|
78
|
-
end
|
|
79
|
-
def remove_#{r[:add]}(t)
|
|
80
|
-
direct_#{prop}_roles.select{|r| r.player == t}.each{|r| r.parent.remove}
|
|
81
|
-
# TODO remove_x in define_association needs to trigger reload of the topics somewhere
|
|
82
|
-
end
|
|
83
|
-
EOS
|
|
84
|
-
end
|
|
85
|
-
end
|
|
86
|
-
end
|
|
87
|
-
end
|
data/lib/rtm/base.rb
DELETED
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
module RTM
|
|
2
|
-
def self.create(base_locator)
|
|
3
|
-
AR::TopicMap.create(base_locator)
|
|
4
|
-
end
|
|
5
|
-
|
|
6
|
-
def self.topic_maps
|
|
7
|
-
AR::TopicMap.topic_maps
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
def self.[](*args)
|
|
11
|
-
if args.size == 0
|
|
12
|
-
return AR::TopicMap.topic_maps
|
|
13
|
-
end
|
|
14
|
-
AR::TopicMap.topic_maps[*args]
|
|
15
|
-
end
|
|
16
|
-
module TopicMapConstruct
|
|
17
|
-
def find(*args)
|
|
18
|
-
RTM::AR.const_get(name.split("::").last).find(*args)
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
module Reifiable
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
module TopicMap
|
|
25
|
-
extend TopicMapConstruct
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
module Topic
|
|
29
|
-
extend TopicMapConstruct
|
|
30
|
-
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
module Association
|
|
34
|
-
extend TopicMapConstruct
|
|
35
|
-
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
module AssociationRole
|
|
39
|
-
extend TopicMapConstruct
|
|
40
|
-
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
module TopicName
|
|
44
|
-
extend TopicMapConstruct
|
|
45
|
-
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
module Variant
|
|
49
|
-
extend TopicMapConstruct
|
|
50
|
-
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
module Occurrence
|
|
54
|
-
extend TopicMapConstruct
|
|
55
|
-
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
module Locator
|
|
59
|
-
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
module ItemIdentifier
|
|
63
|
-
extend Locator
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
module SubjectIdentifier
|
|
67
|
-
extend Locator
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
module SubjectLocator
|
|
71
|
-
extend Locator
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
# module Topics
|
|
75
|
-
# end
|
|
76
|
-
# module Associations
|
|
77
|
-
# end
|
|
78
|
-
# module TopicNames
|
|
79
|
-
# end
|
|
80
|
-
# module Occurrences
|
|
81
|
-
# end
|
|
82
|
-
# module AssociationRoles
|
|
83
|
-
# end
|
|
84
|
-
# module Reifiables
|
|
85
|
-
# end
|
|
86
|
-
# module Variants
|
|
87
|
-
# end
|
|
88
|
-
# module TopicMaps
|
|
89
|
-
# end
|
|
90
|
-
# module Locators
|
|
91
|
-
# end
|
|
92
|
-
end
|
data/lib/rtm/connect.rb
DELETED
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
require 'active_record'
|
|
2
|
-
require 'rtm/backend/active_record/001_initial_schema'
|
|
3
|
-
module RTM
|
|
4
|
-
|
|
5
|
-
# Assignes a logger to active record (or STDOUT as default) which outputs
|
|
6
|
-
# the sql statements.
|
|
7
|
-
def self.log(to=STDOUT)
|
|
8
|
-
ActiveRecord::Base.logger = Logger.new(to)
|
|
9
|
-
ActiveRecord::Base.colorize_logging = false if PLATFORM =~ /mswin/
|
|
10
|
-
end
|
|
11
|
-
# This function generates the database schema using the default
|
|
12
|
-
# ActiveRecord connection.
|
|
13
|
-
def self.generate_database
|
|
14
|
-
RTM::AR::TMDM::InitialSchema.migrate(:up)
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
# Connects to the sqlite3 database given in the path or to
|
|
18
|
-
# a default database if no path is given.
|
|
19
|
-
def self.connect_sqlite3(dbname="tmdm.sqlite3")
|
|
20
|
-
ActiveRecord::Base.establish_connection(
|
|
21
|
-
:adapter => platform_specific_adapter("sqlite3"),
|
|
22
|
-
:database => dbname
|
|
23
|
-
)
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
# Connects to the sqlite2 database given in the path or to
|
|
27
|
-
# a default database if no path is given.
|
|
28
|
-
def self.connect_sqlite(dbname="tmdm.sqlite2")
|
|
29
|
-
ActiveRecord::Base.establish_connection(
|
|
30
|
-
:adapter => platform_specific_adapter("sqlite"),
|
|
31
|
-
:database => dbname
|
|
32
|
-
)
|
|
33
|
-
end
|
|
34
|
-
# Connects to a mysql database. Parameters are
|
|
35
|
-
# either
|
|
36
|
-
# database, username, password, host
|
|
37
|
-
# or
|
|
38
|
-
# only a keyword hash with these parameters.
|
|
39
|
-
def self.connect_mysql(database="rtm_development", username=nil, password=nil, host="localhost")
|
|
40
|
-
if database.is_a? Hash
|
|
41
|
-
return ActiveRecord::Base.establish_connection(database)
|
|
42
|
-
end
|
|
43
|
-
ActiveRecord::Base.establish_connection(
|
|
44
|
-
:adapter => platform_specific_adapter("mysql"),
|
|
45
|
-
:database => database,
|
|
46
|
-
:username => username,
|
|
47
|
-
:password => password,
|
|
48
|
-
:host => host
|
|
49
|
-
)
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
# Connects to a in-memory database. No parameters required.
|
|
53
|
-
# Schema will automatically be generated.
|
|
54
|
-
def self.connect_memory
|
|
55
|
-
ActiveRecord::Base.establish_connection(
|
|
56
|
-
:adapter => platform_specific_adapter("sqlite3"),
|
|
57
|
-
:database => ":memory:"
|
|
58
|
-
)
|
|
59
|
-
no_output do
|
|
60
|
-
generate_database
|
|
61
|
-
end
|
|
62
|
-
true
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
# Connects to a in-memory sqlite2 database, as connect_memory does with sqlite3
|
|
66
|
-
def self.connect_memory2
|
|
67
|
-
ActiveRecord::Base.establish_connection(
|
|
68
|
-
:adapter => platform_specific_adapter("sqlite"),
|
|
69
|
-
:database => ":memory:"
|
|
70
|
-
)
|
|
71
|
-
no_output do
|
|
72
|
-
generate_database
|
|
73
|
-
end
|
|
74
|
-
true
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
# Connects Active Record to a database or in Memory database if no parameters given.
|
|
78
|
-
def self.connect(*args)
|
|
79
|
-
if args.size == 0
|
|
80
|
-
return connect_memory
|
|
81
|
-
end
|
|
82
|
-
ActiveRecord::Base.establish_connection(*args)
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
private
|
|
86
|
-
def self.platform_specific_adapter(adapter)
|
|
87
|
-
if PLATFORM && PLATFORM =~ /java/
|
|
88
|
-
return "jdbc#{adapter}"
|
|
89
|
-
end
|
|
90
|
-
return adapter
|
|
91
|
-
end
|
|
92
|
-
end
|
data/lib/rtm/core_ext.rb
DELETED
data/lib/rtm/io/from_xtm2.rb
DELETED
|
@@ -1,263 +0,0 @@
|
|
|
1
|
-
# Ruby Topic Maps (RTM) http://rtm.rubyforge.org/
|
|
2
|
-
|
|
3
|
-
module RTM
|
|
4
|
-
def self.from_xtm2(*args)
|
|
5
|
-
RTM::IO::FROMXTM2.from_xtm2(*args)
|
|
6
|
-
end
|
|
7
|
-
end
|
|
8
|
-
module RTM::IO
|
|
9
|
-
# XTM2 Export.
|
|
10
|
-
# Each Topic Maps Construct gets a to_xtm2 method.
|
|
11
|
-
# The result is a REXML::Element except for TopicMap where it is a REXML::Document.
|
|
12
|
-
module FROMXTM2
|
|
13
|
-
require 'rexml/document'
|
|
14
|
-
require 'rexml/parsers/sax2parser'
|
|
15
|
-
require 'rexml/sax2listener'
|
|
16
|
-
#require 'jrexml'
|
|
17
|
-
XTM2DEBUG = false
|
|
18
|
-
|
|
19
|
-
# Reads XTM2 from source (io object).
|
|
20
|
-
# Example: RTM::IO::FROMXTM2.from_xtm2(File.open(file_name),"http://rtm.rubyforge.org/topicmaps/tm1/")
|
|
21
|
-
# supported options:
|
|
22
|
-
# :strip_whitespace (defaults to false, may be set to true),
|
|
23
|
-
# :deprefix (defaults to nil, may be set to a string (or regex) which will be removed from the beginning of an (unresolved) item_identifier if it is there.
|
|
24
|
-
def self.from_xtm2(source, base_locator, target=nil,options={})
|
|
25
|
-
tm = RTM.create(base_locator) unless target
|
|
26
|
-
list = XTM2Listener.new(base_locator, target || tm, options)
|
|
27
|
-
parser = REXML::Parsers::SAX2Parser.new(source)
|
|
28
|
-
parser.listen(list)
|
|
29
|
-
parser.parse
|
|
30
|
-
true
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
class XTM2Listener
|
|
34
|
-
include REXML::SAX2Listener
|
|
35
|
-
def initialize(base_locator, target,options={})
|
|
36
|
-
@base_locator = base_locator
|
|
37
|
-
@target = target
|
|
38
|
-
@targets = []
|
|
39
|
-
@path = []
|
|
40
|
-
@options=options
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
private
|
|
44
|
-
def resolve(iri)
|
|
45
|
-
warn("resolving nil iri can have unexpected results") unless iri
|
|
46
|
-
# TODO handle %HH sequences, here or in backend/active_record.rb
|
|
47
|
-
if @options[:deprefix]
|
|
48
|
-
iri = iri.gsub(/^#{@options[:deprefix]}/,'')
|
|
49
|
-
end
|
|
50
|
-
@target.resolve(iri, @base_locator)
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
public
|
|
54
|
-
def start_element(uri, name, qname, attrs)
|
|
55
|
-
return unless uri == "http://www.topicmaps.org/xtm/"
|
|
56
|
-
a = attrs #Hash[* attrs.flatten]
|
|
57
|
-
#puts "Start of tag #{name} - attrs: #{a.inspect}"
|
|
58
|
-
|
|
59
|
-
case name
|
|
60
|
-
when "topic"
|
|
61
|
-
@topic = @targets.last.topic_by_item_identifier! resolve(a["id"])
|
|
62
|
-
@targets.push @topic
|
|
63
|
-
when "association"
|
|
64
|
-
assoc = nil
|
|
65
|
-
if a["reifier"]
|
|
66
|
-
ref = @targets.last.topic_map.topic_by_item_identifier! resolve(a["reifier"])
|
|
67
|
-
raise "The topic reifiing this association already reifies something else: #{ref}." if ref.reified && !ref.reified.is_a?(RTM::Association)
|
|
68
|
-
if ref.reified
|
|
69
|
-
assoc = ref.reified
|
|
70
|
-
else
|
|
71
|
-
assoc = @targets.last.create_association
|
|
72
|
-
assoc.reifier = ref
|
|
73
|
-
end
|
|
74
|
-
end
|
|
75
|
-
assoc ||= @targets.last.create_association
|
|
76
|
-
@targets.push assoc
|
|
77
|
-
when "role"
|
|
78
|
-
if a["reifier"]
|
|
79
|
-
ref = @targets.last.topic_map.topic_by_item_identifier! resolve(a["reifier"])
|
|
80
|
-
raise "The topic reifiing this association role already reifies something else: #{ref}." if ref.reified && !ref.reified.is_a?(RTM::AssociationRole)
|
|
81
|
-
if ref.reified
|
|
82
|
-
role = ref.reified
|
|
83
|
-
else
|
|
84
|
-
role = @targets.last.create_role
|
|
85
|
-
role.reifier = ref
|
|
86
|
-
end
|
|
87
|
-
end
|
|
88
|
-
role ||= @targets.last.create_role
|
|
89
|
-
@targets.push role
|
|
90
|
-
when "name"
|
|
91
|
-
if a["reifier"]
|
|
92
|
-
ref = @targets.last.topic_map.topic_by_item_identifier! resolve(a["reifier"])
|
|
93
|
-
raise "The topic reifiing this topic name already reifies something else: #{ref}." if ref.reified && !ref.reified.is_a?(RTM::TopicName)
|
|
94
|
-
if ref.reified
|
|
95
|
-
tname = ref.reified
|
|
96
|
-
else
|
|
97
|
-
tname = @targets.last.create_name
|
|
98
|
-
tname.reifier = ref
|
|
99
|
-
end
|
|
100
|
-
end
|
|
101
|
-
tname ||= @targets.last.create_name
|
|
102
|
-
@targets.push tname
|
|
103
|
-
when "value"
|
|
104
|
-
# this is handled in text()
|
|
105
|
-
when "variant"
|
|
106
|
-
if a["reifier"]
|
|
107
|
-
ref = @targets.last.topic_map.topic_by_item_identifier! resolve(a["reifier"])
|
|
108
|
-
raise "The topic reifiing this topic variant already reifies something else: #{ref}." if ref.reified && !ref.reified.is_a?(RTM::Variant)
|
|
109
|
-
if ref.reified
|
|
110
|
-
variant = ref.reified
|
|
111
|
-
else
|
|
112
|
-
variant = @targets.last.create_variant
|
|
113
|
-
variant.reifier = ref
|
|
114
|
-
end
|
|
115
|
-
end
|
|
116
|
-
variant ||= @targets.last.create_variant
|
|
117
|
-
@targets.push variant
|
|
118
|
-
when "scope"
|
|
119
|
-
# nothing to be done here :)
|
|
120
|
-
when "instanceOf"
|
|
121
|
-
# nothing to be done here :)
|
|
122
|
-
when "type"
|
|
123
|
-
# nothing to be done here :)
|
|
124
|
-
when "occurrence"
|
|
125
|
-
if a["reifier"]
|
|
126
|
-
ref = @targets.last.topic_map.topic_by_item_identifier! resolve(a["reifier"])
|
|
127
|
-
raise "The topic reifiing this topic occurrence already reifies something else: #{ref}." if ref.reified && !ref.reified.is_a?(RTM::Occurrence)
|
|
128
|
-
if ref.reified
|
|
129
|
-
occur = ref.reified
|
|
130
|
-
else
|
|
131
|
-
occur = @targets.last.create_occurrence
|
|
132
|
-
occur.reifier = ref
|
|
133
|
-
end
|
|
134
|
-
end
|
|
135
|
-
occur ||= @targets.last.create_occurrence
|
|
136
|
-
@targets.push occur
|
|
137
|
-
when "resourceData"
|
|
138
|
-
occur_or_variant = @targets.last
|
|
139
|
-
if a["datatype"]
|
|
140
|
-
occur_or_variant.datatype = a["datatype"]
|
|
141
|
-
# special handling is done in tag_end
|
|
142
|
-
else
|
|
143
|
-
occur_or_variant.datatype = RTM::PSI[:String]
|
|
144
|
-
end
|
|
145
|
-
when "topicRef"
|
|
146
|
-
case @path.last
|
|
147
|
-
when "scope"
|
|
148
|
-
@targets.last.scope << a["href"]
|
|
149
|
-
when "instanceOf"
|
|
150
|
-
assoc = @targets.last.topic_map.create_association :type => RTM::PSI[:type_instance]
|
|
151
|
-
assoc.create_role @targets.last, RTM::PSI[:instance]
|
|
152
|
-
assoc.create_role a["href"], RTM::PSI[:type]
|
|
153
|
-
when "type"
|
|
154
|
-
@targets.last.type = a["href"]
|
|
155
|
-
when "role"
|
|
156
|
-
@targets.last.player = a["href"]
|
|
157
|
-
end
|
|
158
|
-
when "resourceRef"
|
|
159
|
-
occurrence = @targets.last
|
|
160
|
-
occurrence.datatype = RTM::PSI[:IRI]
|
|
161
|
-
occurrence.value = a["href"]
|
|
162
|
-
when "subjectLocator"
|
|
163
|
-
@targets.last.subject_locators << a["href"]
|
|
164
|
-
when "subjectIdentifier"
|
|
165
|
-
@targets.last.subject_identifiers << a["href"]
|
|
166
|
-
when "itemIdentity"
|
|
167
|
-
@targets.last.item_identifiers << resolve(a["href"])
|
|
168
|
-
when "topicMap"
|
|
169
|
-
# check where we are
|
|
170
|
-
raise "unexpected element topicMap" unless @path.empty?
|
|
171
|
-
# check version
|
|
172
|
-
raise "Sorry, only XTM 2.0 is supported" if a["version"] != "2.0"
|
|
173
|
-
|
|
174
|
-
# reifier. if target topic map is already reified we have to merge, if not create topic
|
|
175
|
-
if a["reifier"]
|
|
176
|
-
if @target.reifier # TODO this might be no topic here. In this case something should be raised!
|
|
177
|
-
@target.reifier.item_identifiers << resolve(a["reifier"])
|
|
178
|
-
else
|
|
179
|
-
@target.topic_by_item_identifier! resolve(a["reifier"])
|
|
180
|
-
end
|
|
181
|
-
end
|
|
182
|
-
@targets.push @target
|
|
183
|
-
when "mergeMap"
|
|
184
|
-
# TODO mergeMap
|
|
185
|
-
warn "mergeMap is not supported yet!"
|
|
186
|
-
else
|
|
187
|
-
warn "Unhandled element: #{name}"
|
|
188
|
-
end
|
|
189
|
-
|
|
190
|
-
@path.push name
|
|
191
|
-
end
|
|
192
|
-
|
|
193
|
-
# Called when the end tag is reached. In the case of <tag/>, tag_end
|
|
194
|
-
# will be called immidiately after tag_start
|
|
195
|
-
# @p the name of the tag
|
|
196
|
-
def end_element(uri, name, qname)
|
|
197
|
-
return unless uri == "http://www.topicmaps.org/xtm/"
|
|
198
|
-
#puts "end of tag: #{name}"
|
|
199
|
-
|
|
200
|
-
old_name = @path.pop
|
|
201
|
-
raise "Tag_end did not match: expected: #{old_name}, got: #{name}." unless old_name == name
|
|
202
|
-
case name
|
|
203
|
-
when "topicMap", "topic", "association", "role", "name", "variant", "occurrence"
|
|
204
|
-
@targets.pop
|
|
205
|
-
when "resourceData"
|
|
206
|
-
occur = @targets.last
|
|
207
|
-
# puts "finalizing occurrence #{occur.inspect}"
|
|
208
|
-
if occur.datatype == RTM::PSI[:IRI]
|
|
209
|
-
occur.value = resolve(occur.value)
|
|
210
|
-
elsif occur.datatype == RTM::PSI[:anyType]
|
|
211
|
-
# TODO Content must be canonicalized according to http://www.isotopicmaps.org/sam/sam-xtm/#sect-xml-canonicalization
|
|
212
|
-
warn("Content canonicalization is not yet implemented!")
|
|
213
|
-
end
|
|
214
|
-
# puts "leaving finalizing occurrence"
|
|
215
|
-
end
|
|
216
|
-
# puts "after case"
|
|
217
|
-
end
|
|
218
|
-
# Called when text is encountered in the document
|
|
219
|
-
# @p text the text content.
|
|
220
|
-
def characters(text)
|
|
221
|
-
if @options[:strip_whitespace]
|
|
222
|
-
text.strip!
|
|
223
|
-
return if text.empty?
|
|
224
|
-
end
|
|
225
|
-
case @path.last
|
|
226
|
-
when "value", "resourceData"
|
|
227
|
-
if @targets.last.value
|
|
228
|
-
@targets.last.value += text
|
|
229
|
-
else
|
|
230
|
-
@targets.last.value = text
|
|
231
|
-
end
|
|
232
|
-
else
|
|
233
|
-
puts "Found text but don't know that to do: #{text}" unless text.strip.empty?
|
|
234
|
-
end
|
|
235
|
-
end
|
|
236
|
-
|
|
237
|
-
def cdata content
|
|
238
|
-
if @options[:strip_whitespace]
|
|
239
|
-
content.strip!
|
|
240
|
-
return if content.empty?
|
|
241
|
-
end
|
|
242
|
-
case @path.last
|
|
243
|
-
when "value", "resourceData"
|
|
244
|
-
if @targets.last.value
|
|
245
|
-
@targets.last.value += content
|
|
246
|
-
else
|
|
247
|
-
@targets.last.value = content
|
|
248
|
-
end
|
|
249
|
-
else
|
|
250
|
-
puts "Found cdata but don't know that to do: #{content}" unless content.strip.empty?
|
|
251
|
-
end
|
|
252
|
-
end
|
|
253
|
-
|
|
254
|
-
def xmldecl version, encoding, standalone
|
|
255
|
-
warn "XML Version 1.0 expected. Not sure if we can handle this, but we will try." unless version == "1.0"
|
|
256
|
-
warn "Be aware there is no encoding manipulation done, everything gets in as-is." if encoding
|
|
257
|
-
# what about standalone?
|
|
258
|
-
end
|
|
259
|
-
|
|
260
|
-
end
|
|
261
|
-
|
|
262
|
-
end
|
|
263
|
-
end
|