rtm 0.2.0 → 0.2.1

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 (88) hide show
  1. data/README +38 -3
  2. data/lib/rtm.rb +25 -47
  3. data/lib/rtm/axes.rb +7 -4
  4. data/lib/rtm/axes/association.rb +1 -1
  5. data/lib/rtm/axes/associations.rb +1 -1
  6. data/lib/rtm/axes/characteristic.rb +1 -1
  7. data/lib/rtm/axes/characteristics.rb +1 -1
  8. data/lib/rtm/axes/topic.rb +3 -3
  9. data/lib/rtm/axes/topics.rb +3 -3
  10. data/lib/rtm/engine.rb +48 -5
  11. data/lib/rtm/extensions.rb +58 -8
  12. data/lib/rtm/io.rb +2 -1
  13. data/lib/rtm/io/tmapix_from.rb +155 -0
  14. data/lib/rtm/io/tmapix_to.rb +223 -0
  15. data/lib/rtm/io/to_hash.rb +79 -41
  16. data/lib/rtm/io/to_jtm.rb +1 -1
  17. data/lib/rtm/io/to_rdf.rb +20 -5
  18. data/lib/rtm/io/to_string.rb +13 -2
  19. data/lib/rtm/io/to_yaml.rb +39 -11
  20. data/lib/rtm/navigation.rb +1 -15
  21. data/lib/rtm/navigation/association/players.rb +1 -1
  22. data/lib/rtm/navigation/name/characteristics.rb +1 -1
  23. data/lib/rtm/navigation/occurrence/characteristics.rb +1 -1
  24. data/lib/rtm/navigation/topic/characteristics.rb +1 -1
  25. data/lib/rtm/navigation/topic/players.rb +1 -1
  26. data/lib/rtm/navigation/topic/supertypes.rb +21 -17
  27. data/lib/rtm/navigation/topic/traverse.rb +1 -1
  28. data/lib/rtm/navigation/topic/types.rb +6 -4
  29. data/lib/rtm/psi.rb +6 -0
  30. data/lib/rtm/sugar.rb +42 -29
  31. data/lib/rtm/sugar/association/hash_access.rb +3 -3
  32. data/lib/rtm/sugar/occurrence/dynamic_value.rb +39 -56
  33. data/lib/rtm/sugar/occurrence/external.rb +53 -0
  34. data/lib/rtm/sugar/reifiable/reifier.rb +21 -0
  35. data/lib/rtm/sugar/role/counterparts.rb +12 -6
  36. data/lib/rtm/sugar/topic/best_name.rb +74 -0
  37. data/lib/rtm/sugar/topic/characteristics.rb +10 -10
  38. data/lib/rtm/sugar/topic/counterparts.rb +131 -119
  39. data/lib/rtm/sugar/topic/scoped.rb +102 -53
  40. data/lib/rtm/sugar/topic/topic_ref.rb +63 -12
  41. data/lib/rtm/sugar/topic/typed.rb +50 -2
  42. data/lib/rtm/sugar/topic_map/query_cache.rb +66 -0
  43. data/lib/rtm/sugar/topic_map/themes.rb +53 -0
  44. data/lib/rtm/sugar/typed/types.rb +1 -1
  45. data/lib/rtm/validation.rb +2 -2
  46. data/lib/rtm/version.rb +18 -6
  47. data/spec/rtm/axes/string_spec.rb +7 -7
  48. data/spec/rtm/axes/strings_spec.rb +10 -10
  49. data/spec/rtm/io/tmapix_from_spec.rb +76 -0
  50. data/spec/rtm/io/tmapix_to_spec.rb +159 -0
  51. data/spec/rtm/io/to_hash_spec.rb +90 -0
  52. data/spec/rtm/io/to_rdf_spec.rb +37 -0
  53. data/spec/rtm/io/to_string_spec.rb +122 -0
  54. data/spec/rtm/io/to_yaml_spec.rb +89 -0
  55. data/spec/rtm/sugar/occurrence/dynamic_value_spec.rb +156 -1
  56. data/spec/rtm/sugar/occurrence/external_spec.rb +129 -0
  57. data/spec/rtm/sugar/reifiable/reifier_spec.rb +41 -0
  58. data/spec/rtm/sugar/role/counterparts_spec.rb +174 -172
  59. data/spec/rtm/sugar/topic/best_name_spec.rb +25 -0
  60. data/spec/rtm/sugar/topic/characteristics_spec.rb +20 -5
  61. data/spec/rtm/sugar/topic/counterparts_spec.rb +41 -1
  62. data/spec/rtm/sugar/topic/hash_access_spec.rb +1 -1
  63. data/spec/rtm/sugar/topic/scoped_spec.rb +178 -114
  64. data/spec/rtm/sugar/topic/topic_ref_spec.rb +10 -10
  65. data/spec/rtm/sugar/topic/typed_spec.rb +196 -134
  66. data/spec/rtm/sugar/topic_map/themes_spec.rb +67 -0
  67. data/spec/rtm/sugar/typed/types_spec.rb +1 -1
  68. data/spec/rtm/tmapi/core/association_spec.rb +2 -2
  69. data/spec/rtm/tmapi/core/datatype_aware_spec.rb +236 -0
  70. data/spec/rtm/tmapi/core/name_spec.rb +186 -1
  71. data/spec/rtm/tmapi/core/occurrence_spec.rb +24 -67
  72. data/spec/rtm/tmapi/core/reifiable_spec.rb +2 -2
  73. data/spec/rtm/tmapi/core/scoped_spec.rb +40 -2
  74. data/spec/rtm/tmapi/core/topic_map_spec.rb +98 -30
  75. data/spec/rtm/tmapi/core/topic_spec.rb +558 -82
  76. data/spec/rtm/tmapi/core/variant_spec.rb +3 -3
  77. data/spec/rtm_spec.rb +0 -1
  78. data/spec/spec_helper.rb +7 -2
  79. data/test/javalibs/junit-4.5.jar +0 -0
  80. data/test/javalibs/tmapi-2.0-tests.jar +0 -0
  81. data/test/tmapi_tests.rb +25 -0
  82. metadata +66 -11
  83. data/lib/rtm/io/ontopia_io.rb +0 -25
  84. data/lib/rtm/io/tmapix.rb +0 -234
  85. data/lib/rtm/sugar/occurrence/externalize.rb +0 -31
  86. data/spec/rtm/io/tmapix_spec.rb +0 -85
  87. data/test/base_unit_test.rb +0 -161
  88. data/test/base_unit_test_tmapi.rb +0 -165
@@ -1,7 +1,7 @@
1
1
  # Copyright: Copyright 2009 Topic Maps Lab, University of Leipzig.
2
2
  # License: Apache License, Version 2.0
3
3
 
4
- module Sugar
4
+ module RTM::Sugar
5
5
  module Association
6
6
  # This module implements methods for Hash-like access in Associations.
7
7
  module HashAccess
@@ -10,7 +10,7 @@ module Sugar
10
10
  #
11
11
  # If type is given, returns the Roles of this Association
12
12
  # whose Role type match type.
13
- # Type may be a Topic or Topic-Reference.
13
+ # Type may be a topic reference.
14
14
  #
15
15
  # The result may be empty.
16
16
  #
@@ -32,7 +32,7 @@ module Sugar
32
32
 
33
33
  # Creates a new Role in this Association where type specifies the
34
34
  # Role type and player the associated Role player.
35
- # Type and player may each be a Topic, String-Reference or Locator.
35
+ # Type and player may each be a topic reference.
36
36
  #
37
37
  # :call-seq:
38
38
  # [type]= player
@@ -1,34 +1,43 @@
1
1
  # Copyright: Copyright 2010 Topic Maps Lab, University of Leipzig.
2
2
  # License: Apache License, Version 2.0
3
3
 
4
- module Sugar::Occurrence
4
+ module RTM::Sugar::Occurrence
5
5
  module DynamicValue
6
- # Returns the value of this occurrence cast as appropriate Ruby type.
6
+
7
+ # Given the occurrence's datatype this method returns the value of this
8
+ # occurrence cast as appropriate Ruby type.
9
+ #
10
+ # :call-seq:
11
+ # dynamic_value -> Object
12
+ #
7
13
  def dynamic_value
8
- case self.datatype.to_external_form # first_oc.datatype is actually of type Locator
9
- when RTM::PSI[:Decimal]
10
- self.value.to_f
11
- when RTM::PSI[:Double]
12
- self.value.to_f
13
- when RTM::PSI[:Int]
14
- self.value.to_i
15
- when RTM::PSI[:Integer]
16
- self.value.to_i
17
- when RTM::PSI[:Float]
18
- self.value.to_f
19
- when RTM::PSI[:Long]
20
- self.value.to_i
21
- # Date, ... missing
22
- else
23
- self.value
24
- end
25
- end
26
-
27
- class NoDatatypeHandlerAvailableException < Exception
28
- def initialize(value)
29
- super "Cannot map #{value} to an occurrence value+datatype. Maybe you need to add a handler for your Ruby object type."
14
+ value = self.value # a String
15
+ case self.datatype.reference
16
+ when RTM::PSI[:IRI]
17
+ return topic_map.create_locator(value)
18
+ when RTM::PSI[:Decimal]
19
+ return value.to_f
20
+ when RTM::PSI[:Double]
21
+ return value.to_f
22
+ when RTM::PSI[:Int]
23
+ return value.to_i
24
+ when RTM::PSI[:Integer]
25
+ return value.to_i
26
+ when RTM::PSI[:Float]
27
+ return value.to_f
28
+ when RTM::PSI[:Long]
29
+ return value.to_i
30
+ when RTM::PSI[:Date]
31
+ return Date.parse(value)
32
+ when RTM::PSI[:DateTime]
33
+ return DateTime.parse(value)
34
+ when RTM::PSI[:Time]
35
+ return Time.parse(value)
36
+ else
37
+ return value
30
38
  end
31
39
  end
40
+
32
41
  end
33
42
  end
34
43
 
@@ -37,39 +46,13 @@ class Float
37
46
  s = self.to_s
38
47
 
39
48
  case s
40
- when "Infinity"
41
- "INF"
42
- when "-Infinity"
43
- "-INF"
44
- else
45
- s
49
+ when "Infinity"
50
+ "INF"
51
+ when "-Infinity"
52
+ "-INF"
53
+ else
54
+ s
46
55
  end
47
56
  end
48
57
  end
49
58
 
50
- module Sugar::Topic::Characteristics
51
- #
52
- # Weird. create_occurrence has an options hash, and we don't have one. We should unify the syntax. What is the right thing to do?
53
- #
54
- def dynamic_create_occurrence(type,value,datatype,scope = nil)
55
- if !datatype # well, let's choose one
56
- case value
57
- when Integer
58
- datatype = RTM::PSI[:Integer]
59
- use_value = value.to_s
60
- when Float
61
- datatype = RTM::PSI[:Double]
62
- use_value = value.to_xsd_double
63
- when String
64
- datatype = RTM::PSI[:String]
65
- use_value = value
66
- else
67
- raise Sugar::Occurrence::DynamicValue::NoDatatypeHandlerAvailableException.new(value)
68
- end
69
- else
70
- use_value = value
71
- end
72
-
73
- create_occurrence(type,use_value,:datatype => datatype, :scope => scope)
74
- end
75
- end
@@ -0,0 +1,53 @@
1
+ # Copyright: Copyright 2009 Topic Maps Lab, University of Leipzig.
2
+ # License: Apache License, Version 2.0
3
+
4
+ module RTM::Sugar::Occurrence
5
+ module External
6
+
7
+ # Creates an association out of this occurrence which represents the
8
+ # occurrence information in relation to the parent topic.
9
+ #
10
+ # The association is of type "http://psi.topicmapslab.de/subject-representation".
11
+ # It includes two roles. The parent topic plays the role of type
12
+ # "http://psi.topicmapslab.de/represented-subject". The topic with the
13
+ # subject locator created from the occurrence value plays the role
14
+ # of a type the same as the occurrence type.
15
+ #
16
+ # The subject locator will be resolved using the get-method of RTM::TopicMap,
17
+ # that means if the occurrence value is stored as String and is not a valid uri
18
+ # the base_iri of the topic map is used to create one.
19
+ #
20
+ # The occurrence datatype may be xsd:anyURI as well as xsd:String.
21
+ # The occurrence value must be a valid URL.
22
+ #
23
+ # Example: Creates an association out of the occurrence with value
24
+ # "http://www.leipzig.de" and type "webpage" of the topic Leipzig:
25
+ # * association type: subject_representation
26
+ # * role 1: Leipzig plays the role "represented_subject"
27
+ # * role 2: topic with subject locator "http://www.leipzig.de" plays the role "webpage"
28
+ #
29
+ # :call-seq:
30
+ # externalize -> Association
31
+ #
32
+ def externalize
33
+ topic_map.create_association(RTM::PSI[:subject_representation], RTM::PSI[:represented_subject] => parent, self.type => "=#{self.value}")
34
+ end
35
+
36
+ # Executes externalize and removes this occurrence from the topic map afterwards
37
+ #
38
+ # :call-seq:
39
+ # externalize!
40
+ #
41
+ def externalize!(*args)
42
+ association = externalize(*args)
43
+ remove
44
+ return association
45
+ end
46
+
47
+ # Returns true, if the datatype of this occurrence equals xsd:anyURI.
48
+ def external?
49
+ return self.datatype.reference == RTM::PSI[:IRI] ? true : false
50
+ end
51
+
52
+ end
53
+ end
@@ -0,0 +1,21 @@
1
+ # Copyright: Copyright 2009 Topic Maps Lab, University of Leipzig.
2
+ # License: Apache License, Version 2.0
3
+
4
+ module RTM::Sugar::Reifiable
5
+ module CreateReifier
6
+
7
+ # Returns the reifier (a topic) of this Reifiable.
8
+ # If there is no current reifier, then a reifier will be generated.
9
+ # This reifier did not exist in the topic map before.
10
+ #
11
+ # :call-seq:
12
+ # reifier! -> Topic
13
+ #
14
+ def reifier!
15
+ self.reifier ||= self.topic_map.create_topic
16
+ end
17
+ alias :create_reifier :reifier!
18
+
19
+ end
20
+ end
21
+
@@ -1,14 +1,16 @@
1
1
  # Copyright: Copyright 2009 Topic Maps Lab, University of Leipzig.
2
2
  # License: Apache License, Version 2.0
3
3
 
4
- module Sugar::Role
4
+ module RTM::Sugar::Role
5
5
  module Counterparts
6
6
 
7
- # Returns all Roles from the parent Association of this Role,
7
+ # Returns all roles from the parent association of this role,
8
8
  # except itself.
9
9
  #
10
- # A filter-hash may be used to filter for the type of the other Roles
11
- # (:otype). The identfier may be a Topic or Topic-Reference.
10
+ # A filter-hash may be used to filter for the type of the other roles
11
+ # (:otype) or the player of the other roles (:oplayer).
12
+ #
13
+ # The identfiers may be topic references.
12
14
  #
13
15
  # :call-seq:
14
16
  # counterparts -> Array of Roles
@@ -16,7 +18,11 @@ module Sugar::Role
16
18
  #
17
19
  def counterparts(filter={})
18
20
  _roles = parent.roles.reject{|r| r.id==self.id}
19
- return filter[:otype] ? _roles.select{|r| r.type == topic_map.get(filter[:otype]) } : _roles
21
+ otype = filter[:otype]
22
+ _roles = _roles.select{|r| r.type == topic_map.get(otype)} if otype && otype != :any
23
+ oplayer = filter[:oplayer]
24
+ _roles = _roles.select{|r| r.player == topic_map.get(oplayer)} if oplayer && oplayer != :any
25
+ return _roles
20
26
  end
21
27
 
22
28
  # Returns the other role, if the parent association is binary.
@@ -35,7 +41,7 @@ module Sugar::Role
35
41
  # except the player of itself.
36
42
  #
37
43
  # A filter-hash may be used to filter for the type of the other Roles
38
- # (:otype). The identifier may be a Topic or Topic-Reference.
44
+ # (:otype). The identifier may be a topic reference.
39
45
  #
40
46
  # :call-seq:
41
47
  # counterplayers -> Array of Topics
@@ -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,9 +1,9 @@
1
1
  # Copyright: Copyright 2009 Topic Maps Lab, University of Leipzig.
2
2
  # License: Apache License, Version 2.0
3
3
 
4
- module Sugar::Topic::Characteristics
4
+ module RTM::Sugar::Topic::Characteristics
5
5
 
6
- # Returns all Occurrences of this Topic whose Datatype is not IRI
6
+ # Returns all Occurrences of this Topic whose datatype is not IRI
7
7
  #
8
8
  # :call-seq:
9
9
  # internal_occurrences -> Set of Occurrences
@@ -12,7 +12,7 @@ module Sugar::Topic::Characteristics
12
12
  occurrences.select{|x| x.getDatatype.toExternalForm != RTM::PSI[:IRI]}
13
13
  end
14
14
 
15
- # Returns all Occurrences of this Topic whose Datatype is IRI
15
+ # Returns all Occurrences of this Topic whose datatype is IRI
16
16
  #
17
17
  # :call-seq:
18
18
  # external_occurrences -> Set of Occurrences
@@ -21,15 +21,15 @@ module Sugar::Topic::Characteristics
21
21
  occurrences.select{|y| y.getDatatype.toExternalForm == RTM::PSI[:IRI]}
22
22
  end
23
23
 
24
- # Returns the Names of this Topic which may be filtered for their type,
24
+ # Returns the names of this topic which may be filtered for their type,
25
25
  # value and/or scope.
26
26
  #
27
- # If scope is set to :ucs, Names which exist in the unconstrained scope
27
+ # If scope is set to :ucs, names which exist in the unconstrained scope
28
28
  # are selected. If scope is set to :any (default), scope does not constrain
29
- # the Names-Array. Else, only the Names which exist in the given scope
30
- # are selected.
29
+ # the names-Array. Else, only the names which whose scope contains one of the
30
+ # given themes are returned.
31
31
  #
32
- # Returns an empty Array if no Names match or if the Name type
32
+ # Returns an empty Array if no names match or if the name type
33
33
  # or scope does not exist.
34
34
  #
35
35
  # :call-seq:
@@ -57,8 +57,8 @@ module Sugar::Topic::Characteristics
57
57
  #
58
58
  # If scope is set to :ucs, Occurrences which exist in the unconstrained scope
59
59
  # are selected. If scope is set to :any (default), scope does not constrain
60
- # the Occurrence-Array. Else, only the Occurrences which exist in the given scope
61
- # are selected.
60
+ # the Occurrence-Array. Else, only the occurrences which whose scope contains
61
+ # one of the given themes are returned.
62
62
  #
63
63
  # Returns an empty Array if no Occurrences match or if the Occurrence type or
64
64
  # scope does not exist.
@@ -1,138 +1,150 @@
1
1
  # Copyright: Copyright 2009 Topic Maps Lab, University of Leipzig.
2
2
  # License: Apache License, Version 2.0
3
3
 
4
- module Sugar
5
- module Topic
6
- module Counterparts
4
+ module RTM::Sugar::Topic
5
+ module Counterparts
7
6
 
8
- # Returns all Roles belonging to Associations in which this Topic
9
- # is a player and for which this Topic is not the player.
10
- #
11
- # A filter-hash may be used to filter for the the type
12
- # of the Role this Topic playes
13
- # (:rtype), for the Association type (:atype) and/or
14
- # for the type of the returned Roles (:otype). The
15
- # identifier may be a Topic, String-Reference or Locator.
16
- #
17
- # The result may be empty.
18
- #
19
- # :call-seq:
20
- # counterparts -> Array of Roles
21
- # counterparts({:rtype => identifier}) -> Array of Roles
22
- # counterparts({:atype => identifier}) -> Array of Roles
23
- # counterparts({:otype => identifier}) -> Array of Roles
24
- # counterparts({:rtype => identifier, :atype => identifier}) -> Array of Roles
25
- # counterparts({:rtype => identifier, :atype => identifier, :otype => identifier}) -> Array of Roles
26
- #
27
- def counterparts(filter={})
28
- roles.select{|r| filter[:rtype] ? r.type == self.topic_map.get(filter[:rtype]) : true}.
29
- select{|r| filter[:atype] ? r.parent.type == self.topic_map.get(filter[:atype]) : true}.
30
- inject([]){|all,r| all+=r.counterparts(filter)}
31
- end
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
32
31
 
33
- # Returns all Topics that are players of Roles belonging to Associations
34
- # in which this Topic is another player. The resulting Array does
35
- # not contain duplicates.
36
- #
37
- # A filter-hash may be used to filter for the the type
38
- # of the Role this Topic playes
39
- # (:rtype), for the Association type (:atype) and/or
40
- # for the type of the Roles the returned Topics play (:otype). The
41
- # identifier may be a Topic, String-Reference or Locator.
42
- #
43
- # The result may be empty.
44
- #
45
- # :call-seq:
46
- # counterplayers -> Array of Topics
47
- # counterplayers(:rtype => identifier) -> Array of Topics
48
- # counterplayers(:atype => identifier) -> Array of Topics
49
- # counterplayers(:otype => identifier) -> Array of Topics
50
- # counterplayers(:rtype => identifier1, :atype => identifier2) -> Array of Topics
51
- # counterplayers(:rtype => identifier1, :atype => identifier2, :otype => identifier3) -> Array of Topics
52
- #
53
- def counterplayers(filter={})
54
- return counterparts(filter).map{|r| r.player}.uniq
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
55
  end
56
+ end
56
57
 
57
- # Returns all players (Topics) which share a counterplayer with this Topic (player),
58
- # If type is given, it may constrain the type of the Role this Topic should play
59
- # (and therefore the type of the Roles the peers play)
60
- # or the type of the Association this Topic plays a Role in
61
- # (and therefore the type of the Associations the peers play an Role in).
62
- #
63
- # Type may be a Topic or Topic-Reference.
64
- #
65
- # The result may be empty.
66
- #
67
- # :call-seq:
68
- # peers -> Array of Topics
69
- # peers(type) -> Array of Topics
70
- #
71
- def peers(type=:any)
72
- _peers = []
73
- if type == :any
74
- self.roles.each do |r|
75
- _peers = _peers + r.peers(:arity => :loose, :atype => :loose, :otype => :loose, :rtype => :loose)
76
- end
77
- else
78
- type = topic_map.get(type)
79
- if type
80
- if self.roles.map{|r| r.type}.include?(type) #-> rtype
81
- self.roles(type).each do |r|
82
- _peers = _peers + r.peers(:arity => :loose, :atype => :loose, :otype => :loose, :rtype => :strict)
83
- end
84
- elsif self.roles.map{|r| r.parent.type}.include?(type) #->atype
85
- self.roles.select{|r| r.parent.type == type}.each do |r|
86
- _peers = _peers + r.peers(:arity => :loose, :atype => :strict, :otype => :loose, :rtype => :strict)
87
- end
88
- elsif self.roles.map{|r| r.counterparts}.flatten.map{|r| r.type}.include?(type) #-> otype
89
- # nothing can happen so far
90
- else
91
- return []
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)
92
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
93
91
  else
94
92
  return []
95
93
  end
94
+ else
95
+ return []
96
96
  end
97
- return _peers.map{|r| r.player}
98
97
  end
98
+ return _peers.map{|r| r.player}
99
+ end
99
100
 
100
- # Returns all Associations in which this Topic
101
- # is a player.
102
- #
103
- # A filter-hash may be used to filter
104
- # for the type of the Role this Topic plays (:rtype),
105
- # for the Association type (:atype),
106
- # for the type of another role (:otype) as well as
107
- # for the player of this other role (:oplayer).
108
- # Each value of this filter-hash may be a Topic, String-Reference or Locator.
109
- #
110
- # The result may be empty.
111
- #
112
- # :call-seq:
113
- # associations_played -> Array of Associations
114
- # associations_played({:rtype => identifier}) -> Array of Associations
115
- # associations_played({:atype => identifier}) -> Array of Associations
116
- # associations_played({:otype => identifier}) -> Array of Associations
117
- # associations_played({:otype => identifier, :oplayer => identifier}) -> Array of Associations
118
- # associations_played({:rtype => identifier, :atype => identifier}) -> Array of Associations
119
- # associations_played({:rtype => identifier, :atype => identifier, :otype => identifier}) -> Array of Associations
120
- # associations_played({:rtype => identifier, :atype => identifier, :otype => identifier, :oplayer => identifier}) -> Array of Associations
121
- #
122
- def associations_played(filter = {})
123
- roles = self.counterparts(filter)
124
-
125
- if filter[:oplayer]
126
- oplayer = topic_map.get(filter[:oplayer])
127
- roles = roles.map do |role|
128
- (role.player==oplayer)?role:nil
129
- end.compact
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
130
142
  end
131
-
132
- roles.map do |role|
133
- role.parent
134
- end.uniq
143
+
144
+ # return parent associations
145
+ roles.map{|role| role.parent}.uniq
135
146
  end
136
147
  end
148
+
137
149
  end
138
150
  end