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.ArrayList; 025import java.util.List; 026 027import org.biojava.bio.BioException; 028import org.biojava.bio.seq.db.IllegalIDException; 029import org.biojava.bio.symbol.Location; 030 031/** 032 * A feature that indicates that there is some remote feature that can't be 033 * represented entirely on a single Sequence. 034 * <p> 035 * These are the sort of features that represent things like the horible Embl 036 * remote feature spans (such as AL24199:100..200). The method getRemoteFeature 037 * should return a Feature on another Sequence that properly represents the 038 * Location. This Seqeunce will often be an Assembly of the parent Sequence to 039 * this Feature, and the Sequence associated with the remote Location sequence 040 * ID. Thse Features are also applicable to the case when a portion of a 041 * Sequence is projected but some Feature overlaps the boundary of the projected 042 * portion. 043 * 044 * @see org.biojavax.bio.seq.RichFeature 045 * @author Matthew Pocock 046 * @author Greg Cox 047 * @since 1.2 048 */ 049public interface RemoteFeature extends StrandedFeature { 050 /** 051 * Retrieve the list of Regions that locate this feature both localy and 052 * remotely. Local Regions have a null sequence ID. 053 * 054 * @return an immutable List of Regions 055 */ 056 List getRegions(); 057 058 /** 059 * Retrieve the Feature on some assembly Sequence that can represent this 060 * RemoteFeature properly. 061 * <p> 062 * This method should be equivalent to calling 063 * <code>getResolver().resolve(this)</code>. 064 * 065 * @return the Feature on another Sequence that this is projected onto 066 * @throws BioException if for any reason the remote Feature could not be 067 * constructed 068 */ 069 Feature getRemoteFeature() throws BioException; 070 071 Resolver getResolver(); 072 073 public class Template extends StrandedFeature.Template { 074 public List regions; 075 public Resolver resolver; 076 077 public Template() { 078 super(); 079 location = Location.empty; 080 regions = new ArrayList(); 081 resolver = null; 082 } 083 084 /** 085 * Creates a RemoteFeature.Template that has the same values as the 086 * template passed in. Fields that are in the template passed in but 087 * not in RemoteFeature Templates will be silently discarded. Regions is 088 * set to an empty list and the resolver is set to null. 089 * 090 * @param theTemplate the template for this template. 091 */ 092 public Template(Feature.Template theTemplate) { 093 location = theTemplate.location; 094 if (location == null) { 095 location = Location.empty; 096 } 097 type = theTemplate.type; 098 source = theTemplate.source; 099 annotation = theTemplate.annotation; 100 if (theTemplate instanceof StrandedFeature.Template) { 101 strand = ((StrandedFeature.Template) theTemplate).strand; 102 } else { 103 strand = StrandedFeature.UNKNOWN; 104 } 105 resolver = null; 106 regions = null; 107 } 108 109 } 110 111 /** 112 * The interface for objects that actually can take a RemoteFeature and 113 * return a Sequence object with the feature resolved into a real feature. 114 * <p> 115 * An implementation may choose to create a new Assembly from Sequences 116 * in a SequenceDB instance, or to return some existing larger Sequence that 117 * the sequence parent of the Feature is part of. This interface should ensure 118 * canonicalization of the returned Feature and the Sequence it resides on 119 * (using, for instance, SoftReferenceCacheMap keyed by a set of sequence 120 * IDs). 121 * 122 * @author Matthew Pocock 123 * @since 1.1 124 */ 125 public static interface Resolver { 126 /** 127 * Resolve rFeat. 128 * <p> 129 * This method returns a Feature that represents the RemoteFeature rFeat on 130 * some Sequence where all of the Regions can be represented localy. This 131 * may be an assembly of the parent sequence of rFeat and each of the 132 * Sequences that have IDs listed in the Region list of rFeat. 133 * 134 * @param rFeat the RemoteFeature to resolve 135 * @return a Feature on some other Seqence where each Region of rFeat is 136 * resolved into a local Location 137 */ 138 Feature resolve(RemoteFeature rFeat) throws IllegalIDException, BioException; 139 } 140 141 /** 142 * A tuple of Location and sequence ID. 143 * <p> 144 * For local locations, the Region is just a wrapper for a Location. For 145 * remote Regions, it also contains a String representing the Sequence ID of 146 * the remote Location. 147 * 148 * @author Matthew Pocock 149 * @since 1.1 150 */ 151 public final static class Region { 152 private final Location location; 153 private final String seqID; 154 private final boolean isRemote; 155 156 /** 157 * Create a new Region. 158 * 159 * @param location the Location of the Region 160 * @param seqID the ID of the Sequence containing the Location, or null if 161 * it is a local Region 162 */ 163 public Region(Location location, String seqID, boolean isRemote) { 164 this.location = location; 165 this.seqID = seqID; 166 this.isRemote = isRemote; 167 } 168 169 /** 170 * Retrieve the Location of the Region. 171 * 172 * @return the Location of this Region 173 */ 174 public Location getLocation() { 175 return location; 176 } 177 178 /** 179 * Return the remote Sequence ID if this Region is on another Sequence 180 * (isRemote will return true), null otherwise. 181 * 182 * @return the ID of the remote Sequence containing this Region 183 */ 184 public String getSeqID() { 185 return seqID; 186 } 187 188 /** 189 * Return whether this Region is remote or local. 190 * <p> 191 * If this returns true, getSeqID() will return the ID of the remote 192 * sequence. Otherwise, getSeqID() will return null. 193 * 194 * @return true if this is a remote Region, false otherwise 195 */ 196 public boolean isRemote() { 197 return isRemote; 198 } 199 } 200}