File: lines.rb

package info (click to toggle)
ruby-rgfa 1.3.1%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 824 kB
  • sloc: ruby: 5,649; makefile: 9
file content (158 lines) | stat: -rw-r--r-- 4,543 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
require_relative "error"

#
# Methods for the RGFA class, which allow to handle lines of multiple types.
#
module RGFA::Lines

  # Add a line to a RGFA
  #
  # @overload <<(gfa_line_string)
  #   @param [String] gfa_line_string representation of a RGFA line
  # @overload <<(gfa_line)
  #   @param [RGFA::Line] gfa_line instance of a subclass of RGFA::Line
  # @raise [RGFA::DuplicatedLabelError] if multiple segment or path lines
  #   with the same name are added
  # @return [RGFA] self
  def <<(gfa_line)
    gfa_line = gfa_line.to_rgfa_line(validate: @validate)
    rt = gfa_line.record_type
    case rt
    when :H
      add_header(gfa_line)
    when :S
      add_segment(gfa_line)
    when :L
      add_link(gfa_line)
    when :C
      add_containment(gfa_line)
    when :P
      add_path(gfa_line)
    when :"#"
      # do nothing, as the spec says these shall be ignored
      # maybe we want to store them and output them again in a future version
    else
      raise # this never happens, as already catched by gfa_line init
    end
    return self
  end

  # Delete elements from the RGFA graph
  # @overload rm(segment)
  #   @param segment [String, RGFA::Line::Segment] segment name or instance
  # @overload rm(path)
  #   @param path [String, RGFA::Line::Segment] path name or instance
  # @overload rm(link)
  #   @param link [RGFA::Line::Link] link
  # @overload rm(containment)
  #   @param link [RGFA::Line::Containment] containment
  # @overload rm(:headers)
  #   Remove all headers
  # @overload rm(array)
  #   Calls {#rm} using each element of the array as argument
  #   @param array [Array]
  # @overload rm(method_name, *args)
  #   Call a method of RGFA instance, then {#rm} for each returned value
  #   @param method_name [Symbol] method to call
  #   @param args arguments of the method
  # @return [RGFA] self
  def rm(x, *args)
    if x.kind_of?(RGFA::Line)
      raise ArgumentError,
        "One argument required if first RGFA::Line" if !args.empty?
      case x.record_type
      when :H then raise ArgumentError, "Cannot remove single header lines"
      when :S then delete_segment(x)
      when :P then delete_path(x)
      when :L then delete_link(x)
      when :C then delete_containment(x)
      end
    elsif x.kind_of?(Symbol)
      if @segments.has_key?(x)
        if !args.empty?
          raise ArgumentError, "One arguments required if first segment name"
        end
        delete_segment(x)
      elsif @paths.has_key?(x)
        if !args.empty?
          raise ArgumentError, "One argument required if first path name"
        end
        delete_path(x)
      elsif x == :headers
        if !args.empty?
          raise ArgumentError, "One argument required if first :headers"
        end
        delete_headers
      else
        if respond_to?(x)
          rm(send(x, *args))
        else
          raise ArgumentError, "Cannot remove #{x.inspect}"
        end
      end
    elsif x.kind_of?(String)
      rm(x.to_sym, *args)
    elsif x.kind_of?(Array)
      x.each {|elem| rm(elem, *args)}
    elsif x.nil?
      return self
    else
      raise ArgumentError, "Cannot remove #{x.inspect}"
    end
    return self
  end

  # Rename a segment or a path
  #
  # @param old_name [String] the name of the segment or path to rename
  # @param new_name [String] the new name for the segment or path
  #
  # @raise[RGFA::DuplicatedLabelError]
  #   if +new_name+ is already a segment or path name
  # @return [RGFA] self
  def rename(old_name, new_name)
    old_name = old_name.to_sym
    new_name = new_name.to_sym
    s = segment(old_name)
    pt = nil
    if s.nil?
      pt = path(old_name)
      if pt.nil?
        raise RGFA::LineMissingError,
          "#{old_name} is not a path or segment name"
      end
    end
    if segment(new_name) or path(new_name)
      raise RGFA::DuplicatedLabelError,
        "#{new_name} is already a path or segment name"
    end
    if s
      s.name = new_name
      @segments.delete(old_name)
      @segments[new_name] = s
    else
      pt.path_name = new_name
      @paths.delete(old_name)
      @paths[new_name] = pt
    end
    self
  end

  private

  def lines
    headers + segments + links + containments + paths
  end

  def each_line(&block)
    lines.each(&block)
  end

end

# Exception raised if a label for segment or path is duplicated
class RGFA::DuplicatedLabelError < RGFA::Error; end

# The error raised by banged line finders if no line respecting the criteria
# exist in the RGFA
class RGFA::LineMissingError < RGFA::Error; end