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}