# Copyright: Copyright 2009 Topic Maps Lab, University of Leipzig. # License: Apache License, Version 2.0 module RTM::Sugar module Topic # This module implements methods for Hash-like access in Topics. module HashAccess # Returns an Array of Names or Occurrences of # this Topic depending on the argument given. # # If argument is a Topic, an Array of Occurrences of this Topic which # have the specified type is returned. # # Argument may be a String. Then the structure should resemble "-type @scope" # or "type @scope". # # If argument starts with a "-", an Array of Names of this # Topic, which have the specified type (trailing the "-"), # is returned. # # If argument equals "-", Names that have the standard name type # are returned. # # If argument starts with a "*", both Names and Occurrences, which have the # specified type (trailing the "*") are returned as Array. # # If argument equals "*", all Names and Occurrences of this Topic are # returned. In this case this method equals the characteristics()-method. # # Else, if argument is a String, an Array of Occurrences # of this Topic, which have the specified type, # is returned. # # The argument may include an "@" after the type. # The String trailing the @ defines the # scope the selected Names and Occurrences should live in. Themes in the # scope may be c. # # Examples: # topic[occtype_topic] # topic["-"] # topic["*"] # topic["-nametype"] # topic["-nametype @scope] # topic["occtype @scope1, scope2"] # topic["*type"] # topic["*type @scope"] # # :call-seq: # [argument=Topic] -> Array of Occurrences # [argument=String] -> Array of Names and/or Occurrences # def [](identifier = :any) # return occurrences by type if topic is given return [] unless identifier return occurrences(identifier).to_a if (identifier.is_a?(RTM::Topic) || identifier == :any) prefix, type_reference, scope_reference = resolve_characteristic(identifier) if prefix == :name type_reference = RTM::PSI[:name_type] if type_reference == :any ret = names(type_reference).to_a elsif prefix == :occurrence raise "No occurrence type given" if type_reference == :any ret = occurrences(type_reference).to_a elsif prefix == :both ret = names(type_reference).to_a + occurrences(type_reference).to_a # type_reference == :any or not :any else end # we now have a list of names or occurrences, now we have to select for scope return ret if scope_reference == :any if scope_reference == :ucs ret.select{|i| i.scope.size == 0} else ret = ret.select{|i| scope_reference.all?{|sr| i.scope.include? getParent.get(sr)}} end ret end # Creates a Name or Occurrence of this Topic depending on the # argument given and returns this Name/Occurrence. # # Argument may be a String whose structure should resemble "-type @scope" # or "type @scope". # # If argument starts with a "-", a Name that has the specified type # (trailing the "-") is created. # # If argument equals "-", a Name that hase the standard name type # is created. # # Else, an Occurrence that has the specified type is created. # # The argument may include an "@" after the type. The String trailing # the @ defines the optional scope the Name or Occurrence # should live in. Themes in the scope may be comma- and/or space-separated. # # The value should be a String. # # Example: # topic[occtype]= "occvalue" # topic["-"]= "name" # topic["-nametype"]= "name" # topic["-nametype @scope]= "name" # topic["occtype @scope1, scope2"]= "occvalue" # # :call-seq: # [argument]= value # def []=(identifier, value) prefix, type_reference, scope_reference = resolve_characteristic(identifier) if prefix == :name nametype = (type_reference==:any) ? topic_map.get!(RTM::PSI[:name_type]) : type_reference scope_reference = scope_reference==:any ? [] : scope_reference raise("Value is not a String") unless value.is_a?(String) ret = create_name(nametype, value, scope_reference) elsif prefix == :occurrence raise "No occurrence type given" if type_reference == :any ret = create_occurrence(type_reference, value) else return nil end # return object without scope if any or ucs return ret if [:any, :ucs].include? scope_reference # set scope ret.add_scope(scope_reference) ret end private def resolve_characteristic(identifier) # spaces(-|*)?spaces(anything) prefix = :occurrence identifier =~ /^\s*(-|\*)?\s*(.+)?$/ # - or * and then everything else if $1 prefix = ($1 == "-") ? :name : :both end type, scope = resolve_type_and_scope($2) [prefix, type, scope] end def resolve_type_and_scope(ref) return [:any, :any] unless ref if ref[0] == ?@ type = :any scope = ref[1..-1] #cut "@" else type, scope = ref.split(' @', -1) # -1 -> trailing null fields are not suppressed if (type == nil) || (type.length == 0) type = :any else type.strip! #\s removed end end if scope scope = scope.strip.split(/\s*,?\s+/) #divided at \s,\s scope = :ucs if (scope == nil) || (scope.length == 0) else scope = :any end [type, scope] end end end end