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.Collections;
025import java.util.Iterator;
026
027import org.biojava.bio.BioException;
028import org.biojava.utils.ChangeType;
029import org.biojava.utils.ChangeVetoException;
030import org.biojava.utils.Changeable;
031import org.biojava.utils.Unchangeable;
032
033/**
034 * The interface for objects that contain features.
035 * <p>
036 * Feature holders abstract the containment of a feature from the objects
037 * that implements both the real container or the features. FeatureHolders are
038 * like sets of features.
039 * </p>
040 * @see org.biojavax.bio.seq.RichFeatureRelationshipHolder
041 * @author Matthew Pocock
042 * @author Thomas Down
043 */
044public interface FeatureHolder extends Changeable {
045  /**
046   * Signals that features have been added or removed directly within this
047   * FeatureHolder.
048   */
049  public static final ChangeType FEATURES = new ChangeType(
050    "Features have been added or removed",
051    "org.biojava.bio.seq.FeatureHolder",
052    "FEATURES"
053  );
054
055  /**
056   * Signals that the schema of this FeatureHolder has changed.
057   *
058   * @since 1.3
059   */
060  public static final ChangeType SCHEMA = new ChangeType(
061    "The schema has changed",
062    "org.biojava.bio.seq.FeatureHolder",
063    "SCHEMA"
064  );
065
066    /**
067     * Count how many features are contained.
068     *
069     * @return  a positive integer or zero, equal to the number of features
070     *          contained
071     */
072    int countFeatures();
073
074    /**
075     * Iterate over the features in no well defined order.
076     *
077     * @return  an Iterator
078     */
079    Iterator<Feature> features();
080
081    /**
082     * Return a new FeatureHolder that contains all of the children of this one
083     * that passed the filter fc.
084     *
085     * This method is scheduled for deprecation.  Use the 1-arg filter
086     * instead.
087     *
088     * @param fc  the FeatureFilter to apply
089     * @param recurse true if all features-of-features should be scanned, and a
090     *                single flat collection of features returned, or false if
091     *                just immediate children should be filtered.
092     */
093    FeatureHolder filter(FeatureFilter fc, boolean recurse);
094
095    /**
096     * Query this set of features using a supplied <code>FeatureFilter</code>.
097     *
098     * @param filter the <code>FeatureFilter</code> to apply.
099     * @return all features in this container which match <code>filter</code>.
100     */
101
102    FeatureHolder filter(FeatureFilter filter);
103
104    /**
105     * Create a new Feature, and add it to this FeatureHolder.  This
106     * method will generally only work on Sequences, and on some
107     * Features which have been attached to Sequences.
108     *
109     * @throws BioException if something went wrong during creating the feature
110     * @throws ChangeVetoException if this FeatureHolder does not support
111     *         creation of new features, or if the change was vetoed
112     */
113    public Feature createFeature(Feature.Template ft)
114        throws BioException, ChangeVetoException;
115
116    /**
117     * Remove a feature from this FeatureHolder.
118     *
119     * @throws ChangeVetoException if this FeatureHolder does not support
120     *         feature removal or if the change was vetoed
121     * @throws BioException if there was an error removing the feature
122     */
123    public void removeFeature(Feature f)
124        throws ChangeVetoException, BioException;
125
126    /**
127     * Check if the feature is present in this holder.
128     *
129     * @since 1.2
130     * @param f the Feature to check
131     * @return true if f is in this set
132     */
133    public boolean containsFeature(Feature f);
134
135    /**
136     * Return a schema-filter for this <code>FeatureHolder</code>.  This is a filter
137     * which all <code>Feature</code>s <em>immediately</em> contained by this <code>FeatureHolder</code>
138     * will match.  It need not directly match their child features, but it can (and should!) provide
139     * information about them using <code>FeatureFilter.OnlyChildren</code> filters.  In cases where there
140     * is no feature hierarchy, this can be indicated by including <code>FeatureFilter.leaf</code> in
141     * the schema filter.
142     *
143     * <p>
144     * For the truly non-informative case, it is possible to return <code>FeatureFilter.all</code>.  However,
145     * it is almost always possible to provide slightly more information that this.  For example, <code>Sequence</code>
146     * objects should, at a minimum, return <code>FeatureFilter.top_level</code>.  <code>Feature</code> objects
147     * should, as a minimum, return <code>FeatureFilter.ByParent(new FeatureFilter.ByFeature(this))</code>.
148     * </p>
149     *
150     * @since 1.3
151     * @return the schema filter
152     */
153
154    public FeatureFilter getSchema();
155
156    public static final FeatureHolder EMPTY_FEATURE_HOLDER =
157      new EmptyFeatureHolder();
158
159    final class EmptyFeatureHolder
160        extends Unchangeable
161        implements FeatureHolder
162    {
163      public int countFeatures() {
164        return 0;
165      }
166
167      public Iterator<Feature> features() {
168        return Collections.EMPTY_SET.iterator();
169      }
170
171      public FeatureHolder filter(FeatureFilter fc, boolean recurse) {
172        return this;
173      }
174
175      public FeatureHolder filter(FeatureFilter fc) {
176        return this;
177      }
178
179      public Feature createFeature(Feature.Template f) {
180        throw new UnsupportedOperationException();
181      }
182
183      public void removeFeature(Feature f) {
184        throw new UnsupportedOperationException();
185      }
186
187      public boolean containsFeature(Feature f) {
188        return false;
189      }
190
191      public FeatureFilter getSchema() {
192          return FeatureFilter.none;
193      }
194    }
195}