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.biojavax.bio.seq;
023
024import java.util.Set;
025import java.util.TreeSet;
026
027import org.biojava.bio.BioError;
028import org.biojava.bio.seq.Feature;
029import org.biojava.bio.seq.FeatureHolder;
030import org.biojava.bio.seq.SimpleFeatureHolder;
031import org.biojava.bio.seq.StrandedFeature;
032import org.biojava.ontology.InvalidTermException;
033import org.biojava.utils.ChangeType;
034import org.biojava.utils.ChangeVetoException;
035import org.biojavax.RankedCrossRefable;
036import org.biojavax.RichAnnotatable;
037import org.biojavax.SimpleRichAnnotation;
038
039/**
040 * Represents a feature that can be given name and rank and be
041 * moved from one sequence to another.
042 * @author Richard Holland
043 * @since 1.5
044 */
045public interface RichFeature extends StrandedFeature,RankedCrossRefable,RichAnnotatable,RichFeatureRelationshipHolder,Comparable {
046    
047    public static final ChangeType NAME = new ChangeType(
048            "This feature's name has changed",
049            "org.biojavax.bio.seq.RichFeature",
050            "NAME"
051            );
052    public static final ChangeType RANK = new ChangeType(
053            "This feature's rank has changed",
054            "org.biojavax.bio.seq.RichFeature",
055            "RANK"
056            );
057    public static final ChangeType SOURCETERM = new ChangeType(
058            "This feature's source term has changed",
059            "org.biojavax.bio.seq.RichFeature",
060            "SOURCETERM"
061            );
062    public static final ChangeType TYPETERM = new ChangeType(
063            "This feature's type term has changed",
064            "org.biojavax.bio.seq.RichFeature",
065            "TYPETERM"
066            );
067    public static final ChangeType LOCATION = new ChangeType(
068            "This feature's location has changed",
069            "org.biojavax.bio.seq.RichFeature",
070            "LOCATION"
071            );
072    public static final ChangeType PARENT = new ChangeType(
073            "This feature's parent has changed",
074            "org.biojavax.bio.seq.RichFeature",
075            "PARENT"
076            );
077    public static final ChangeType CROSSREF = new ChangeType(
078            "This feature's crossrefs have changed",
079            "org.biojavax.bio.seq.RichFeature",
080            "CROSSREF"
081            );
082    public static final ChangeType RELATION = new ChangeType(
083            "This feature's relations have changed",
084            "org.biojavax.bio.seq.RichFeature",
085            "RELATION"
086            );
087    
088    /**
089     * Sets the parent of this feature.
090     * @param parent the parent the feature should identify itself with.
091     * @throws ChangeVetoException if the new value is unacceptable.
092     */
093    public void setParent(FeatureHolder parent) throws ChangeVetoException;
094    
095    /**
096     * Returns the name of this feature.
097     * @return the name.
098     */
099    public String getName();
100    
101    /**
102     * Sets the name of this feature.
103     * @param name the name the feature should identify itself with.
104     * @throws ChangeVetoException if the new value is unacceptable.
105     */
106    public void setName(String name) throws ChangeVetoException;
107    
108    /**
109     * Returns the rank of this feature.
110     * @return the rank.
111     */
112    public int getRank();
113    
114    /**
115     * Sets the rank of this feature.
116     * @param rank the rank the feature should identify itself with.
117     * @throws ChangeVetoException if the new value is unacceptable.
118     */
119    public void setRank(int rank) throws ChangeVetoException;
120    
121    /**
122     * Added-value extension of Feature.Template including bits we're 
123     * interested in, eg. featureRelationshipSet for relationships with
124     * other features, and rankedCrossRefs for lookups into other databases.
125     */
126    public static class Template extends Feature.Template {
127        public Set featureRelationshipSet;
128        public Set rankedCrossRefs;
129    }
130    
131    /**
132     * Some useful tools for working with features.
133     */
134    public static class Tools {
135        
136        // because it is a static class we don't want instances of it
137        private Tools() {}
138        
139        /**
140         * Takes a normal Feature and attempts to convert it into a RichFeature.
141         * @param f the Feature to enrich.
142         * @return the RichFeature equivalent.
143         * @throws ChangeVetoException if any of the terms from the feature were
144         * not convertible.
145         */
146        public static RichFeature enrich(Feature f) throws ChangeVetoException {
147            try {
148                if (f instanceof RichFeature) return (RichFeature)f;
149                else return new SimpleRichFeature(f.getParent(),f.makeTemplate());
150            } catch (InvalidTermException e) {
151                throw new ChangeVetoException("Unable to convert one of the feature's terms",e);
152            }
153        }
154        
155        /**
156         * A way to make a dummy feature
157         */
158        public static RichFeature makeEmptyFeature(){            
159            RichFeature.Template templ = new RichFeature.Template();
160            templ.annotation = new SimpleRichAnnotation();
161            templ.featureRelationshipSet = new TreeSet();
162            templ.rankedCrossRefs = new TreeSet();
163            templ.type = "none";
164            templ.source = "none";
165            templ.location = RichLocation.full;
166            try{
167                return new SimpleRichFeature(new SimpleFeatureHolder(),templ);
168            }catch(Exception ex){
169                throw new BioError(ex);
170            }//can't happen            
171        }
172    }
173}
174