import jalview.util.StringUtils;
import java.util.Comparator;
-import java.util.HashMap;
+import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.SortedMap;
private static final String STATUS = "status";
- private static final String STRAND = "STRAND";
+ public static final String STRAND = "STRAND";
- // private key for Phase designed not to conflict with real GFF data
- private static final String PHASE = "!Phase";
+ // key for Phase designed not to conflict with real GFF data
+ public static final String PHASE = "!Phase";
// private key for ENA location designed not to conflict with real GFF data
private static final String LOCATION = "!Location";
private static final String ROW_DATA = "<tr><td>%s</td><td>%s</td><td>%s</td></tr>";
/*
- * ATTRIBUTES is reserved for the GFF 'column 9' data, formatted as
- * name1=value1;name2=value2,value3;...etc
- */
- private static final String ATTRIBUTES = "ATTRIBUTES";
-
- /*
* type, begin, end, featureGroup, score and contactFeature are final
* to ensure that the integrity of SequenceFeatures data store
* can't be broken by direct update of these fields
if (sf.otherDetails != null)
{
- otherDetails = new HashMap<>();
- for (Entry<String, Object> entry : sf.otherDetails.entrySet())
- {
- otherDetails.put(entry.getKey(), entry.getValue());
- }
+ otherDetails = new LinkedHashMap<>();
+ otherDetails.putAll(sf.otherDetails);
}
if (sf.links != null && sf.links.size() > 0)
{
links = new Vector<>();
- for (int i = 0, iSize = sf.links.size(); i < iSize; i++)
- {
- links.addElement(sf.links.elementAt(i));
- }
+ links.addAll(sf.links);
}
}
@Override
public boolean equals(Object o)
{
- return (o instanceof SequenceFeature
- && equals((SequenceFeature) o, false));
+ return equals(o, false);
}
/**
* @param ignoreParent
* @return
*/
- public boolean equals(SequenceFeature sf, boolean ignoreParent)
+ public boolean equals(Object o, boolean ignoreParent)
{
- return (begin == sf.begin && end == sf.end
- && getStrand() == sf.getStrand()
- && (Float.isNaN(score) ? Float.isNaN(sf.score)
- : score == sf.score)
- && (type + description + featureGroup + getPhase())
- .equals(sf.type + sf.description + sf.featureGroup
- + sf.getPhase())
- && equalAttribute(getValue("ID"), sf.getValue("ID"))
- && equalAttribute(getValue("Name"), sf.getValue("Name"))
- && (ignoreParent || equalAttribute(getValue("Parent"),
- sf.getValue("Parent"))));
+ if (o == null || !(o instanceof SequenceFeature))
+ {
+ return false;
+ }
+
+ SequenceFeature sf = (SequenceFeature) o;
+ boolean sameScore = Float.isNaN(score) ? Float.isNaN(sf.score)
+ : score == sf.score;
+ if (begin != sf.begin || end != sf.end || !sameScore)
+ {
+ return false;
+ }
+
+ 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;
}
/**
return featureGroup;
}
+ /**
+ * Adds a hyperlink for the feature. This should have the format label|url.
+ *
+ * @param labelLink
+ */
public void addLink(String labelLink)
{
if (links == null)
{
if (otherDetails == null)
{
- otherDetails = new HashMap<>();
+ /*
+ * LinkedHashMap preserves insertion order of attributes
+ */
+ otherDetails = new LinkedHashMap<>();
}
otherDetails.put(key, value);
return (String) getValue(STATUS);
}
- public void setAttributes(String attr)
- {
- setValue(ATTRIBUTES, attr);
- }
-
- public String getAttributes()
- {
- return (String) getValue(ATTRIBUTES);
- }
-
/**
* Return 1 for forward strand ('+' in GFF), -1 for reverse strand ('-' in
* GFF), and 0 for unknown or not (validly) specified
/**
* Answers an html-formatted report of feature details
*
+ * @param seqName
+ *
* @return
*/
- public String getDetailsReport()
+ public String getDetailsReport(String seqName)
{
FeatureSourceI metadata = FeatureSources.getInstance()
.getSource(source);
StringBuilder sb = new StringBuilder(128);
sb.append("<br>");
sb.append("<table>");
+ sb.append(String.format(ROW_DATA, "Location", seqName,
+ begin == end ? begin
+ : begin + (isContactFeature() ? ":" : "-") + end));
sb.append(String.format(ROW_DATA, "Type", type, ""));
- sb.append(String.format(ROW_DATA, "Start/end", begin == end ? begin
- : begin + (isContactFeature() ? ":" : "-") + end, ""));
String desc = StringUtils.stripHtmlTags(description);
sb.append(String.format(ROW_DATA, "Description", desc, ""));
if (!Float.isNaN(score) && score != 0f)
for (Entry<String, Object> entry : ordered.entrySet())
{
String key = entry.getKey();
- if (ATTRIBUTES.equals(key))
- {
- continue; // to avoid double reporting
- }
Object value = entry.getValue();
if (value instanceof Map<?, ?>)
{
source = theSource;
}
-
-
}
class SFSortByEnd implements Comparator<SequenceFeature>