class TraceableSet

this class represents a set of traceables

Public Class Methods

load_from_marshal(file) click to toggle source

this loads cached information into a particular slot @param file [String] name of the cachefile

# File lib/wortsammler/class.Traceable.rb, line 210
def self.load_from_marshal(file)
  a = nil
  File.open(file, "rb") { |f| a = Marshal.load(f) }
  a
end
new() click to toggle source

Initialize the traceable set

@return [type] [description]

# File lib/wortsammler/class.Traceable.rb, line 24
def initialize()
  # the traces
  @traces = {}

  # the list of supporters
  # supporters for foo 0 @@supported_by["foo"]
  @supported_by = {}


  # define the sort order policy
  # it is the same for all slots
  @sortOrder = []

end
processTracesInMdFile(mdFile) click to toggle source

@return [TraceableSet] The set of traceables found in the markdown file

# File lib/wortsammler/class.Traceable.md.rb, line 70
def self.processTracesInMdFile(mdFile)

  parser=TraceInMarkdownParser.new
  parser.consume_all_input = true

  raw_md_code_file=File.open(mdFile, "r:bom|utf-8")
  raw_md_code = raw_md_code_file.readlines.join
  raw_md_code_file.close
  #       print mdFile
  result = parser.parse(raw_md_code)
  #       print " ... parsed\n" todo: use logger here

  result_set = TraceableSet.new

  if result
    result.descendant.select{|x| x.getLabel==="trace"}.each{|c|
      id       = c.traceId.payload.text_value
      uptraces = c.uptraces.payload.text_value
      header   = c.traceHead.payload.text_value
      bodytext = c.traceBody.payload.text_value
      uptraces = c.uptraces.payload.text_value
      # Populate the Traceable entry
      theTrace = Traceable.new
      theTrace.info           = mdFile
      theTrace.id             = id
      theTrace.header_orig    = header
      theTrace.body_orig      = bodytext
      theTrace.trace_orig     = c.text_value
      theTrace.contributes_to = uptraces.gsub!(/\s*/, "").split(",")
      theTrace.category       = :SPECIFICATION_ITEM
      result_set.add(theTrace)
    }
    #            puts " .... finished"
  else
    puts ["","-----------", texFile, parser.failure_reason].join("\n")
  end
  result_set
end

Public Instance Methods

[](id) click to toggle source

this returns a particular trace in case of duplicates, it delivers the first one @param id [String] the id of the requested traceable

# File lib/wortsammler/class.Traceable.rb, line 179
def [] (id)
  if @traces.has_key?(id)
    @traces[id].first
  else
    nil
  end
end
add(traceable) click to toggle source
add add a traceable to the Traceable set

@param traceable [Traceable] The traceable which shall be added

* first
* second

@return [type] [description]

# File lib/wortsammler/class.Traceable.rb, line 48
def add(traceable)
  #TOOD: check traceable
  #TODO: check if append can be optimized

  @traces[traceable.id] = [@traces[traceable.id], traceable].flatten.compact

  traceable.contributes_to.each do |t|
    @supported_by[t] = [@supported_by[t], traceable.id].flatten.compact
  end
end
added_trace_ids(reference_set, category = nil) click to toggle source

expose added traceables found as a result of comparing two TraceableSets @param reference_set [TraceableSet] The set of traceables used as reference @param category [Symbol] Restrict the comparison to a particlar category

@return [Array] the ids of the added traces (list of trace_id which are not in @referece_set)

# File lib/wortsammler/class.Traceable.rb, line 66
def added_trace_ids(reference_set, category = nil)
  self.all_trace_ids(category) - reference_set.all_trace_ids(category)
end
all_trace_ids(selected_category = nil) click to toggle source

this delivers an array ids of all Traceables @param [Symbol] selected_category the category of the deisred Traceables

if nil is given, then all Traceables are returned

@return [Array of String] an array of the registered Traceables

of the selectedCategory
# File lib/wortsammler/class.Traceable.rb, line 148
def all_trace_ids(selected_category = nil)
  @traces.keys.select { |x|
    y = @traces[x].first
    selected_category.nil? or y.category == selected_category
  }.sort
end
all_traces(selected_category = nil) click to toggle source

return an array of all traces of a given category @param selected_category [Symbol] the category of traceables to return

@return [Array of Traceable] The array of traceables

# File lib/wortsammler/class.Traceable.rb, line 163
def all_traces(selected_category = nil)
  all_trace_ids(selected_category).map { |t| @traces[t].first }
end
all_traces_as_arrays() click to toggle source

return an array of all traces

@return [Array of Traceable] array of all traces

# File lib/wortsammler/class.Traceable.rb, line 172
def all_traces_as_arrays
  @traces
end
changed_trace_ids(reference_set, category = nil) click to toggle source

expose changed traceables @param reference_set [TraceableSet] the set of traceables used as reference @param category [Symbol] Restrict the operation to traceables of this category.

@return [Array] List of trace_id which changed not in reference_set

# File lib/wortsammler/class.Traceable.rb, line 77
def changed_trace_ids(reference_set, category = nil)
  candidates = self.all_trace_ids(category) & reference_set.all_trace_ids(category)
  candidates.map { |candidate|
    self[candidate].get_diff(reference_set[candidate])
  }.compact
end
deleted_trace_ids(reference_set, category = nil) click to toggle source

expose deleted traceables @param reference_set [TraceableSet] the set of traceables used as reference @param category [Symbol] Restrict the operation to traceables of this category.

@return [Array] List of trace_id which are deleted (not in current set)

# File lib/wortsammler/class.Traceable.rb, line 104
def deleted_trace_ids(reference_set, category = nil)
  reference_set.all_trace_ids(category) - self.all_trace_ids(category)
end
dump_to_marshal(file) click to toggle source

this serializes a particular slot for caching @param file [String] name of the cachefile

# File lib/wortsammler/class.Traceable.rb, line 202
def dump_to_marshal(file)
  File.open(file, "wb") { |f|
    Marshal.dump(self, f)
  }
end
duplicate_ids() click to toggle source

this lists duplicate traces @return [Array of String] the list of the id of duplicate Traces

# File lib/wortsammler/class.Traceable.rb, line 189
def duplicate_ids()
  @traces.select { |id, traceables| traceables.length > 1 }.map { |id, traceable| id }.sort
end
duplicate_traces() click to toggle source

this lists duplicate traces @return [Array of Traceable] the list duplicate Traces.

# File lib/wortsammler/class.Traceable.rb, line 195
def duplicate_traces()
  @traces.select { |id, traceables| traceables.length > 1 }.map { |id, traceable| traceable }.sort
end
merge(set) click to toggle source

this merges a TraceableSet @return [Treaceable] the current traceable set

# File lib/wortsammler/class.Traceable.rb, line 218
def merge(set)
  set.all_traces_as_arrays.values.flatten.each { |t| self.add(t) }
end
reqtraceSynopsis(selectedCategory) click to toggle source

this generates a synopsis of traces in markdown Format @param [Symbol] selectedCategory the the category of the Traceables

which shall be reported.
# File lib/wortsammler/class.Traceable.md.rb, line 24
def reqtraceSynopsis(selectedCategory)
  all_traces(selectedCategory).
    sort_by{|x| trace_order_index(x.id) }.
  map{|t|
    tidm=t.id.gsub("_","-")

    lContributes = t.contributes_to.
        map { |c| mk_hyperlink(c) }

    luptraces = [uptrace_ids[t.id]].flatten.compact.map{|x| self[x]}

    luptraces=luptraces.
    sort_by{|x| trace_order_index(x.id)}.
    map{|u|
      "    - #{mk_hyperlink(u.id)} #{u.header_orig}"
    }

    ["- #{mk_hyperlink(t.id)} <!-- --> <a id=\"RT-#{tidm}\"/>**#{t.header_orig}**" +
     #                     "  (#{t.contributes_to.join(', ')})", "",
     "  (#{lContributes.join(', ')})", "",
     luptraces
     ].flatten.join("\n")
  }.join("\n\n")
end
sort_order=(sort_order) click to toggle source

this adjusts the sortOrder @param sort_order [Array of String ] is an array of strings if a traceId starts with such a string it is placed according to the sequence in the array. Otherwise it is sorted at the end

# File lib/wortsammler/class.Traceable.rb, line 245
def sort_order= (sort_order)
  @sort_order = sort_order
end
to_compareEntries() click to toggle source

return a string all traces sorted which can be saved as a file and subsequently be used by a textual diff to determine changed traces.

@return [type] [description]

# File lib/wortsammler/class.Traceable.rb, line 274
def to_compareEntries
  all_traces.sort.map { |t| "\n\n[#{t.id}]\n#{t.as_oneline}" }.join("\n")
end
to_downstream_tracefile(selectedCategory) click to toggle source

this generates the downstream_tracefile

# File lib/wortsammler/class.Traceable.md.rb, line 51
def to_downstream_tracefile(selectedCategory)
  all_traces(selectedCategory).
    sort_by{|x| trace_order_index(x.id) }.
  map{|t|
    "\n\n\\[#{t.id}\\] **#{t.header_orig}** { }()"
  }.join("\n\n")
end
to_graphml() click to toggle source

export the trace as graphml for yed @return - the requirements tree in graphml

# File lib/wortsammler/class.Traceable.rb, line 111
def to_graphml
  f   = File.open("#{File.dirname(__FILE__)}/../../resources/requirementsSynopsis.graphml")
  doc = Nokogiri::XML(f)
  f.close

  graph = doc.xpath("//xmlns:graph").first

  # generate all nodes
  self.all_traces(nil).each { |theTrace|
    n_node              = Nokogiri::XML::Node.new "node", doc
    n_node["id"]        = theTrace.id
    n_data              = Nokogiri::XML::Node.new "data", doc
    n_data["key"]       = "d6"
    n_ShapeNode         = Nokogiri::XML::Node.new "y:ShapeNode", doc
    n_NodeLabel         = Nokogiri::XML::Node.new "y:NodeLabel", doc
    n_NodeLabel.content = "[#{theTrace.id}] #{theTrace.header_orig}"
    n_ShapeNode << n_NodeLabel
    n_data << n_ShapeNode
    n_node << n_data
    graph << n_node

    theTrace.contributes_to.each { |up|
      n_edge           = Nokogiri::XML::Node.new "edge", doc
      n_edge["source"] = theTrace.id
      n_edge["target"] = up
      n_edge["id"]     = "#{up}_#{theTrace.id}"
      graph << n_edge
    }
  }
  xp(doc).to_xml
end
trace_order_index(trace_id) click to toggle source

this determines the sort order index of a trace required behavior needs to be set in advance by the method sortOrder= @param trace_id [String] the id of a Traceable for which

the sort order index shall be coumputed.

@return [String] the sort key of the given id.

# File lib/wortsammler/class.Traceable.rb, line 254
def trace_order_index(trace_id)
  global = @sort_order.index { |x| trace_id.start_with? x } ||
      (@sort_order.length + 1)

  # add the {index} of the trace to
  orderId = [global.to_s.rjust(5, "0"), trace_id].join("_")
  orderId
end
unchanged_trace_ids(reference_set, category = nil) click to toggle source

expose unchanged traceables @param reference_set [TraceableSet] the set of traceables used as reference @param category [Symbol] Restrict the operation to traceables of this category.

@return [Array] List of trace_id which unchanged

# File lib/wortsammler/class.Traceable.rb, line 90
def unchanged_trace_ids(reference_set, category = nil)
  candidates = self.all_trace_ids(category) & reference_set.all_trace_ids(category)
  candidates.select { |candidate|
    self[candidate].get_diff(reference_set[candidate]).nil?
  }.compact
end
undefined_ids() click to toggle source

this retunrs traces marked as supported but not being defined @return [Array of String] the list of the id of undefined Traces

traces which are marked as uptraces but do not exist.
# File lib/wortsammler/class.Traceable.rb, line 225
def undefined_ids
  @supported_by.keys.select { |t| not @traces.has_key?(t) }.sort
end
uptrace_ids() click to toggle source

returns the list of all uptraces in the current TraceableSet. Note that this is a hash of strings.

myset.uptrace_ids[rs_foo_001]  # yield id of traces referring to rs_foo_001

@return [Hash of Array of String] the Hash of the uptrace ids.

# File lib/wortsammler/class.Traceable.rb, line 236
def uptrace_ids
  @supported_by
end

Private Instance Methods

xp(doc) click to toggle source

this is used to beautify an nokigiri document @param [Nokogiri::XML::Document] doc - the document @return [Nokogiri::XML::Document] the beautified document

# File lib/wortsammler/class.Traceable.rb, line 287
  def xp(doc)
    xsl = <<-XSL
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" encoding="UTF-8" indent="yes"/>
    <xsl:strip-space elements="*"/>
    <xsl:template match="/">
    <xsl:copy-of select="."/>
    </xsl:template>
    </xsl:stylesheet>
    XSL


    xslt = Nokogiri::XSLT(xsl)
    out  = xslt.transform(doc)

    out
  end