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 159 160 161 162
|
require_relative "error"
# A segment or segment name plus an additional boolean attribute
#
# This class shall not be initialized directly.
# @api private
#
class RGFA::SegmentInfo < Array
# Check that the elements of the array are compatible with the definition.
#
# @!macro [new] segment_info_validation_errors
# @raise [RGFA::SegmentInfo::InvalidSizeError] if size is not 2
# @raise [RGFA::SegmentInfo::InvalidAttributeError] if second element
# is not a valid info
# @return [void]
def validate!
if size != 2
raise RGFA::SegmentInfo::InvalidSizeError,
"Wrong n of elements, 2 expected (#{inspect})"
end
if !self.class::ATTR.include?(self[1])
raise RGFA::SegmentInfo::InvalidAttributeError,
"Invalid attribute (#{self[1].inspect})"
end
return nil
end
# @return [Symbol, RGFA::Line::Segment] the segment instance or name
def segment
self[0]
end
# Set the segment
# @param value [Symbol, RGFA::Line::Segment] the segment instance or name
# @return Symbol, RGFA::Line::Segment] +value+
def segment=(value)
self[0]=value
end
# @return [Symbol] the segment name
def name
self[0].kind_of?(RGFA::Line::Segment) ? self[0].name : self[0].to_sym
end
# @return [Symbol] the attribute
def attribute
self[1]
end
# Set the attribute
# @param value [Symbol] the attribute
# @return [Symbol] +value+
def attribute=(value)
self[1]=(value)
end
# @return [Symbol] the other possible value of the attribute
def attribute_inverted
self.class::ATTR[self.class::ATTR[0] == self[1] ? 1 : 0]
end
# @return [RGFA::SegmentInfo] same segment, inverted attribute
def invert_attribute
self.class.new([self[0], self.attribute_inverted])
end
# @param [Symbol] attribute an attribute value
# @return [Symbol] the other attribute value
def self.invert(attribute)
i = self::ATTR.index(attribute.to_sym)
if i.nil?
raise RGFA::SegmentInfo::InvalidAttributeError,
"Invalid attribute (#{self[1].inspect})"
end
return self::ATTR[i-1]
end
# @return [String] name of the segment and attribute
def to_s
"#{name}#{attribute}"
end
# @return [Symbol] name of the segment and attribute
def to_sym
to_s.to_sym
end
# Compare the segment names and attributes of two instances
#
# @param [RGFA::SegmentInfo] other the other instance
# @return [Boolean]
def ==(other)
to_s == other.to_segment_info(self.class).to_s
end
# Compare the segment names and attributes of two instances
#
# @param [RGFA::SegmentInfo] other the other instance
# @return [Boolean]
def <=>(other)
to_s <=> other.to_segment_info(self.class).to_s
end
end
# Error raised if the size of the array is wrong
class RGFA::SegmentInfo::InvalidSizeError < RGFA::Error; end
# Error raised if an unknown value for attribute is used
class RGFA::SegmentInfo::InvalidAttributeError < RGFA::Error; end
# A representation of a segment end
class RGFA::SegmentEnd < RGFA::SegmentInfo
# Segment end type (begin or end)
ATTR = [ END_TYPE_BEGIN = :B, END_TYPE_END = :E ]
alias_method :end_type, :attribute
alias_method :end_type=, :attribute=
alias_method :invert_end_type, :invert_attribute
alias_method :end_type_inverted, :attribute_inverted
end
# A segment plus orientation
class RGFA::OrientedSegment < RGFA::SegmentInfo
# Segment orientation
ATTR = [ ORIENT_FWD = :+, ORIENT_REV = :- ]
alias_method :orient, :attribute
alias_method :orient=, :attribute=
alias_method :invert_orient, :invert_attribute
alias_method :orient_inverted, :attribute_inverted
end
class Array
# Create and validate a segment end from an array
# @!macro segment_info_validation_errors
# @return [RGFA::SegmentEnd]
def to_segment_end
to_segment_info(RGFA::SegmentEnd)
end
# Create and validate a segment end from an array
# @!macro segment_info_validation_errors
# @return [RGFA::OrientedSegment]
def to_oriented_segment
to_segment_info(RGFA::OrientedSegment)
end
protected
def to_segment_info(subclass)
return self if self.kind_of?(subclass)
# support converting from gfa gem GraphVertex objects:
if respond_to?(:segment) and respond_to?(:orient)
return RGFA::OrientedSegment.new([segment.to_sym, orient.to_sym])
end
se = subclass.new(map {|e| e.kind_of?(String) ? e.to_sym : e})
se.validate!
return se
end
end
|