package org.nextprot.api.core.utils.annot.comp;
import com.google.common.base.Preconditions;
import org.nextprot.api.core.domain.annotation.Annotation;
import org.nextprot.api.core.domain.annotation.AnnotationIsoformSpecificity;
import java.util.*;
import static org.nextprot.api.core.utils.annot.comp.AnnotationComparators.compareNullableComparableObject;
/**
* Comparison function that sort Annotations based on feature positions.
*
* <h3>A. Selecting isoform feature positions</h3>
* As Annotation can contain multiple isoform targets, we first have to choose one of them
* with the following criteria:
*
* <pre>
* if has a single isoform:
* pick this one
* else
* select the one with the lowest feature position (see Section B)
* endif
* </pre>
*
* The feature positions of the selected isoforms are then compared as below
*
* <h3>B. Feature position based Annotation comparison</h3>
*
* <ol>
* <li>feature begin ASC</li>
* <li>feature end DESC</li>
* </ol>
*/
class ByFeaturePositionComparator implements Comparator<Annotation> {
@Override
public int compare(Annotation a1, Annotation a2) {
String isoformName1 = selectIsoformNameForComparison(a1);
String isoformName2 = selectIsoformNameForComparison(a2);
return compareAnnotByNullablePosition(
a1.getStartPositionForIsoform(isoformName1), a1.getEndPositionForIsoform(isoformName1),
a2.getStartPositionForIsoform(isoformName2), a2.getEndPositionForIsoform(isoformName2)
);
}
private String selectIsoformNameForComparison(Annotation annotation) {
Map<String, AnnotationIsoformSpecificity> targets = annotation.getTargetingIsoformsMap();
if (targets.size() == 1)
return targets.keySet().iterator().next();
else
return getFirstIsoformSpecificity(targets.values()).getIsoformAccession();
}
static AnnotationIsoformSpecificity getFirstIsoformSpecificity(Collection<AnnotationIsoformSpecificity> targets) {
Preconditions.checkNotNull(targets);
Preconditions.checkArgument(!targets.isEmpty());
Iterator<AnnotationIsoformSpecificity> iter = targets.iterator();
AnnotationIsoformSpecificity first = iter.next();
while (iter.hasNext()) {
AnnotationIsoformSpecificity specificity = iter.next();
int cmp = compareAnnotByNullablePosition(
specificity.getFirstPosition(), specificity.getLastPosition(),
first.getFirstPosition(), first.getLastPosition()
);
if (cmp < 0) {
first = specificity;
}
}
return first;
}
/*
<h2>Comparison contract</h2>
<h3>Unknown(null) begin comes first</h3>
[1] ?-------
[2] i---------
<h3>Same begins greater ending comes first</h3>
[1] ----------
[2] ------
*/
static int compareAnnotByNullablePosition(Integer begin1, Integer end1, Integer begin2, Integer end2) {
int cmp;
// 1. begin positions in ascending order
// UNKNOWN BEGIN COMES FIRST
cmp = compareNullableComparableObject(begin1, begin2, true);
// 2. end positions in descending order (most inclusive comes first)
if (cmp == 0) {
// UNKNOWN END COMES LAST
cmp = compareNullableComparableObject(end1, end2, false);
}
return cmp;
}
}