001/* 002 * BioJava development code 003 * 004 * This code may be freely distributed and modified under the 005 * terms of the GNU Lesser General Public Licence. This should 006 * be distributed with the code. If you do not have a copy, 007 * see: 008 * 009 * http://www.gnu.org/copyleft/lesser.html 010 * 011 * Copyright for this code is held jointly by the individual 012 * authors. These should be listed in @author doc comments. 013 * 014 * For more information on the BioJava project and its aims, 015 * or to join the biojava-l mailing list, visit the home page 016 * at: 017 * 018 * http://www.biojava.org/ 019 * 020 */ 021 022package org.biojava.bio.seq; 023 024import java.util.Iterator; 025import java.util.List; 026 027import org.biojava.bio.Annotatable; 028import org.biojava.bio.Annotation; 029import org.biojava.bio.BioError; 030import org.biojava.bio.BioException; 031import org.biojava.bio.SimpleAnnotation; 032import org.biojava.bio.seq.impl.AssembledSymbolList; 033import org.biojava.bio.symbol.Alphabet; 034import org.biojava.bio.symbol.Edit; 035import org.biojava.bio.symbol.IllegalAlphabetException; 036import org.biojava.bio.symbol.Location; 037import org.biojava.bio.symbol.Symbol; 038import org.biojava.bio.symbol.SymbolList; 039import org.biojava.utils.AbstractChangeable; 040import org.biojava.utils.ChangeForwarder; 041import org.biojava.utils.ChangeSupport; 042import org.biojava.utils.ChangeType; 043import org.biojava.utils.ChangeVetoException; 044 045/** 046 * A Sequence which is assembled from other sequences contained 047 * in a set of ComponentFeature objects. 048 * 049 * <p> 050 * There is still some potential for optimising SymbolList 051 * operations on this class. 052 * </p> 053 * 054 * @author Thomas Down 055 * @author Matthew Pocock 056 * @since 1.1 057 */ 058 059public class SimpleAssembly 060 extends 061 AbstractChangeable 062 implements 063 Sequence, 064 RealizingFeatureHolder 065{ 066 private final String name; 067 private final String uri; 068 private final Annotation annotation = new SimpleAnnotation(); 069 private final SimpleFeatureHolder features; 070 private final AssembledSymbolList assembly; 071 072 private final FeatureRealizer featureRealizer = org.biojava.bio.seq.impl.FeatureImpl.DEFAULT; 073 074 protected transient ChangeForwarder annotationForwarder; 075 076 { 077 assembly = new AssembledSymbolList(); 078 features = new SimpleFeatureHolder(); 079 } 080 081 /** 082 * Construct a new SimpleAssembly using the DNA alphabet. 083 * Initially, the sequence will just contain a list of `N's. 084 * Sequence data can be added by adding one or more 085 * ComponentFeatures. 086 * 087 * @param length The length of the sequence 088 * @param name The name of the sequence (returned by getName()) 089 * @param uri The identifier of the sequence (returned by getURN()); 090 */ 091 092 public SimpleAssembly(int length, String name, String uri) { 093 this.name = name; 094 this.uri = uri; 095 assembly.setLength(length); 096 } 097 098 /** 099 * Construct a new SimpleAssembly using the DNA alphabet. 100 * Initially, the sequence will just contain a list of `N's. 101 * Sequence data can be added by adding one or more 102 * ComponentFeatures. 103 * 104 * @param name The name of the sequence (returned by getName()) 105 * @param uri The identifier of the sequence (returned by getURN()); 106 */ 107 108 public SimpleAssembly(String name, String uri) { 109 this.name = name; 110 this.uri = uri; 111 } 112 113 // 114 // SymbolList 115 // 116 117 public Alphabet getAlphabet() { 118 return assembly.getAlphabet(); 119 } 120 121 public int length() { 122 return assembly.length(); 123 } 124 125 public Symbol symbolAt(int pos) { 126 return assembly.symbolAt(pos); 127 } 128 129 public SymbolList subList(int start, int end) { 130 return assembly.subList(start, end); 131 } 132 133 public String seqString() { 134 return assembly.seqString(); 135 } 136 137 public String subStr(int start, int end) { 138 return assembly.subStr(start, end); 139 } 140 141 public Iterator iterator() { 142 return assembly.iterator(); 143 } 144 145 public List toList() { 146 return assembly.toList(); 147 } 148 149 public void edit(Edit e) 150 throws IllegalAlphabetException, ChangeVetoException 151 { 152 assembly.edit(e); 153 } 154 155 // 156 // Sequence identification 157 // 158 159 public String getName() { 160 return name; 161 } 162 163 public String getURN() { 164 return uri; 165 } 166 167 // 168 // Annotatable 169 // 170 171 public Annotation getAnnotation() { 172 return annotation; 173 } 174 175 // 176 // FeatureHolder 177 // 178 179 public Iterator features() { 180 return features.features(); 181 } 182 183 public int countFeatures() { 184 return features.countFeatures(); 185 } 186 187 public FeatureHolder filter(FeatureFilter ff, boolean recurse) { 188 return features.filter(ff, recurse); 189 } 190 191 public FeatureHolder filter(FeatureFilter ff) { 192 return features.filter(ff); 193 } 194 195 public boolean containsFeature(Feature f) { 196 return features.containsFeature(f); 197 } 198 199 public Feature createFeature(Feature.Template temp) 200 throws BioException, ChangeVetoException 201 { 202 if (temp.location.getMin() < 1) 203 throw new BioException("Coordinates out of range"); 204 205 if (temp instanceof ComponentFeature.Template) { 206 for (Iterator i = assembly.getComponentLocationSet().iterator(); i.hasNext(); ) { 207 Location l = (Location) i.next(); 208 if (l.overlaps(temp.location)) 209 throw new BioError("Can't create overlapping ComponentFeature"); 210 } 211 } 212 213 Feature f = realizeFeature(this, temp); 214 features.addFeature(f); 215 if (f instanceof ComponentFeature) { 216 ComponentFeature cf = (ComponentFeature) f; 217 Location loc = cf.getLocation(); 218 if (loc.getMax() > assembly.length()) { 219 assembly.setLength(loc.getMax()); 220 } 221 assembly.putComponent(cf); 222 } 223 return f; 224 } 225 226 public void removeFeature(Feature f) 227 throws ChangeVetoException { 228 if (f instanceof ComponentFeature) { 229 assembly.removeComponent(f.getLocation()); 230 } 231 features.removeFeature(f); 232 } 233 234 // 235 // Feature realization 236 // 237 238 public Feature realizeFeature(FeatureHolder fh, Feature.Template temp) 239 throws BioException { 240 if (temp instanceof ComponentFeature.Template) { 241 if (fh != this) { 242 throw new BioException("ComponentFeatures can only be attached directly to SimpleAssembly objects"); 243 } 244 ComponentFeature.Template cft = (ComponentFeature.Template) temp; 245 return new SimpleComponentFeature(this, cft); 246 } else { 247 FeatureHolder gopher = fh; 248 while (gopher instanceof Feature) { 249 if (gopher instanceof ComponentFeature) { 250 // fixme: this should delegate onto the ComponentFeature, which 251 // should in turn delegate to its ProjectedFeatureHolder and let 252 // the projection magic sort this out 253 throw new BioException("Cannot [currently] realize features on components of SimpleAssemblies"); 254 } 255 gopher = ((Feature) gopher).getParent(); 256 } 257 return featureRealizer.realizeFeature(this, fh, temp); 258 } 259 } 260 261 protected ChangeSupport getChangeSupport(ChangeType ct){ 262 ChangeSupport cs = super.getChangeSupport(ct); 263 264 if(annotationForwarder == null && 265 (ct == null || ct == Annotatable.ANNOTATION)){ 266 annotationForwarder = 267 new ChangeForwarder.Retyper(this, cs, Annotation.PROPERTY); 268 getAnnotation().addChangeListener( 269 annotationForwarder, 270 Annotatable.ANNOTATION); 271 } 272 return cs; 273 } 274 275 public FeatureFilter getSchema() { 276 return FeatureFilter.top_level; 277 } 278}