/**
   * Delete an exon. Deletes both the transcript -> exon and exon -> transcript relationships.
   *
   * @param exon - Exon to be deleted
   */
  public void deleteExon(Exon exon) {
    Collection<CVTerm> partOfCvterms = conf.getCVTermsForClass("PartOf");
    Collection<CVTerm> exonCvterms = conf.getCVTermsForClass("Exon");
    Collection<CVTerm> transcriptCvterms = conf.getCVTermsForClass("Transcript");

    // delete transcript -> exon child relationship
    for (FeatureRelationship fr : feature.getChildFeatureRelationships()) {
      if (!partOfCvterms.contains(fr.getType())) {
        continue;
      }
      if (!exonCvterms.contains(fr.getSubjectFeature().getType())) {
        continue;
      }
      if (fr.getSubjectFeature().equals(exon.getFeature())) {
        boolean ok = feature.getChildFeatureRelationships().remove(fr);
        break;
      }
    }

    // delete transcript -> exon parent relationship
    for (FeatureRelationship fr : exon.getFeature().getParentFeatureRelationships()) {
      if (!partOfCvterms.contains(fr.getType())) {
        continue;
      }
      if (!transcriptCvterms.contains(fr.getObjectFeature().getType())) {
        continue;
      }
      if (fr.getSubjectFeature().equals(exon.getFeature())) {
        boolean ok = exon.getFeature().getParentFeatureRelationships().remove(fr);
        break;
      }
    }
  }
  /**
   * Add an exon. If the exon's bounds are beyond the transcript's bounds, the transcript's bounds
   * are adjusted accordingly. Sets the exon's transcript to this transcript object.
   *
   * @param exon - Exon to be added
   */
  public void addExon(Exon exon) {
    CVTerm partOfCvterm = conf.getDefaultCVTermForClass("PartOf");

    // if the exon's bounds are beyond the transcript's bounds, need to adjust the transcript's
    // bounds
    if (exon.getFeatureLocation().getFmin() < getFeatureLocation().getFmin()) {
      getFeatureLocation().setFmin(exon.getFeatureLocation().getFmin());
    }
    if (exon.getFeatureLocation().getFmax() > getFeatureLocation().getFmax()) {
      getFeatureLocation().setFmax(exon.getFeatureLocation().getFmax());
    }

    // if the transcript's bounds are beyond the gene's bounds, need to adjust the gene's bounds
    if (getGene() != null) {
      if (getFmin() < getGene().getFmin()) {
        getGene().setFmin(getFmin());
      }
      if (getFmax() > getGene().getFmax()) {
        getGene().setFmax(getFmax());
      }
    }

    // add exon
    int rank = 0;
    // TODO: do we need to figure out the rank?
    feature
        .getChildFeatureRelationships()
        .add(new FeatureRelationship(partOfCvterm, feature, exon.getFeature(), rank));
    exon.setTranscript(this);
  }