class XodusIxMap extends XodusIxBase<T> implements IxMap<T> {

    public Optional<T> put(Tx.Write tx, Key primaryKey, T value) {
        checkKeyAndValue(primaryKey, value);
        final Transaction txn = castTxn(tx);
        final ByteIterable pkBuf = primaryKey.toByteIterable();
        final ByteIterable newVal = valueWithChecksum(value);

        final ByteIterable oldVal = getMainDb().get(txn, pkBuf);
        if (newVal.equals(oldVal)) {
            // Exact same value already exists in the database, no need to store it again
            // or to update indexes.
            return Optional.of(value);
        }

        getMainDb().put(txn, pkBuf, newVal);
        if (oldVal != null) {
            final T oldValue = getValue(primaryKey, Bytes.toBytes(oldVal));
            indexFunctions.forEach((idxName, idxFun) -> {
                final Set<Key> oldIndexKeys = idxFun.apply(oldValue);
                final Set<Key> indexKeys = idxFun.apply(value).stream()
                        .filter(Objects::nonNull)
                        .collect(Collectors.toSet());
                final Store index = getIdx(idxName);
                oldIndexKeys.stream()
                        .filter(oik -> !indexKeys.contains(oik))
                        .forEach(oik -> {
                            try (Cursor c = index.openCursor(txn)) {
                                if (c.getSearchBoth(oik.toByteIterable(), pkBuf)) {
                                    c.deleteCurrent();
                                }
                            }
                        });

                indexKeys.stream()
                        .filter(ik -> !oldIndexKeys.contains(ik))
                        .forEach(ik -> index.put(txn, ik.toByteIterable(), pkBuf));
            });
            return Optional.of(oldValue);
        }
        indexFunctions.forEach((idxName, idxFun) -> {
            final Set<Key> indexKeys = idxFun.apply(value).stream()
                    .filter(Objects::nonNull)
                    .collect(Collectors.toSet());

            indexKeys.forEach(ik -> getIdx(idxName).put(txn, ik.toByteIterable(), pkBuf));
        });

        return Optional.empty();
    }

    public  XodusIxMap(final Xodus xodus,
                      final String name,
                      final Coder<T> coder,
                      final Map<String, Function<T, Set<Key>>> indexFunctions);

}