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.HashSet;
025import java.util.Iterator;
026import java.util.Set;
027
028import org.biojava.utils.ChangeVetoException;
029
030  /**
031   * This class intendes to provide some FeatureHolder utilities. 
032   * Currently it is mainly providing set operators.
033   * 
034   * @author Markus Brosch (markus[at]brosch[dot]cc)
035   */
036  public class FeatureHolderUtils {
037
038    /**
039     * Operator: Union of FeatureHolder1 and FeatureHolder2
040     * @param fh1 FeatureHolder1
041     * @param fh2 FeatureHolder2
042     * @return Union of fh1 and fh2 (corresponds to logical OR)
043     * @throws ChangeVetoException
044     */
045    public static FeatureHolder union(FeatureHolder fh1, FeatureHolder fh2)
046        throws ChangeVetoException {
047
048      int s1 = fh1.countFeatures();
049      int s2 = fh2.countFeatures();
050
051      if (s1 < s2) {
052        return unionOp(fh2, fh1);
053      } else {
054        return unionOp(fh1, fh2);
055      }
056    }
057
058    private static FeatureHolder unionOp(FeatureHolder fh1, FeatureHolder fh2)
059        throws ChangeVetoException {
060
061      SimpleFeatureHolder res = new SimpleFeatureHolder();
062      for (Iterator it = fh1.features(); it.hasNext();) {
063        res.addFeature((Feature) it.next());
064      }
065      for (Iterator it = fh2.features(); it.hasNext();) {
066        Feature f = (Feature) it.next();
067        if (!res.containsFeature(f)) {
068          res.addFeature(f);
069        }
070      }
071      return res;
072    }
073
074    /**
075     * Operator: Intersect FeatureHolder1 with FeatureHolder2
076     * @param fh1 FeatureHolder1
077     * @param fh2 FeatureHolder2
078     * @return Intersection of fh1 and fh2 (corresponds to logical AND)
079     * @throws ChangeVetoException
080     */
081    public static FeatureHolder intersect(FeatureHolder fh1, FeatureHolder fh2)
082        throws ChangeVetoException {
083
084      int s1 = fh1.countFeatures();
085      int s2 = fh2.countFeatures();
086
087      if (s1 < s2) {
088        return intersectOp(fh1, fh2);
089      } else {
090        return intersectOp(fh2, fh1);
091      }
092    }
093
094    private static FeatureHolder intersectOp(FeatureHolder fh1,
095        FeatureHolder fh2)
096        throws ChangeVetoException {
097
098      SimpleFeatureHolder res = new SimpleFeatureHolder();
099      for (Iterator it = fh1.features(); it.hasNext();) {
100        Feature f = (Feature) it.next();
101        if (fh2.containsFeature(f)) {
102          res.addFeature(f);
103        }
104      }
105      return res;
106    }
107
108    /**
109     * Operator: FeatureHolder 1 NOT FeatureHolder2
110     * @param fh1 FeatureHolder1
111     * @param fh2 FeatureHolder2
112     * @return Set of fh1 without any feature of fh2 (Not)
113     * @throws ChangeVetoException
114     */
115    public static FeatureHolder not(FeatureHolder fh1, FeatureHolder fh2)
116        throws ChangeVetoException {
117
118      SimpleFeatureHolder res = new SimpleFeatureHolder();
119      for (Iterator it = fh1.features(); it.hasNext();) {
120        Feature f = (Feature) it.next();
121        if (!fh2.containsFeature(f)) {
122          res.addFeature(f);
123        }
124      }
125      return res;
126    }
127
128    /**
129     * Returns a FeatureHolder as a Set of Features
130     * @param fh FeatureHolder you want to have as a Set
131     * @return Set of FeatureHoler fh
132     */
133    public static Set featureHolderAsSet(FeatureHolder fh) {
134      return new FeatureHolderAsSet(fh);
135    }
136
137    /**
138     * FeatureHolderAsSet represents a FeatureHolder as a Set.<br>
139     * You can use the FeatureHolder as a normal Set.
140     */
141    private final static class FeatureHolderAsSet extends HashSet {
142
143      FeatureHolderAsSet(FeatureHolder fh) {
144        for (Iterator it = fh.features(); it.hasNext();) {
145          add(it.next());
146        }
147      }
148    }
149
150  }