
net.fortytwo.sesametools.ValueComparator Maven / Gradle / Ivy
Show all versions of common Show documentation
package net.fortytwo.sesametools;
import org.openrdf.model.BNode;
import org.openrdf.model.IRI;
import org.openrdf.model.Literal;
import org.openrdf.model.Value;
import java.util.Comparator;
import java.util.Optional;
/**
* Implements a Comparator for OpenRDF Value objects where
* the order for Values is:
*
* - Blank Node's
* - URI's
* - Literals
*
*
* with null Values sorted before others
*
* @author Peter Ansell [email protected]
*/
public class ValueComparator implements Comparator {
/**
* A thread-safe pre-instantiated instance of ValueComparator.
*/
private final static ValueComparator INSTANCE = new ValueComparator();
/**
* A thread-safe pre-instantiated instance of ValueComparator.
*/
public static ValueComparator getInstance() {
return INSTANCE;
}
public final static int BEFORE = -1;
public final static int EQUAL = 0;
public final static int AFTER = 1;
/**
* Sorts in the order nulls>BNodes>URIs>Literals
*
* This is due to the fact that nulls are only applicable to contexts,
* and according to the OpenRDF documentation, the type of the null
* cannot be sufficiently distinguished from any other Value to make
* an intelligent comparison to other Values:
*
*
* BNodes are sorted according to the lexical compare of their identifiers,
* which provides a way to sort statements with the same BNodes in the same positions, near each other
* BNode sorting is not specified across sessions
*
*/
@Override
public int compare(Value first, Value second) {
if (first == null) {
if (second == null) {
return EQUAL;
} else {
return BEFORE;
}
} else if (second == null) {
// always sort null Values before others, so if the second is null,
// but the first wasn't, sort the first after the second
return AFTER;
}
if (first == second || first.equals(second)) {
return EQUAL;
}
if (first instanceof BNode) {
if (second instanceof BNode) {
// if both are BNodes, sort based on the lexical value of the internal ID
// Although this sorting is not guaranteed to be consistent across sessions,
// it provides a consistent sorting of statements in every case
// so that statements with the same BNode are sorted near each other
return ((BNode) first).getID().compareTo(((BNode) second).getID());
} else {
return BEFORE;
}
} else if (second instanceof BNode) {
// sort BNodes before other things, and first was not a BNode
return AFTER;
} else if (first instanceof IRI) {
if (second instanceof IRI) {
return first.stringValue().compareTo(second.stringValue());
} else {
return BEFORE;
}
} else if (second instanceof IRI) {
// sort URIs before Literals
return AFTER;
}
// they must both be Literal's, so sort based on the lexical value of the Literal
else {
Literal firstLiteral = (Literal) first;
Literal secondLiteral = (Literal) second;
int cmp = firstLiteral.getLabel().compareTo(secondLiteral.getLabel());
if (EQUAL == cmp) {
Optional firstLang = firstLiteral.getLanguage();
Optional secondLang = secondLiteral.getLanguage();
if (firstLang.isPresent()) {
if (secondLang.isPresent()) {
return firstLang.get().compareTo(secondLang.get());
} else {
return AFTER;
}
} else if (secondLang.isPresent()) {
return BEFORE;
}
IRI firstType = firstLiteral.getDatatype();
IRI secondType = secondLiteral.getDatatype();
if (null == firstType) {
if (null == secondType) {
return EQUAL;
} else {
return BEFORE;
}
} else if (null == secondType) {
return AFTER;
} else {
return firstType.stringValue().compareTo(secondType.stringValue());
}
} else {
return cmp;
}
}
}
}