private OptionallyStableInMemorySortIterator()

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);
            }
        }