Skip to content

@Node with interfaces returned as a parent class #2839

Open
@EliotRagueneau

Description

@EliotRagueneau

I have an issue where I have defined some @node with interfaces so that I can fetch a group of Nodes which are unrelated in terms of inheritance.

Because of this, my nodes are having labels that the NodeDescriptionStore is not aware of, since it doesn't resolve interface as Labels.

Because of that, none of the haystack definitions are a perfect match for the result labels, which is absolutely fine in theory .

if (staticLabels.containsAll(labels)) {
Set<String> surplusLabels = new HashSet<>(labels);
staticLabels.forEach(surplusLabels::remove);
return new NodeDescriptionAndLabels(nd, surplusLabels);
}

Since none of them is a perfect match, it then try to pick the mostMatchingNodeDescription and that is where the problem lies I believe:

int unmatchedLabelsCount = 0;
List<String> matchingLabels = new ArrayList<>();
for (String staticLabel : staticLabels) {
if (labels.contains(staticLabel)) {
matchingLabels.add(staticLabel);
} else {
unmatchedLabelsCount++;
}
}
unmatchedLabelsCache.put(nd, unmatchedLabelsCount);
if (mostMatchingNodeDescription == null || unmatchedLabelsCount < unmatchedLabelsCache.get(mostMatchingNodeDescription)) {
mostMatchingNodeDescription = nd;
mostMatchingStaticLabels = matchingLabels;
}
}

Indeed, with the current implementation, if A extends B and B extends C

A --> B --> C

but the record node labels are [A,B,C,D], then even though A is the most "concrete" class, A, B and C node description will all have an unmatchedLabelCount of 0.
Therefore, the NodeDescription being picked in the end is the one that was first in the haystack, not the one with the most matching labels.

I would suggest something like

if (
    mostMatchingNodeDescription == null || 
    unmatchedLabelsCount < unmatchedLabelsCache.get(mostMatchingNodeDescription) || 
    (unmatchedLabelsCount ==  unmatchedLabelsCache.get(mostMatchingNodeDescription) && matchingLabels.size() > mostMatchingStaticLabels.size())
) {
	mostMatchingNodeDescription = nd;
        mostMatchingStaticLabels = matchingLabels;
}

This way, if there is a tie in terms of "unmatchness", we pick the one with the best "matchness", aka, the one with the biggest amount of matching labels

Thanks for all the support you already provided to Reactome team,
Best regards,
Eliot

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions