rtm 0.1.6 → 0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (163) hide show
  1. data/DISCLAIMER +10 -33
  2. data/LICENSE +201 -0
  3. data/README +32 -3
  4. data/lib/rtm.rb +126 -74
  5. data/lib/rtm/axes.rb +298 -0
  6. data/lib/rtm/axes/association.rb +76 -0
  7. data/lib/rtm/axes/associations.rb +96 -0
  8. data/lib/rtm/axes/assocs_names_occs.rb +56 -0
  9. data/lib/rtm/axes/characteristic.rb +68 -0
  10. data/lib/rtm/axes/characteristics.rb +93 -0
  11. data/lib/rtm/axes/string.rb +76 -0
  12. data/lib/rtm/axes/strings.rb +87 -0
  13. data/lib/rtm/axes/topic.rb +233 -0
  14. data/lib/rtm/axes/topics.rb +280 -0
  15. data/lib/rtm/{backward_compatibility.rb → deprecated/index_property_set.rb} +3 -0
  16. data/lib/rtm/engine.rb +101 -0
  17. data/lib/rtm/extensions.rb +65 -5
  18. data/lib/rtm/{locator_helpers.rb → helpers/locator.rb} +15 -4
  19. data/lib/rtm/{helpers.rb → helpers/no_output.rb} +3 -0
  20. data/lib/rtm/helpers/uri.rb +13 -0
  21. data/lib/rtm/io.rb +19 -0
  22. data/lib/rtm/io/from_xtm2_libxml.rb +2 -1
  23. data/lib/rtm/io/tmapix_from.rb +155 -0
  24. data/lib/rtm/io/tmapix_to.rb +223 -0
  25. data/lib/rtm/io/to_hash.rb +154 -0
  26. data/lib/rtm/io/to_jtm.rb +53 -103
  27. data/lib/rtm/io/to_rdf.rb +45 -0
  28. data/lib/rtm/io/to_string.rb +21 -8
  29. data/lib/rtm/io/to_xtm1.rb +6 -4
  30. data/lib/rtm/io/to_xtm2.rb +10 -8
  31. data/lib/rtm/io/to_yaml.rb +59 -100
  32. data/lib/rtm/navigation.rb +23 -0
  33. data/lib/rtm/navigation/association/players.rb +25 -0
  34. data/lib/rtm/navigation/name/atomify.rb +19 -0
  35. data/lib/rtm/navigation/name/characteristics.rb +33 -0
  36. data/lib/rtm/navigation/occurrence/atomify.rb +19 -0
  37. data/lib/rtm/navigation/occurrence/characteristics.rb +33 -0
  38. data/lib/rtm/navigation/topic/characteristics.rb +33 -0
  39. data/lib/rtm/navigation/topic/indicators.rb +31 -0
  40. data/lib/rtm/navigation/topic/items.rb +31 -0
  41. data/lib/rtm/navigation/topic/locators.rb +31 -0
  42. data/lib/rtm/navigation/topic/players.rb +27 -0
  43. data/lib/rtm/navigation/topic/supertypes.rb +166 -0
  44. data/lib/rtm/navigation/topic/traverse.rb +51 -0
  45. data/lib/rtm/navigation/topic/types.rb +109 -0
  46. data/lib/rtm/psi.rb +39 -2
  47. data/lib/rtm/sugar.rb +47 -0
  48. data/lib/rtm/sugar/association/hash_access.rb +46 -0
  49. data/lib/rtm/sugar/occurrence/dynamic_value.rb +58 -0
  50. data/lib/rtm/sugar/occurrence/external.rb +53 -0
  51. data/lib/rtm/sugar/reifiable/reifier.rb +21 -0
  52. data/lib/rtm/sugar/role/counterparts.rb +139 -46
  53. data/lib/rtm/sugar/topic/best_name.rb +74 -0
  54. data/lib/rtm/sugar/topic/characteristics.rb +126 -12
  55. data/lib/rtm/sugar/topic/counterparts.rb +145 -10
  56. data/lib/rtm/sugar/topic/hash_access.rb +140 -30
  57. data/lib/rtm/sugar/topic/scoped.rb +114 -0
  58. data/lib/rtm/sugar/topic/topic_ref.rb +86 -0
  59. data/lib/rtm/sugar/topic/typed.rb +207 -0
  60. data/lib/rtm/sugar/topic_map/query_cache.rb +66 -0
  61. data/lib/rtm/sugar/topic_map/themes.rb +53 -0
  62. data/lib/rtm/sugar/typed/types.rb +38 -0
  63. data/lib/rtm/validation.rb +7 -4
  64. data/lib/rtm/version.rb +30 -0
  65. data/spec/helpers/spec_exampleexamplegroup.rb +14 -0
  66. data/spec/rtm/axes/association_spec.rb +88 -0
  67. data/spec/rtm/axes/associations_spec.rb +60 -0
  68. data/spec/rtm/axes/assocs_names_occs_spec.rb +9 -0
  69. data/spec/rtm/axes/characteristic_spec.rb +90 -0
  70. data/spec/rtm/axes/characteristics_spec.rb +85 -0
  71. data/spec/rtm/axes/string_spec.rb +145 -0
  72. data/spec/rtm/axes/strings_spec.rb +168 -0
  73. data/spec/rtm/axes/topic_spec.rb +124 -0
  74. data/spec/rtm/axes/topics_spec.rb +103 -0
  75. data/spec/rtm/base_spec.rb +32 -0
  76. data/spec/rtm/io/tmapix_from_spec.rb +76 -0
  77. data/spec/rtm/io/tmapix_to_spec.rb +159 -0
  78. data/spec/rtm/io/to_hash_spec.rb +90 -0
  79. data/spec/rtm/io/to_rdf_spec.rb +37 -0
  80. data/spec/rtm/io/to_string_spec.rb +122 -0
  81. data/spec/rtm/io/to_yaml_spec.rb +89 -0
  82. data/spec/rtm/navigation/association/players_spec.rb +58 -0
  83. data/spec/rtm/navigation/association_spec.rb +52 -0
  84. data/spec/rtm/navigation/name/atomify_spec.rb +27 -0
  85. data/spec/rtm/navigation/name/characteristics_spec.rb +34 -0
  86. data/spec/rtm/navigation/name_spec.rb +52 -0
  87. data/spec/rtm/navigation/occurrence/atomify_spec.rb +27 -0
  88. data/spec/rtm/navigation/occurrence/characteristics_spec.rb +34 -0
  89. data/spec/rtm/navigation/occurrence_spec.rb +52 -0
  90. data/spec/rtm/navigation/string_spec.rb +51 -0
  91. data/spec/rtm/navigation/topic/characteristics_spec.rb +55 -0
  92. data/spec/rtm/navigation/topic/indicators_spec.rb +43 -0
  93. data/spec/rtm/navigation/topic/items_spec.rb +44 -0
  94. data/spec/rtm/navigation/topic/locators_spec.rb +44 -0
  95. data/spec/rtm/navigation/topic/players_spec.rb +48 -0
  96. data/spec/rtm/navigation/topic/scope_spec.rb +41 -0
  97. data/spec/rtm/navigation/topic/supertypes_spec.rb +376 -0
  98. data/spec/rtm/navigation/topic/traverse_spec.rb +64 -0
  99. data/spec/rtm/navigation/topic/types_spec.rb +195 -0
  100. data/spec/rtm/navigation/topic_spec.rb +153 -0
  101. data/spec/rtm/sugar/association/hash_access_spec.rb +55 -0
  102. data/spec/rtm/sugar/occurrence/dynamic_value_spec.rb +171 -0
  103. data/spec/rtm/sugar/occurrence/external_spec.rb +129 -0
  104. data/spec/rtm/sugar/reifiable/reifier_spec.rb +41 -0
  105. data/spec/rtm/sugar/role/counterparts_spec.rb +193 -0
  106. data/spec/rtm/sugar/topic/best_name_spec.rb +25 -0
  107. data/spec/rtm/sugar/topic/characteristics_spec.rb +333 -0
  108. data/spec/rtm/sugar/topic/counterparts_spec.rb +224 -0
  109. data/spec/rtm/sugar/topic/hash_access_spec.rb +234 -0
  110. data/spec/rtm/sugar/topic/scoped_spec.rb +195 -0
  111. data/spec/rtm/sugar/topic/topic_ref_spec.rb +44 -0
  112. data/spec/rtm/sugar/topic/typed_spec.rb +217 -0
  113. data/spec/rtm/sugar/topic_map/themes_spec.rb +67 -0
  114. data/spec/rtm/sugar/typed/types_spec.rb +24 -0
  115. data/spec/rtm/tmapi/core/association_spec.rb +169 -0
  116. data/spec/rtm/tmapi/core/construct_spec.rb +25 -0
  117. data/spec/rtm/tmapi/core/datatype_aware_spec.rb +236 -0
  118. data/spec/rtm/tmapi/core/name_spec.rb +270 -0
  119. data/spec/rtm/tmapi/core/occurrence_spec.rb +53 -0
  120. data/spec/rtm/tmapi/core/reifiable_spec.rb +168 -0
  121. data/spec/rtm/tmapi/core/role_spec.rb +73 -0
  122. data/spec/rtm/tmapi/core/scoped_spec.rb +441 -0
  123. data/spec/rtm/tmapi/core/topic_map_spec.rb +716 -0
  124. data/spec/rtm/tmapi/core/topic_spec.rb +1468 -0
  125. data/spec/rtm/tmapi/core/typed_spec.rb +112 -0
  126. data/spec/rtm/tmapi/core/variant_spec.rb +52 -0
  127. data/spec/rtm/tmapi/ext/java_util_set_spec.rb +34 -0
  128. data/spec/rtm/tmapi_spec.rb +44 -0
  129. data/spec/rtm/utils/sparql_spec.rb +26 -0
  130. data/spec/rtm_spec.rb +93 -0
  131. data/spec/spec_helper.rb +28 -0
  132. data/test/javalibs/junit-4.5.jar +0 -0
  133. data/test/javalibs/tmapi-2.0-tests.jar +0 -0
  134. data/test/tmapi_tests.rb +25 -0
  135. metadata +169 -65
  136. data/COPYRIGHT +0 -4
  137. data/lib/Rakefile.rb +0 -42
  138. data/lib/activetopicmaps.rb +0 -278
  139. data/lib/rtm/backend/active_record.rb +0 -58
  140. data/lib/rtm/backend/active_record/001_initial_schema.rb +0 -116
  141. data/lib/rtm/backend/active_record/association_and_role.rb +0 -33
  142. data/lib/rtm/backend/active_record/locators.rb +0 -55
  143. data/lib/rtm/backend/active_record/name_variant_occurrence.rb +0 -45
  144. data/lib/rtm/backend/active_record/quaaxtm2rtm.rb +0 -113
  145. data/lib/rtm/backend/active_record/quaaxtm2rtmviews.rb +0 -134
  146. data/lib/rtm/backend/active_record/set_wrapper.rb +0 -98
  147. data/lib/rtm/backend/active_record/tm_construct.rb +0 -62
  148. data/lib/rtm/backend/active_record/tm_delegator.rb +0 -345
  149. data/lib/rtm/backend/active_record/tm_set_delegator.rb +0 -195
  150. data/lib/rtm/backend/active_record/tmdm.rb +0 -298
  151. data/lib/rtm/backend/active_record/topic.rb +0 -87
  152. data/lib/rtm/backend/active_record/topic_map.rb +0 -314
  153. data/lib/rtm/backend/active_record/traverse_associations.rb +0 -87
  154. data/lib/rtm/base.rb +0 -92
  155. data/lib/rtm/connect.rb +0 -92
  156. data/lib/rtm/core_ext.rb +0 -6
  157. data/lib/rtm/io/from_xtm2.rb +0 -263
  158. data/lib/rtm/merging/merging.rb +0 -307
  159. data/lib/rtm/pimp_my_api.rb +0 -28
  160. data/lib/rtm/sugar/topic/identifier_direct.rb +0 -11
  161. data/lib/rtm/sugar/topic/predefined_associations.rb +0 -42
  162. data/lib/run_main_project.rb +0 -16
  163. data/test/base_test.rb +0 -162
@@ -0,0 +1,74 @@
1
+ # Copyright: Copyright 2009 Topic Maps Lab, University of Leipzig.
2
+ # License: Apache License, Version 2.0
3
+
4
+ module RTM::Sugar::Topic::BestName
5
+
6
+ # Tries to find the best matching name for a given topic.
7
+ #
8
+ def best_name (theme = nil)
9
+ all_names = self.names
10
+
11
+ # return last part of identifier if no name exist
12
+ return find_user_friendly_identifier(self) if all_names.empty
13
+
14
+ # collect name with default name type
15
+ default_names = []
16
+ all_names.each do |name|
17
+ type_of_name = name.getType
18
+
19
+ next if type_of_name.nil?
20
+ type_identifiers = type_of_name.subject_identifiers.to_a
21
+
22
+ type_identifiers.each do |i|
23
+ if i.toExternalForm == RTM::PSI[:name_type] then
24
+ default_names << name
25
+ break
26
+ end
27
+ end
28
+ end
29
+
30
+ default_names = all_names if default_names.empty?
31
+ default_names = default_names.select { |name| not name.scope.to_a.index(theme).nil? } if not theme.nil?
32
+ default_names = all_names if default_names.empty?
33
+
34
+ # get default name with the minimum number of scopes
35
+ min_scoped_name = default_names.sort_by{|n| n.value}.min {|n1,n2| n1.getScope.size <=> n2.getScope.size}
36
+ min_scoped_name.value
37
+ end
38
+
39
+ private
40
+ def find_user_friendly_identifier(topic)
41
+ return psi_prefix topic.
42
+ subject_identifiers.
43
+ sort_by{|sid| sid.value.length}.
44
+ first.
45
+ value unless topic.subject_identifiers.empty?
46
+
47
+ return topic.
48
+ topic_references.
49
+ map{|sid| sid.gsub /^[\^=]/, ''}.
50
+ sort_by{|sid| sid.length }.
51
+ first
52
+
53
+ # fallback
54
+ return create_shortest_topic_identifier topic
55
+ end
56
+
57
+ def create_shortest_topic_identifier(topic)
58
+ base_iri = topic.topic_map.base_locator
59
+
60
+ topic.getItemIdentifiers.each do |item_identifier|
61
+ iid_iri = item_identifier.value
62
+ iid_iri.scan(/(file:)?\/*#{base_iri}#(.*)/) { |pair| return "^#{pair[1]}" }
63
+ end
64
+
65
+ CGI::escape(topic.topic_references.sort_by { |reference| reference.length }.first.to_s)
66
+
67
+ # throw('Unable to create simplified identifier from topic.', topic)
68
+ end
69
+
70
+ # HACK
71
+ def psi_prefix(name)
72
+ name.gsub /^http\:\/\/psi\.topicmaps\.org\/iso13250\/model\//, 'tmdm:'
73
+ end
74
+ end
@@ -1,15 +1,129 @@
1
- module RTM::Sugar
2
- module Topic
3
- module Characteristics
4
- def characteristics
5
- topic_names.to_a + occurrences.to_a
6
- end
7
- def internal_occurrences
8
- occurrences.select{|o| o.datatype != RTM::PSI[:IRI]}
9
- end
10
- def external_occurrences
11
- occurrences.select{|o| o.datatype == RTM::PSI[:IRI]}
12
- end
1
+ # Copyright: Copyright 2009 Topic Maps Lab, University of Leipzig.
2
+ # License: Apache License, Version 2.0
3
+
4
+ module RTM::Sugar::Topic::Characteristics
5
+
6
+ # Returns all Occurrences of this Topic whose datatype is not IRI
7
+ #
8
+ # :call-seq:
9
+ # internal_occurrences -> Set of Occurrences
10
+ #
11
+ def internal_occurrences
12
+ occurrences.select{|x| x.getDatatype.toExternalForm != RTM::PSI[:IRI]}
13
+ end
14
+
15
+ # Returns all Occurrences of this Topic whose datatype is IRI
16
+ #
17
+ # :call-seq:
18
+ # external_occurrences -> Set of Occurrences
19
+ #
20
+ def external_occurrences
21
+ occurrences.select{|y| y.getDatatype.toExternalForm == RTM::PSI[:IRI]}
22
+ end
23
+
24
+ # Returns the names of this topic which may be filtered for their type,
25
+ # value and/or scope.
26
+ #
27
+ # If scope is set to :ucs, names which exist in the unconstrained scope
28
+ # are selected. If scope is set to :any (default), scope does not constrain
29
+ # the names-Array. Else, only the names which whose scope contains one of the
30
+ # given themes are returned.
31
+ #
32
+ # Returns an empty Array if no names match or if the name type
33
+ # or scope does not exist.
34
+ #
35
+ # :call-seq:
36
+ # names_by -> Array of Names
37
+ # names_by(:type => identifier) -> Array of Names
38
+ # names_by(:value => string) -> Array of Names
39
+ # names_by(:scope => identifier) -> Array of Names
40
+ # names_by(:type => identifier, :value => string) -> Array of Names
41
+ # names_by(:type => identifier, :value => string, :scope => identifier) -> Array of Names
42
+ # and so on
43
+ #
44
+ def names_by(args = {})
45
+ raise("names_by: arguments must be a Hash") unless args.is_a?(Hash)
46
+ default_hash = {:type => :any, :value => :any, :scope => :any}
47
+ args = default_hash.merge(args)
48
+ #filter for type
49
+ _names = args[:type] == :any ? names : names(args[:type])
50
+ _names = self.filter_by(_names,args)
51
+ # return Array
52
+ return _names.to_a
53
+ end
54
+
55
+ # Returns Occurrences of this Topic which may be filtered for their type,
56
+ # value, datatype and/or scope.
57
+ #
58
+ # If scope is set to :ucs, Occurrences which exist in the unconstrained scope
59
+ # are selected. If scope is set to :any (default), scope does not constrain
60
+ # the Occurrence-Array. Else, only the occurrences which whose scope contains
61
+ # one of the given themes are returned.
62
+ #
63
+ # Returns an empty Array if no Occurrences match or if the Occurrence type or
64
+ # scope does not exist.
65
+ #
66
+ # :call-seq:
67
+ # occurrence_by -> Array of Occurrences
68
+ # occurrences_by(:type => argument) -> Array of Occurrences
69
+ # occurrences_by(:value => argument) -> Array of Occurrences
70
+ # occurrences_by(:scope => argument) -> Array of Occurrences
71
+ # occurrences_by(:datatype => argument) -> Array of Occurrences
72
+ # occurrences_by(:type => argument1, :value => argument2) -> Array of Occurrences
73
+ # occurrences_by(:type => argument1, :value => argument2, :scope => argument3, :datatype => argument4) -> Array of Occurrences
74
+ # and so on
75
+ #
76
+ def occurrences_by(args = {})
77
+ raise("occurrences_by: arguments must be a Hash") unless args.is_a?(Hash)
78
+ default_hash = {:type => :any, :value => :any, :scope => :any, :datatype => :any}
79
+ args = default_hash.merge(args)
80
+ #filter for type
81
+ _occurrences = args[:type] == :any ? occurrences : occurrences(args[:type])
82
+ _occurrences = self.filter_by(_occurrences,args)
83
+ #filter for datatype
84
+ _occurrences = _occurrences.select{|o| o.datatype == args[:datatype]} unless args[:datatype] == :any
85
+ return _occurrences.to_a
86
+ end
87
+
88
+ protected
89
+ def filter_by(_characteristics,args)
90
+ #filter for value
91
+ unless args[:value] == :any
92
+ _characteristics = args[:value].is_a?(Array) ? _characteristics.select{|o| args[:value].any?{|v| o.value == v}} : _characteristics.select{|o| o.value == args[:value]}
93
+ end
94
+ #filter for scope
95
+ case args[:scope]
96
+ when :any
97
+ when :ucs, []
98
+ _characteristics = _characteristics.select{|o| o.scope.empty?}
99
+ else
100
+ _scope = topic_map.get(args[:scope])
101
+ _characteristics = _scope.is_a?(Array) ? _characteristics.select{|o| _scope.any?{|theme| o.scope.include?(theme)}} : _characteristics.select{|o| o.scope.include?(_scope)}
13
102
  end
103
+ _characteristics
14
104
  end
105
+
106
+ # Returns the Occurrences and Names of this Topic which have the specified type as
107
+ # Occurrence/Name type. Additionally, scope may constrain the the selection.
108
+ #
109
+ # If scope is set to :ucs, Occurrences/Names which exist in the unconstrained scope
110
+ # are selected. If scope is set to :any (default), scope does not constrain
111
+ # the Occurrence/Names-Array. Else, only the Occurrences/Names which exist in the given scope
112
+ # are selected.
113
+ #
114
+ # Returns an empty Array if no Occurrences or Names match or if the Occurrence/Name type or
115
+ # scope does not exist.
116
+ #
117
+ # :call-seq:
118
+ # characteristics_by -> Array of Occurrences and Names
119
+ #
120
+ # def characteristics_by(args = {})
121
+ # raise("characteristics_by: arguments must be a Hash") unless args.is_a?(Hash)
122
+ # default_hash = {:type => :any, :value => :any, :scope => :any, :datatype => :any}
123
+ # args = default_hash.merge(args)
124
+ # _names = names_by(args) if args[:datatype].include(:any) || args[:datatype] == RTM::PSI[:String] || args[:datatype] == topic_map.create_locator(RTM::PSI[:String])
125
+ # _occurrences = occurrences_by(args)
126
+ #
127
+ # end
128
+
15
129
  end
@@ -1,15 +1,150 @@
1
- module RTM::Sugar
2
- module Topic
3
- module Counterparts
4
- def counterparts(filter={})
5
- self.roles.
6
- select{|r| filter[:rtype] ? r.type == self.topic_map.get(filter[:rtype]) : true}.
7
- select{|r| filter[:atype] ? r.parent.type == self.topic_map.get(filter[:atype]) : true}.
8
- inject([]){|all,r| all+=r.counterparts(filter)}
1
+ # Copyright: Copyright 2009 Topic Maps Lab, University of Leipzig.
2
+ # License: Apache License, Version 2.0
3
+
4
+ module RTM::Sugar::Topic
5
+ module Counterparts
6
+
7
+ # Returns all Roles belonging to Associations in which this Topic
8
+ # is a player and for which this Topic is not the player.
9
+ #
10
+ # A filter-hash may be used to filter for the the type
11
+ # of the Role this Topic playes
12
+ # (:rtype), for the Association type (:atype) and/or
13
+ # for the type of the returned Roles (:otype). The
14
+ # identifier may be a topic reference.
15
+ #
16
+ # The result may be empty.
17
+ #
18
+ # :call-seq:
19
+ # counterparts -> Array of Roles
20
+ # counterparts({:rtype => identifier}) -> Array of Roles
21
+ # counterparts({:atype => identifier}) -> Array of Roles
22
+ # counterparts({:otype => identifier}) -> Array of Roles
23
+ # counterparts({:rtype => identifier, :atype => identifier}) -> Array of Roles
24
+ # counterparts({:rtype => identifier, :atype => identifier, :otype => identifier}) -> Array of Roles
25
+ #
26
+ def counterparts(filter={})
27
+ roles.select{|r| filter[:rtype] ? r.type == self.topic_map.get(filter[:rtype]) : true}.
28
+ select{|r| filter[:atype] ? r.parent.type == self.topic_map.get(filter[:atype]) : true}.
29
+ inject([]){|all,r| all+=r.counterparts(filter)}
30
+ end
31
+
32
+ # Returns all Topics that are players of Roles belonging to Associations
33
+ # in which this Topic is another player. The resulting Array does
34
+ # not contain duplicates.
35
+ #
36
+ # A filter-hash may be used to filter for the the type
37
+ # of the Role this Topic playes
38
+ # (:rtype), for the Association type (:atype) and/or
39
+ # for the type of the Roles the returned Topics play (:otype). The
40
+ # identifier may be a topic reference.
41
+ #
42
+ # The result may be empty.
43
+ #
44
+ # :call-seq:
45
+ # counterplayers -> Array of Topics
46
+ # counterplayers(:rtype => identifier) -> Array of Topics
47
+ # counterplayers(:atype => identifier) -> Array of Topics
48
+ # counterplayers(:otype => identifier) -> Array of Topics
49
+ # counterplayers(:rtype => identifier1, :atype => identifier2) -> Array of Topics
50
+ # counterplayers(:rtype => identifier1, :atype => identifier2, :otype => identifier3) -> Array of Topics
51
+ #
52
+ def counterplayers(filter={})
53
+ topic_map.cached self, :counterplayers, filter do
54
+ counterparts(filter).map{|r| r.player}.uniq
55
+ end
56
+ end
57
+
58
+ # Returns all players (Topics) which share a counterplayer with this Topic (player),
59
+ # If type is given, it may constrain the type of the Role this Topic should play
60
+ # (and therefore the type of the Roles the peers play)
61
+ # or the type of the Association this Topic plays a Role in
62
+ # (and therefore the type of the Associations the peers play an Role in).
63
+ #
64
+ # Type may be a topic reference.
65
+ #
66
+ # The result may be empty.
67
+ #
68
+ # :call-seq:
69
+ # peers -> Array of Topics
70
+ # peers(type) -> Array of Topics
71
+ #
72
+ def peers(type=:any)
73
+ _peers = []
74
+ if type == :any
75
+ self.roles.each do |r|
76
+ _peers = _peers + r.peers(:arity => :loose, :atype => :loose, :otype => :loose, :rtype => :loose)
77
+ end
78
+ else
79
+ type = topic_map.get(type)
80
+ if type
81
+ if self.roles.map{|r| r.type}.include?(type) #-> rtype
82
+ self.roles(type).each do |r|
83
+ _peers = _peers + r.peers(:arity => :loose, :atype => :loose, :otype => :loose, :rtype => :strict)
84
+ end
85
+ elsif self.roles.map{|r| r.parent.type}.include?(type) #->atype
86
+ self.roles.select{|r| r.parent.type == type}.each do |r|
87
+ _peers = _peers + r.peers(:arity => :loose, :atype => :strict, :otype => :loose, :rtype => :strict)
88
+ end
89
+ elsif self.roles.map{|r| r.counterparts}.flatten.map{|r| r.type}.include?(type) #-> otype
90
+ # nothing can happen so far
91
+ else
92
+ return []
93
+ end
94
+ else
95
+ return []
96
+ end
9
97
  end
10
- def counterplayers(*args)
11
- return self.counterparts(*args).map{|r| r.player}
98
+ return _peers.map{|r| r.player}
99
+ end
100
+
101
+ # Returns all Associations in which this Topic
102
+ # is a player.
103
+ #
104
+ # A filter-hash may be used to filter
105
+ # for the type of the Role this Topic plays (:rtype),
106
+ # for the Association type (:atype),
107
+ # for the type of another role (:otype) as well as
108
+ # for the player of this other role (:oplayer).
109
+ # Each value of this filter-hash may be a topic reference.
110
+ #
111
+ # The result may be empty.
112
+ #
113
+ # :call-seq:
114
+ # associations_played -> Array of Associations
115
+ # associations_played({:rtype => identifier}) -> Array of Associations
116
+ # associations_played({:atype => identifier}) -> Array of Associations
117
+ # associations_played({:otype => identifier}) -> Array of Associations
118
+ # associations_played({:otype => identifier, :oplayer => identifier}) -> Array of Associations
119
+ # associations_played({:rtype => identifier, :atype => identifier}) -> Array of Associations
120
+ # associations_played({:rtype => identifier, :atype => identifier, :otype => identifier}) -> Array of Associations
121
+ # associations_played({:rtype => identifier, :atype => identifier, :otype => identifier, :oplayer => identifier}) -> Array of Associations
122
+ #
123
+ def associations_played(filter = {})
124
+ topic_map.cached self, :associations_played, filter do
125
+ raise("associations_played(filter): filter must be a Hash") unless filter.is_a?(Hash)
126
+ default_hash = {:rtype => :any, :atype => :any, :otype => :any, :oplayer => :any}
127
+ filter = default_hash.merge(filter)
128
+
129
+ # get all roles played
130
+ roles = self.roles_played(filter[:rtype], filter[:atype])
131
+ filter.delete(:rtype)
132
+ filter.delete(:atype)
133
+
134
+ #filter for the other roles types and players if there are other roles
135
+ roles = roles.reject do |role|
136
+ if role.parent.roles.size == 1 #association size
137
+ if (filter[:otype] != :any) || filter[:player] != :any
138
+ end
139
+ else
140
+ role.counterparts(filter).empty?
141
+ end
142
+ end
143
+
144
+ # return parent associations
145
+ roles.map{|role| role.parent}.uniq
12
146
  end
13
147
  end
148
+
14
149
  end
15
150
  end
@@ -1,52 +1,162 @@
1
+ # Copyright: Copyright 2009 Topic Maps Lab, University of Leipzig.
2
+ # License: Apache License, Version 2.0
3
+
1
4
  module RTM::Sugar
2
5
  module Topic
6
+ # This module implements methods for Hash-like access in Topics.
3
7
  module HashAccess
4
- def [](cref)
5
- raise "Characteristic reference must be a String" unless cref.is_a? String
6
- is_name, type_reference, scope_reference = resolve_characteristic(cref)
7
- if is_name
8
+
9
+ # Returns an Array of Names or Occurrences of
10
+ # this Topic depending on the argument given.
11
+ #
12
+ # If argument is a Topic, an Array of Occurrences of this Topic which
13
+ # have the specified type is returned.
14
+ #
15
+ # Argument may be a String. Then the structure should resemble "-type @scope"
16
+ # or "type @scope".
17
+ #
18
+ # If argument starts with a "-", an Array of Names of this
19
+ # Topic, which have the specified type (trailing the "-"),
20
+ # is returned.
21
+ #
22
+ # If argument equals "-", Names that have the standard name type
23
+ # are returned.
24
+ #
25
+ # If argument starts with a "*", both Names and Occurrences, which have the
26
+ # specified type (trailing the "*") are returned as Array.
27
+ #
28
+ # If argument equals "*", all Names and Occurrences of this Topic are
29
+ # returned. In this case this method equals the characteristics()-method.
30
+ #
31
+ # Else, if argument is a String, an Array of Occurrences
32
+ # of this Topic, which have the specified type,
33
+ # is returned.
34
+ #
35
+ # The argument may include an "@" after the type.
36
+ # The String trailing the @ defines the
37
+ # scope the selected Names and Occurrences should live in. Themes in the
38
+ # scope may be c.
39
+ #
40
+ # Examples:
41
+ # topic[occtype_topic]
42
+ # topic["-"]
43
+ # topic["*"]
44
+ # topic["-nametype"]
45
+ # topic["-nametype @scope]
46
+ # topic["occtype @scope1, scope2"]
47
+ # topic["*type"]
48
+ # topic["*type @scope"]
49
+ #
50
+ # :call-seq:
51
+ # [argument=Topic] -> Array of Occurrences
52
+ # [argument=String] -> Array of Names and/or Occurrences
53
+ #
54
+ def [](identifier = :any)
55
+ # return occurrences by type if topic is given
56
+ return [] unless identifier
57
+ return occurrences(identifier).to_a if (identifier.is_a?(RTM::Topic) || identifier == :any)
58
+ prefix, type_reference, scope_reference = resolve_characteristic(identifier)
59
+ if prefix == :name
8
60
  type_reference = RTM::PSI[:name_type] if type_reference == :any
9
- names.select{|n| n.type == topic_map.get(type_reference)}
10
- else
61
+ ret = names(type_reference).to_a
62
+ elsif prefix == :occurrence
11
63
  raise "No occurrence type given" if type_reference == :any
12
- occurrences.select{|o| o.type == topic_map.get(type_reference)}
64
+ ret = occurrences(type_reference).to_a
65
+ elsif prefix == :both
66
+ ret = names(type_reference).to_a + occurrences(type_reference).to_a # type_reference == :any or not :any
67
+ else
68
+
69
+ end
70
+ # we now have a list of names or occurrences, now we have to select for scope
71
+ return ret if scope_reference == :any
72
+ if scope_reference == :ucs
73
+ ret.select{|i| i.scope.size == 0}
74
+ else
75
+ ret = ret.select{|i| scope_reference.all?{|sr| i.scope.include? getParent.get(sr)}}
13
76
  end
77
+ ret
14
78
  end
15
79
 
16
- def []=(cref, value)
17
- is_name, type_reference, scope_reference = resolve_characteristic(cref)
18
- if is_name
19
- type_reference = nil if type_reference == :any
20
- nametype = type_reference || topic_map.get!(RTM::PSI[:name_type])
21
- n = create_name(value, nametype)
22
- n
23
- else
80
+ # Creates a Name or Occurrence of this Topic depending on the
81
+ # argument given and returns this Name/Occurrence.
82
+ #
83
+ # Argument may be a String whose structure should resemble "-type @scope"
84
+ # or "type @scope".
85
+ #
86
+ # If argument starts with a "-", a Name that has the specified type
87
+ # (trailing the "-") is created.
88
+ #
89
+ # If argument equals "-", a Name that hase the standard name type
90
+ # is created.
91
+ #
92
+ # Else, an Occurrence that has the specified type is created.
93
+ #
94
+ # The argument may include an "@" after the type. The String trailing
95
+ # the @ defines the optional scope the Name or Occurrence
96
+ # should live in. Themes in the scope may be comma- and/or space-separated.
97
+ #
98
+ # The value should be a String.
99
+ #
100
+ # Example:
101
+ # topic[occtype]= "occvalue"
102
+ # topic["-"]= "name"
103
+ # topic["-nametype"]= "name"
104
+ # topic["-nametype @scope]= "name"
105
+ # topic["occtype @scope1, scope2"]= "occvalue"
106
+ #
107
+ # :call-seq:
108
+ # [argument]= value
109
+ #
110
+ def []=(identifier, value)
111
+ prefix, type_reference, scope_reference = resolve_characteristic(identifier)
112
+ if prefix == :name
113
+ nametype = (type_reference==:any) ? topic_map.get!(RTM::PSI[:name_type]) : type_reference
114
+ scope_reference = scope_reference==:any ? [] : scope_reference
115
+ raise("Value is not a String") unless value.is_a?(String)
116
+ ret = create_name(nametype, value, scope_reference)
117
+ elsif prefix == :occurrence
24
118
  raise "No occurrence type given" if type_reference == :any
25
- o = create_occurrence(value, type_reference)
26
- o
119
+ ret = create_occurrence(type_reference, value)
120
+ else
121
+ return nil
27
122
  end
123
+ # return object without scope if any or ucs
124
+ return ret if [:any, :ucs].include? scope_reference
125
+ # set scope
126
+ ret.add_scope(scope_reference)
127
+ ret
28
128
  end
29
-
129
+
30
130
  private
31
- def resolve_characteristic(ref)
32
- ref =~ /^(-\s*)?(.+)?$/
33
- is_name = $1 ? true : false
131
+
132
+ def resolve_characteristic(identifier)
133
+ # spaces(-|*)?spaces(anything)
134
+ prefix = :occurrence
135
+ identifier =~ /^\s*(-|\*)?\s*(.+)?$/ # - or * and then everything else
136
+ if $1
137
+ prefix = ($1 == "-") ? :name : :both
138
+ end
34
139
  type, scope = resolve_type_and_scope($2)
35
- [is_name, type, scope]
140
+ [prefix, type, scope]
36
141
  end
37
-
142
+
38
143
  def resolve_type_and_scope(ref)
39
144
  return [:any, :any] unless ref
40
- return [ref, :ucs] if ref.is_a? Topic
41
- type, scope = ref.split('@', -1)
42
- if type.blank?
145
+ if ref[0] == ?@
43
146
  type = :any
147
+ scope = ref[1..-1] #cut "@"
44
148
  else
45
- type.strip!
149
+ type, scope = ref.split(' @', -1) # -1 -> trailing null fields are not suppressed
150
+ if (type == nil) || (type.length == 0)
151
+ type = :any
152
+ else
153
+ type.strip! #\s removed
154
+ end
46
155
  end
156
+
47
157
  if scope
48
- scope = scope.strip.split(/\s+/)
49
- scope = :ucs if scope.blank?
158
+ scope = scope.strip.split(/\s*,?\s+/) #divided at \s,\s
159
+ scope = :ucs if (scope == nil) || (scope.length == 0)
50
160
  else
51
161
  scope = :any
52
162
  end
@@ -54,4 +164,4 @@ module RTM::Sugar
54
164
  end
55
165
  end
56
166
  end
57
- end
167
+ end