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
|