in entity-store/src/main/java/jetbrains/exodus/entitystore/iterate/SortIterable.java [385:460]
private OptionallyStableInMemorySortIterator(final int sourceSize, final boolean stable) {
super(propIndex);
pairs = new ArrayList<>(sourceSize / 2);
hasNull = false;
cursor = 0;
final PersistentEntityStoreImpl store = getStore();
final PersistentStoreTransaction txn = getTransaction();
final String propertyName = store.getPropertyName(txn, propertyId);
if (propertyName == null) {
throw new NullPointerException("Property name is null");
}
final int propertyId = store.getPropertyId(txn, propertyName, false);
if (propertyId < 0) {
throw new IllegalStateException("Property name is not registered");
}
final TransactionBase envTxn = (TransactionBase) txn.getEnvironmentTransaction();
final boolean isStoreGetCacheDisabled = envTxn.isDisableStoreGetCache();
try {
envTxn.setDisableStoreGetCache(true);
final EntityIterator it = source.iterator();
while (it.hasNext()) {
final PersistentEntityId nextId = (PersistentEntityId) it.nextId();
if (nextId == null) {
hasNull = true;
} else if (nextId.getTypeId() == sourceTypeId) {
final PropertyValue propValue = store.getPropertyValue(txn, new PersistentEntity(store, nextId), propertyId);
pairs.add(new IdValuePair(nextId.getLocalId(), propValue == null ? null : propValue.getData()));
}
}
} finally {
envTxn.setDisableStoreGetCache(isStoreGetCacheDisabled);
}
// finally sort
final Object[] array = pairs.toArray();
Arrays.sort(array, (Comparator) (o1, o2) -> {
final IdValuePair pair1 = (IdValuePair) o1;
final IdValuePair pair2 = (IdValuePair) o2;
final Comparable propValue1 = pair1.propValue;
final Comparable propValue2 = pair2.propValue;
int result;
if (propValue1 == null && propValue2 == null) {
result = 0;
} else if (propValue1 == null) {
result = 1;
} else if (propValue2 == null) {
result = -1;
} else {
final boolean isString = propValue1 instanceof String;
if (ascending) {
result = isString ? ((String) propValue1).compareToIgnoreCase((String) propValue2) :
propValue1.compareTo(propValue2);
} else {
result = isString ? ((String) propValue2).compareToIgnoreCase((String) propValue1) :
propValue2.compareTo(propValue1);
}
}
if (!stable && result == 0) {
if (pair1.localId < pair2.localId) {
result = -1;
} else if (pair1.localId > pair2.localId) {
result = 1;
}
}
return result;
});
final ListIterator<IdValuePair> i = pairs.listIterator();
for (final Object o : array) {
i.next();
i.set((IdValuePair) o);
}
}