Module: Java::OrgTmapiCore::TopicMap
- Extended by:
- Superiseable
- Includes:
- RTM::TopicMap
- Defined in:
- lib/rtm/javatmapi/core/topic_map.rb,
lib/rtm/javatmapi/aliases.rb
Overview
Copyright: Copyright 2009 Topic Maps Lab, University of Leipzig. License: Apache License, Version 2.0
Constant Summary collapse
- URI_PATTERN =
":"
Instance Attribute Summary collapse
-
#engine ⇒ Object
readonly
Returns the value of attribute engine.
-
#prefixes ⇒ Object
readonly
hash.
Instance Method Summary collapse
-
#add_prefix(identifier, reference) ⇒ Object
Adds the identifier (key) and reference (value) to the prefixes-Hash and returns all prefixes.
-
#associations(type = :any) ⇒ Object
(also: #a)
Returns all associations contained in this topic map.
-
#base_iri ⇒ Object
(also: #base_locator)
returns the base iri of this topic map.
-
#children ⇒ Object
(also: #reverse_parent)
Returns all Associations and Topics contained in this TopicMap.
- #construct_by_id(id) ⇒ Object
-
#create_association(type, *args) {|assoc| ... } ⇒ Object
Creates an Association in this TopicMap.
-
#create_locator(identifier) ⇒ Object
Returns a Locator representing the identifier.
-
#create_topic_by(identifier) ⇒ Object
Assumes identifier is an IRI (Locator or String) or an Array of IRIs.
-
#create_topic_by_item_identifier(identifier) ⇒ Object
Assumes identifier is a item identifier (Locator or String) or an Array of item identifiers (Locators and/or Strings).
-
#create_topic_by_subject_identifier(identifier) ⇒ Object
Assumes identifier is a subject identifier (Locator or String) or an Array of subject identifiers (Locators and/or Strings).
-
#create_topic_by_subject_locator(identifier) ⇒ Object
Assumes identifier is a subject locator (Locator or String) or an Array of subject locators (Locators and/or Strings).
-
#delete_prefix(identifier, reference = :any) ⇒ Object
(also: #del_prefix)
Deletes a prefix (given the identifier) from the prefixes-Hash and returnes the remaining prefixes.
-
#find_prefix(filter = {}) ⇒ Object
Returns the prefixes that match the given the identifier and/or reference.
-
#get(identifier) ⇒ Object
(also: #topic)
If identifier is a Topic, returns this Topic.
-
#get!(identifier) ⇒ Object
(also: #topic!)
Calls get(identifier) and returns the Topic or Array of Topics according to the nature of the identifier (Topic/Topic-References or Array of those types).
-
#get_construct_by_item_identifier(identifier) ⇒ Object
(also: #by_ii)
Assumes identifier is an item identifier (Locator or String) or an Array of item identifiers (Locators and/or Strings) and returns a Construct or an Array of Constructs by its/their item identifier/s.
-
#get_topic_by_subject_identifier(identifier) ⇒ Object
(also: #by_si)
Assumes identifier is a subject identifier (Locator or String) or an Array of subject identifiers (Locators and/or Strings) and returns a Topic or an Array of Topics by its/their subject identifier/s.
-
#get_topic_by_subject_locator(identifier) ⇒ Object
(also: #by_sl)
Assumes identifier is a subject locator (Locator or String) or an Array of subject locators (Locators and/or Strings) and returns a Topic or an Array of Topics by its/their subject locator/s.
-
#instances(type = :any) ⇒ Object
Returns all topics in the topic map that are used as instance in an “type-instance”-relationship.
-
#literal_index ⇒ Object
(also: #li)
Calls TMAPI TopicMap.getIndex which returns the index for the LiteralIndex.
-
#names ⇒ Object
Returns all names occurring in the topic map.
-
#occurrences ⇒ Object
Returns all occurrences occurring in the topic map.
-
#parent ⇒ Object
(also: #reverse_children)
Returns nil.
-
#roles ⇒ Object
Returns all roles occurring in the topic map.
-
#scoped_index ⇒ Object
(also: #si)
Calls TMAPI TopicMap.getIndex which returns the index for the ScopedIndex.
- #set_engine(engine) ⇒ Object
-
#topics(type = :any) ⇒ Object
(also: #t)
Returns all topics contained in this topic map.
-
#type_instance_index ⇒ Object
(also: #tii)
Calls TMAPI TopicMap.getIndex which returns the index for the TypeInstanceIndex.
-
#types ⇒ Object
Returns all topics in the topic map that are used as type in an “type-instance”-relationship.
-
#variants ⇒ Object
Returns all variants occurring in the topic map.
Methods included from Superiseable
method_added, register_java_implementation, superised, superising
Instance Attribute Details
#engine ⇒ Object (readonly)
Returns the value of attribute engine.
12 13 14 |
# File 'lib/rtm/javatmapi/core/topic_map.rb', line 12 def engine @engine end |
#prefixes ⇒ Object (readonly)
hash
11 12 13 |
# File 'lib/rtm/javatmapi/core/topic_map.rb', line 11 def prefixes @prefixes end |
Instance Method Details
#add_prefix(identifier, reference) ⇒ Object
Adds the identifier (key) and reference (value) to the prefixes-Hash and returns all prefixes. Qnames consisting of “identifier:localpart” will be converted to “referencelocalpart”.
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/rtm/javatmapi/core/topic_map.rb', line 38 def add_prefix(identifier, reference) unless identifier.is_a?(String) && reference.is_a?(String) raise("add_prefix: identifier and reference must be Strings") # TODO @raise in yardoc end if identifier.empty? || reference.empty? raise("add_prefix: identifier or reference may not be empty") end if (identifier == "sl") || (identifier == "si") || (identifier == "ii") raise("add_prefix: identifier 'sl', 'si' or 'ii' not allowed for prefixes") end unless reference.include?(URI_PATTERN) raise("add_prefix: reference must be absulute") end # prefix xsd is allowed prefixes[identifier]= reference prefixes end |
#associations(type = :any) ⇒ Object Also known as: a
Returns all associations contained in this topic map.
The optional argument specifies the type the associations should have, i.e. all instances of the specified type are returned. Type may be a topic reference.
The return value may be empty.
:call-seq:
associations -> Set of Associations
associations(type) -> Array of Associations
287 288 289 290 291 292 |
# File 'lib/rtm/javatmapi/core/topic_map.rb', line 287 def associations(type = :any) return getAssociations if type == :any raise("associations(type): type must be a topic reference.") unless (type.is_a?(RTM::Topic) || type.is_a?(RTM::Locator) || type.is_a?(String)) type = self.get(type) unless type.is_a?(RTM::Topic) return type ? type_instance_index.getAssociations(type).to_a : [] end |
#base_iri ⇒ Object Also known as: base_locator
returns the base iri of this topic map
19 20 21 |
# File 'lib/rtm/javatmapi/core/topic_map.rb', line 19 def base_iri getLocator.reference end |
#children ⇒ Object Also known as: reverse_parent
Returns all Associations and Topics contained in this TopicMap.
:call-seq:
children -> Array of Associations and/or Topics
130 131 132 |
# File 'lib/rtm/javatmapi/core/topic_map.rb', line 130 def children getAssociations.to_a + getTopics.to_a end |
#construct_by_id(id) ⇒ Object
548 549 550 |
# File 'lib/rtm/javatmapi/core/topic_map.rb', line 548 def construct_by_id(id) getConstructById(id) end |
#create_association(type, *args) {|assoc| ... } ⇒ Object
Creates an Association in this TopicMap.
Type specifies the Association type.
If given, scope specifies the association scope; else the Association is in the unconstrained scope. Scope must be an Array of identifiers.
The last argument - a roles-Hash - is optional. If given, all specified roles will be created additionally. A role is specified by the role type: the key in the Hash and the role player: the corresponding value in the Hash.
Each identifier (type, scope-identifier, roletype-identifier and player-identifier) may be a topic reference.
:call-seq:
create_association(type) -> Association
create_association(type, scope-Array) -> Association
create_association(type, roletype-identifier => player-identifier, ...) -> Association
create_association(type, scope-Array, roletype-identifier => player-identifier, ...) -> Association
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 |
# File 'lib/rtm/javatmapi/core/topic_map.rb', line 158 def create_association(type, *args) roles = {} if args.size == 0 # no args -> no scope and no roles given scope = :ucs elsif args.size == 1 # args may be an array (scope) or hash (roles) argument = args[0] if argument.is_a?(Array) scope = argument elsif argument.is_a?(Hash) scope = :ucs roles = argument else raise("create_association: arguments after type may be an Array or Hash") end else # several arguments after type argument1 = args[0] argument2 = args[1] if argument1.is_a?(Array) scope = argument1 roles = argument2 elsif argument1.is_a?(Hash) scope = :ucs roles = argument1 else raise("create_association: arguments after type may be an Array or Hash") end end raise("create_association: type must be a Topic or Topic-Reference") unless type.is_a?(Java::OrgTmapiCore::Topic) || type.is_a?(String) || type.is_a?(Java::OrgTmapiCore::Locator) if scope == :ucs assoc = createAssociation(get!(type),[].to_java(Java::OrgTmapiCore::Topic)) else raise("create_association: scope must be an Array") unless scope.is_a?(Array) assoc = scope.empty? ? createAssociation(get!(type),[].to_java(Java::OrgTmapiCore::Topic)) : createAssociation(get!(type),get!(scope)) end raise("create_association: roles must be a Hash") unless roles.is_a?(Hash) roles.each do |k,v| if v.is_a?(Array) v.each{|player| assoc.create_role(k,player)} else assoc.create_role(k,v) end end yield assoc if block_given? return assoc end |
#create_locator(identifier) ⇒ Object
Returns a Locator representing the identifier. Identifier may be a String (IRI).
:call-seq:
create_locator(identifier) -> Locator
319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 |
# File 'lib/rtm/javatmapi/core/topic_map.rb', line 319 def create_locator(identifier) return identifier if identifier.is_a?(Java::OrgTmapiCore::Locator) raise("create_locator: identifier must be a String") unless identifier.is_a?(String) qname = check_for_qname(identifier) if qname identifier = qname else unless identifier.include?(URI_PATTERN) begin identifier = getLocator.resolve(identifier) rescue org.tmapi.core.MalformedIRIException => mie raise(mie.) end return identifier end end begin identifier = createLocator(identifier) rescue org.tmapi.core.MalformedIRIException => mie raise(mie.) end return identifier end |
#create_topic_by(identifier) ⇒ Object
Assumes identifier is an IRI (Locator or String) or an Array of IRIs. Returns an existing or created Topic or an Array of Topics according to the nature of the IRI.
:call-seq:
create_topic_by(identifier) -> Topic
create_topic_by(identifier-Array) -> Array of Topics
457 458 459 460 461 462 463 464 465 466 467 468 |
# File 'lib/rtm/javatmapi/core/topic_map.rb', line 457 def create_topic_by(identifier) case identifier when Java::OrgTmapiCore::Locator return create_topic_by_subject_identifier(identifier) when String reroute_for_create(identifier) when Array return identifier.map{|i| create_topic_by(i)} else return nil end end |
#create_topic_by_item_identifier(identifier) ⇒ Object
Assumes identifier is a item identifier (Locator or String) or an Array of item identifiers (Locators and/or Strings). Either returns an existing Topic (or Array of Topics) or creates a/ new Topic instance/s with the specified item identifier/s.
:call-seq:
create_topic_by_item_identifier(identifier) -> Topic
create_topic_by_item_identifier(identifier-Array) -> Array of Topics
If a topic with the specified item identifier exists in the topic map, that topic is returned. If a topic with a subject identifier equals to the specified item identifier exists, the specified item identifier is added to that topic and the topic is returned. If neither a topic with the specified item identifier nor with a subject identifier equals to the subject identifier exists, a topic with the item identifier is created.
445 446 447 |
# File 'lib/rtm/javatmapi/core/topic_map.rb', line 445 def create_topic_by_item_identifier(identifier) get_stuff(identifier){|x| createTopicByItemIdentifier(x)} end |
#create_topic_by_subject_identifier(identifier) ⇒ Object
Assumes identifier is a subject identifier (Locator or String) or an Array of subject identifiers (Locators and/or Strings). Either returns an existing Topic (or Array of Topics) or creates a/ new Topic instance/s with the specified subject identifier/s.
:call-seq:
create_topic_by_subject_identifier(identifier) -> Topic
create_topic_by_subject_identifier(identifier-Array) -> Array of Topics
If a topic with the specified subject identifier exists in the topic map, that topic is returned. If a topic with an item identifier equals to the specified subject identifier exists, the specified subject identifier is added to that topic and the topic is returned. If neither a topic with the specified subject identifier nor with an item identifier equals to the subject identifier exists, a topic with the subject identifier is created.
411 412 413 |
# File 'lib/rtm/javatmapi/core/topic_map.rb', line 411 def create_topic_by_subject_identifier(identifier) get_stuff(identifier){|x| createTopicBySubjectIdentifier(x)} end |
#create_topic_by_subject_locator(identifier) ⇒ Object
Assumes identifier is a subject locator (Locator or String) or an Array of subject locators (Locators and/or Strings). Either returns an existing Topic (or Array of Topics) or creates a/ new Topic instance/s with the specified subject locators/s.
:call-seq:
create_topic_by_subject_locator(identifier) -> Topic
create_topic_by_subject_locator(identifier-Array) -> Array of Topics
425 426 427 |
# File 'lib/rtm/javatmapi/core/topic_map.rb', line 425 def create_topic_by_subject_locator(identifier) get_stuff(identifier){|x| createTopicBySubjectLocator(x)} end |
#delete_prefix(identifier, reference = :any) ⇒ Object Also known as: del_prefix
Deletes a prefix (given the identifier) from the prefixes-Hash and returnes the remaining prefixes.
If reference is given, it must match the value of the identifier (key) in the prefixes-Hash - if not, the prefix is not deleted.
The result may be empty.
:call-seq:
delete_prefix(identifier) -> Hash
delete_prefix(identifier,reference) -> Hash
70 71 72 73 74 75 76 77 78 79 |
# File 'lib/rtm/javatmapi/core/topic_map.rb', line 70 def delete_prefix(identifier,reference = :any) #warn("delete_prefix: identifier not found") unless prefixes.has_key?(identifier) #warn("delete_prefix: reference does not match") unless reference == :any || reference == prefixes[identifier] if reference == :any prefixes.delete(identifier) else prefixes.delete_if{|k,v| k == identifier && v == reference} end prefixes end |
#find_prefix(filter = {}) ⇒ Object
Returns the prefixes that match the given the identifier and/or reference.
:call-seq:
find_prefix -> Hash
find_prefix({:identifier => String}) -> Hash
find_prefix({:reference => String}) -> Hash
find_prefix({:identifier => String, :reference => String}) -> Hash
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/rtm/javatmapi/core/topic_map.rb', line 91 def find_prefix(filter = {}) #TODO Specs identifier = filter[:identifier] reference = filter[:reference] if identifier && reference return prefixes.select{|k,v| k == identifier && v == reference} end if identifier return prefixes.select{|k,v| k == identifier} elsif reference return prefixes.select{|k,v| v == reference} else prefixes end end |
#get(identifier) ⇒ Object Also known as: topic
If identifier is a Topic, returns this Topic.
If identifier is a Locator, returns the Topic specified by the Locator (as item identifier or subject identifier).
If identifier is a String, returnes the Topic which has this String as subject identifier (by default or if the String starts with “si:”) or as subject locator (if the String starts with a “=” or “sl:”) or as item identifier (if the String starts with a “^” or “ii:”).
Returns an Array of Topics if an Array of identifiers is given according to the rules above.
Given one identifier, if no Topic is found, returns nil.
Given an Array of identifiers, if no Topics are found, returnes an empty Array.
:call-seq:
get(identifier) -> Topic or nil
get(identifier-Array) -> Array of Topics or empty Array
491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 |
# File 'lib/rtm/javatmapi/core/topic_map.rb', line 491 def get(identifier) self.cached(self, :get, identifier) { case identifier when nil nil when Java::OrgTmapiCore::Topic identifier when Java::OrgTmapiCore::Locator if get_construct_by_item_identifier(identifier).is_a?(Java::OrgTmapiCore::Topic) get_construct_by_item_identifier(identifier) elsif get_topic_by_subject_identifier(identifier) get_topic_by_subject_identifier(identifier) else #return get_topic_by_subject_locator(identifier) if get_topic_by_subject_locator(identifier) #not allowed because Topics with equals si and ii are merged but sl not nil end when String reroute_for_get(identifier) when Array # in: multi array -> out: multi array identifier.map{|i| get(i)} #when Hash #TODO: use case for getting Topics if argument is a hash else raise("get(#{identifier.inspect}): arguments do not match") end } end |
#get!(identifier) ⇒ Object Also known as: topic!
Calls get(identifier) and returns the Topic or Array of Topics according to the nature of the identifier (Topic/Topic-References or Array of those types).
Calls create_topic_by(identifier) if a Topic specified by identifier does not exist in the TopicMap. Returns the created and/our found Topic/s.
If identifier is a String, returnes/creates the Topic which has this String as subject identifier (by default or if the String starts with “si:”) or as subject locator (if the String starts with a “=” or “sl:”) or as item identifier (if the String starts with a “^” or “ii:”).
:call-seq:
get!(identifier) -> Topic
get!(identifier-Array) -> Array of Topics
538 539 540 541 542 543 544 545 |
# File 'lib/rtm/javatmapi/core/topic_map.rb', line 538 def get!(identifier) return nil unless identifier if identifier.is_a?(Array) return identifier.map{|i| get!(i)} end found = get(identifier) return found ? found : create_topic_by(identifier) end |
#get_construct_by_item_identifier(identifier) ⇒ Object Also known as: by_ii
Assumes identifier is an item identifier (Locator or String) or an Array of item identifiers (Locators and/or Strings) and returns a Construct or an Array of Constructs by its/their item identifier/s.
:call-seq:
get_construct_by_item_identifier(identifier) -> Construct
get_construct_by_item_identifier(identifier-Array) -> Array of Constructs
353 354 355 356 357 358 |
# File 'lib/rtm/javatmapi/core/topic_map.rb', line 353 def get_construct_by_item_identifier(identifier) identifier = create_locator(identifier) if identifier.is_a?(String) return getConstructByItemIdentifier(identifier) if identifier.is_a?(Java::OrgTmapiCore::Locator) return identifier.map{|i| get_topic_by_subject_locator(i)} if identifier.is_a?(Array) return nil end |
#get_topic_by_subject_identifier(identifier) ⇒ Object Also known as: by_si
Assumes identifier is a subject identifier (Locator or String) or an Array of subject identifiers (Locators and/or Strings) and returns a Topic or an Array of Topics by its/their subject identifier/s.
:call-seq:
get_topic_by_subject_identifier(identifier) -> Topic
get_topic_by_subject_identifier(identifier-Array) -> Array of Topics
370 371 372 373 374 375 |
# File 'lib/rtm/javatmapi/core/topic_map.rb', line 370 def get_topic_by_subject_identifier(identifier) identifier = create_locator(identifier) if identifier.is_a?(String) return getTopicBySubjectIdentifier(identifier) if identifier.is_a?(Java::OrgTmapiCore::Locator) return identifier.map{|i| get_topic_by_subject_locator(i)} if identifier.is_a?(Array) return nil end |
#get_topic_by_subject_locator(identifier) ⇒ Object Also known as: by_sl
Assumes identifier is a subject locator (Locator or String) or an Array of subject locators (Locators and/or Strings) and returns a Topic or an Array of Topics by its/their subject locator/s.
:call-seq:
get_topic_by_subject_locator(identifier) -> Topic
get_topic_by_subject_locator(identifier-Array) -> Array of Topics
387 388 389 390 391 392 |
# File 'lib/rtm/javatmapi/core/topic_map.rb', line 387 def get_topic_by_subject_locator(identifier) identifier = create_locator(identifier) if identifier.is_a?(String) return getTopicBySubjectLocator(identifier) if identifier.is_a?(Java::OrgTmapiCore::Locator) return identifier.map{|i| get_topic_by_subject_locator(i)} if identifier.is_a?(Array) return nil end |
#instances(type = :any) ⇒ Object
Returns all topics in the topic map that are used as instance in an “type-instance”-relationship.
The optional argument specifies the type the instances should have. Type may be a topic reference. This method equals topics(type).
The result may be empty.
:call-seq:
instances -> Array of Topics
instances(type) -> Array of Topics
258 259 260 261 262 |
# File 'lib/rtm/javatmapi/core/topic_map.rb', line 258 def instances(type = :any) return types.map{|t| t.instances.to_a}.flatten.uniq if type == :any type = self.get(type) unless type.is_a?(RTM::Topic) return type ? type_instance_index.getTopics(type).to_a : [] end |
#literal_index ⇒ Object Also known as: li
Calls TMAPI TopicMap.getIndex which returns the index for the LiteralIndex.
:call-seq:
literal_index -> LiteralIndex
226 227 228 229 230 231 |
# File 'lib/rtm/javatmapi/core/topic_map.rb', line 226 def literal_index # Equals _index(:LiteralIndex), which doesn't work yet index = getIndex(Java::OrgTmapiIndex::LiteralIndex.java_class) index.open unless index.is_open return index end |
#names ⇒ Object
Returns all names occurring in the topic map
553 554 555 |
# File 'lib/rtm/javatmapi/core/topic_map.rb', line 553 def names name_types.map{|type| type.typed_names.to_a}.flatten end |
#occurrences ⇒ Object
Returns all occurrences occurring in the topic map
558 559 560 |
# File 'lib/rtm/javatmapi/core/topic_map.rb', line 558 def occurrences occurrence_types.map{|type| type.typed_occurrences.to_a}.flatten end |
#parent ⇒ Object Also known as: reverse_children
Returns nil.
:call-seq:
parent -> nil
120 121 122 |
# File 'lib/rtm/javatmapi/core/topic_map.rb', line 120 def parent getParent end |
#roles ⇒ Object
Returns all roles occurring in the topic map
563 564 565 |
# File 'lib/rtm/javatmapi/core/topic_map.rb', line 563 def roles role_types.map{|type| type.typed_roles.to_a}.flatten end |
#scoped_index ⇒ Object Also known as: si
Calls TMAPI TopicMap.getIndex which returns the index for the ScopedIndex.
:call-seq:
scoped_index -> ScopedIndex
239 240 241 242 243 244 |
# File 'lib/rtm/javatmapi/core/topic_map.rb', line 239 def scoped_index # Equals _index(:ScopedIndex), which doesn't work yet index = getIndex(Java::OrgTmapiIndex::ScopedIndex.java_class) index.open unless index.is_open return index end |
#set_engine(engine) ⇒ Object
14 15 16 |
# File 'lib/rtm/javatmapi/core/topic_map.rb', line 14 def set_engine(engine) @engine = engine end |
#topics(type = :any) ⇒ Object Also known as: t
Returns all topics contained in this topic map.
The optional argument specifies the type of the topics should have, i.e. all instances of the specified type are returned. Type may be a topic reference. This method equals instances (type).
The return value may be empty.
:call_spec:
topics -> Set of Topics
topics(type) -> Array of Topics
307 308 309 310 |
# File 'lib/rtm/javatmapi/core/topic_map.rb', line 307 def topics(type = :any) return getTopics if type == :any return instances(type) end |
#type_instance_index ⇒ Object Also known as: tii
Calls TMAPI TopicMap.getIndex which returns the index for the TypeInstanceIndex.
:call-seq:
type_instance_index -> TypeInstanceIndex
213 214 215 216 217 218 |
# File 'lib/rtm/javatmapi/core/topic_map.rb', line 213 def type_instance_index # Equals _index(:TypeInstanceIndex), which doesn't work yet index = getIndex(Java::OrgTmapiIndex::TypeInstanceIndex.java_class) index.open unless index.is_open return index end |
#types ⇒ Object
Returns all topics in the topic map that are used as type in an “type-instance”-relationship.
:call-seq:
types -> Set of Topics
270 271 272 |
# File 'lib/rtm/javatmapi/core/topic_map.rb', line 270 def types type_instance_index.getTopicTypes end |
#variants ⇒ Object
Returns all variants occurring in the topic map
568 569 570 |
# File 'lib/rtm/javatmapi/core/topic_map.rb', line 568 def variants names.map{|name| name.variants.to_a}.flatten end |