this.featureGroup = featureGroup;
}
- public boolean equals(SequenceFeature sf)
+ /**
+ * Two features are considered equal if they have the same type, group,
+ * description, start, end, phase, strand, and (if present) 'Name', ID' and
+ * 'Parent' attributes.
+ *
+ * Note we need to check Parent to distinguish the same exon occurring in
+ * different transcripts (in Ensembl GFF). This allows assembly of transcript
+ * sequences from their component exon regions.
+ */
+ @Override
+ public boolean equals(Object o)
+ {
+ return equals(o, false);
+ }
+
+ /**
+ * Overloaded method allows the equality test to optionally ignore the
+ * 'Parent' attribute of a feature. This supports avoiding adding many
+ * superficially duplicate 'exon' or CDS features to genomic or protein
+ * sequence.
+ *
+ * @param o
+ * @param ignoreParent
+ * @return
+ */
+ public boolean equals(Object o, boolean ignoreParent)
{
+ if (o == null || !(o instanceof SequenceFeature))
+ {
+ return false;
+ }
+
+ SequenceFeature sf = (SequenceFeature) o;
if (begin != sf.begin || end != sf.end || score != sf.score)
{
return false;
}
- if (!(type + description + featureGroup).equals(sf.type
- + sf.description + sf.featureGroup))
+ if (getStrand() != sf.getStrand())
{
return false;
}
+ if (!(type + description + featureGroup + getPhase()).equals(sf.type
+ + sf.description + sf.featureGroup + sf.getPhase()))
+ {
+ return false;
+ }
+ if (!equalAttribute(getValue("ID"), sf.getValue("ID")))
+ {
+ return false;
+ }
+ if (!equalAttribute(getValue("Name"), sf.getValue("Name")))
+ {
+ return false;
+ }
+ if (!ignoreParent)
+ {
+ if (!equalAttribute(getValue("Parent"), sf.getValue("Parent")))
+ {
+ return false;
+ }
+ }
return true;
}
/**
+ * Returns true if both values are null, are both non-null and equal
+ *
+ * @param att1
+ * @param att2
+ * @return
+ */
+ protected static boolean equalAttribute(Object att1, Object att2)
+ {
+ if (att1 == null && att2 == null)
+ {
+ return true;
+ }
+ if (att1 != null)
+ {
+ return att1.equals(att2);
+ }
+ return att2.equals(att1);
+ }
+
+ /**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
return String.format("%d %d %s %s", getBegin(), getEnd(), getType(),
getDescription());
}
+
+ /**
+ * Overridden to ensure that whenever two objects are equal, they have the
+ * same hashCode
+ */
+ @Override
+ public int hashCode()
+ {
+ String s = getType() + getDescription() + getFeatureGroup()
+ + getValue("ID") + getValue("Name") + getValue("Parent")
+ + getPhase();
+ return s.hashCode() + getBegin() + getEnd() + (int) getScore()
+ + getStrand();
+ }
}