github.com/Schaudge/hts@v0.0.0-20240223063651-737b4d69d68c/sam/program.go (about) 1 // Copyright ©2012 The bíogo Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package sam 6 7 import ( 8 "bytes" 9 "errors" 10 "fmt" 11 ) 12 13 // Program represents a SAM program. 14 type Program struct { 15 owner *Header 16 id int32 17 uid string 18 previous string 19 name string 20 command string 21 version string 22 otherTags []tagPair 23 } 24 25 // NewProgram returns a Program with the given unique ID, name, command, 26 // previous program ID in the pipeline and version. 27 func NewProgram(uid, name, command, prev, v string) *Program { 28 return &Program{ 29 id: -1, 30 uid: uid, 31 previous: prev, 32 name: name, 33 command: command, 34 version: v, 35 } 36 } 37 38 // ID returns the header ID for the Program. 39 func (p *Program) ID() int { 40 if p == nil { 41 return -1 42 } 43 return int(p.id) 44 } 45 46 // UID returns the unique program ID for the program. 47 func (p *Program) UID() string { 48 if p == nil { 49 return "" 50 } 51 return p.uid 52 } 53 54 // SetUID sets the unique program ID to uid. 55 func (r *Program) SetUID(uid string) error { 56 if r.owner != nil { 57 id, exists := r.owner.seenProgs[uid] 58 if exists { 59 if id != r.id { 60 return errors.New("sam: uid exists") 61 } 62 return nil 63 } 64 delete(r.owner.seenProgs, r.uid) 65 r.owner.seenProgs[uid] = r.id 66 } 67 r.uid = uid 68 return nil 69 } 70 71 // Name returns the program's name. 72 func (p *Program) Name() string { 73 if p == nil { 74 return "" 75 } 76 return p.name 77 } 78 79 // Command returns the program's command line. 80 func (p *Program) Command() string { 81 if p == nil { 82 return "" 83 } 84 return p.command 85 } 86 87 // Previous returns the unique ID for the previous program in the pipeline. 88 func (p *Program) Previous() string { 89 if p == nil { 90 return "" 91 } 92 return p.previous 93 } 94 95 // Version returns the version of the program. 96 func (p *Program) Version() string { 97 if p == nil { 98 return "" 99 } 100 return p.version 101 } 102 103 // Clone returns a deep copy of the Program. 104 func (p *Program) Clone() *Program { 105 if p == nil { 106 return nil 107 } 108 cp := *p 109 if len(cp.otherTags) != 0 { 110 cp.otherTags = make([]tagPair, len(cp.otherTags)) 111 } 112 copy(cp.otherTags, p.otherTags) 113 cp.id = -1 114 cp.owner = nil 115 return &cp 116 } 117 118 // Tags applies the function fn to each of the tag-value pairs of the Program. 119 // The function fn must not add or delete tags held by the receiver during 120 // iteration. 121 func (p *Program) Tags(fn func(t Tag, value string)) { 122 if fn == nil { 123 return 124 } 125 fn(idTag, p.UID()) 126 if p.name != "" { 127 fn(programNameTag, p.name) 128 } 129 if p.command != "" { 130 fn(commandLineTag, p.command) 131 } 132 if p.previous != "" { 133 fn(previousProgTag, p.previous) 134 } 135 if p.version != "" { 136 fn(versionTag, p.version) 137 } 138 for _, tp := range p.otherTags { 139 fn(tp.tag, tp.value) 140 } 141 } 142 143 // Get returns the string representation of the value associated with the 144 // given program line tag. If the tag is not present the empty string is returned. 145 func (p *Program) Get(t Tag) string { 146 switch t { 147 case idTag: 148 return p.UID() 149 case programNameTag: 150 return p.Name() 151 case commandLineTag: 152 return p.Command() 153 case previousProgTag: 154 return p.Previous() 155 case versionTag: 156 return p.Version() 157 } 158 for _, tp := range p.otherTags { 159 if t == tp.tag { 160 return tp.value 161 } 162 } 163 return "" 164 } 165 166 // Set sets the value associated with the given program line tag to the specified 167 // value. If value is the empty string and the tag may be absent, it is deleted. 168 func (p *Program) Set(t Tag, value string) error { 169 switch t { 170 case idTag: 171 if value == "" { 172 return errDupProgram 173 } 174 case programNameTag: 175 p.name = value 176 case commandLineTag: 177 p.command = value 178 case previousProgTag: 179 p.previous = value 180 case versionTag: 181 p.version = value 182 default: 183 if value == "" { 184 for i, tp := range p.otherTags { 185 if t == tp.tag { 186 copy(p.otherTags[i:], p.otherTags[i+1:]) 187 p.otherTags = p.otherTags[:len(p.otherTags)-1] 188 return nil 189 } 190 } 191 } else { 192 for i, tp := range p.otherTags { 193 if t == tp.tag { 194 p.otherTags[i].value = value 195 return nil 196 } 197 } 198 p.otherTags = append(p.otherTags, tagPair{tag: t, value: value}) 199 } 200 } 201 return nil 202 } 203 204 // String returns a string representation of the program according to the 205 // SAM specification section 1.3, 206 func (p *Program) String() string { 207 var buf bytes.Buffer 208 fmt.Fprintf(&buf, "@PG\tID:%s", p.uid) 209 if p.name != "" { 210 fmt.Fprintf(&buf, "\tPN:%s", p.name) 211 } 212 if p.command != "" { 213 fmt.Fprintf(&buf, "\tCL:%s", p.command) 214 } 215 if p.previous != "" { 216 fmt.Fprintf(&buf, "\tPP:%s", p.previous) 217 } 218 if p.version != "" { 219 fmt.Fprintf(&buf, "\tVN:%s", p.version) 220 } 221 for _, tp := range p.otherTags { 222 fmt.Fprintf(&buf, "\t%s:%s", tp.tag, tp.value) 223 } 224 return buf.String() 225 }