/*
* Copyright 2016 higherfrequencytrading.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package net.openhft.chronicle.engine.map;
import net.openhft.chronicle.bytes.Bytes;
import net.openhft.chronicle.bytes.BytesStore;
import net.openhft.chronicle.engine.api.EngineReplication.ReplicationEntry;
import net.openhft.chronicle.engine.api.map.KeyValueStore;
import net.openhft.chronicle.engine.api.map.MapEvent;
import net.openhft.chronicle.engine.api.pubsub.InvalidSubscriberException;
import net.openhft.chronicle.engine.api.pubsub.SubscriptionConsumer;
import net.openhft.chronicle.engine.api.tree.Asset;
import net.openhft.chronicle.engine.api.tree.Assetted;
import net.openhft.chronicle.engine.api.tree.RequestContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Iterator;
import java.util.Map;
import java.util.function.BiFunction;
import static net.openhft.chronicle.engine.map.Buffers.BUFFERS;
/**
* Created by peter on 25/05/15.
*/
public class ObjectObjectKeyValueStore<K, V> implements KeyValueStore<K, V> {
@NotNull
private final BiFunction<K, Bytes, Bytes> keyToBytes;
@NotNull
private final BiFunction<V, Bytes, Bytes> valueToBytes;
@NotNull
private final BiFunction<BytesStore, K, K> bytesToKey;
@NotNull
private final BiFunction<BytesStore, V, V> bytesToValue;
@NotNull
private final KeyValueStore<BytesStore, BytesStore> kvStore;
private final Asset asset;
public ObjectObjectKeyValueStore(@NotNull RequestContext context, Asset asset, Assetted assetted) {
this.asset = asset;
@NotNull Class type = context.type();
keyToBytes = toBytes(type);
bytesToKey = fromBytes(type);
Class type2 = context.type2();
valueToBytes = toBytes(type2);
bytesToValue = fromBytes(type2);
kvStore = (KeyValueStore<BytesStore, BytesStore>) assetted;
}
private static <T> BiFunction<T, Bytes, Bytes> toBytes(Class type) {
if (type == String.class)
return (t, bytes) -> (Bytes) bytes.appendUtf8((String) t);
throw new UnsupportedOperationException("todo");
}
private <T> BiFunction<BytesStore, T, T> fromBytes(Class type) {
if (type == String.class)
return (t, bytes) -> (T) (bytes == null ? null : bytes.toString());
throw new UnsupportedOperationException("todo");
}
@Override
public boolean put(K key, V value) {
Buffers b = BUFFERS.get();
Bytes keyBytes = keyToBytes.apply(key, b.keyBuffer);
Bytes valueBytes = valueToBytes.apply(value, b.valueBuffer);
return kvStore.put(keyBytes, valueBytes);
}
@Nullable
@Override
public V getAndPut(K key, V value) {
Buffers b = BUFFERS.get();
Bytes keyBytes = keyToBytes.apply(key, b.keyBuffer);
Bytes valueBytes = valueToBytes.apply(value, b.valueBuffer);
@Nullable BytesStore retBytes = kvStore.getAndPut(keyBytes, valueBytes);
return retBytes == null ? null : bytesToValue.apply(retBytes, null);
}
@Override
public boolean remove(K key) {
Buffers b = BUFFERS.get();
Bytes keyBytes = keyToBytes.apply(key, b.keyBuffer);
return kvStore.remove(keyBytes);
}
@Nullable
@Override
public V getAndRemove(K key) {
Buffers b = BUFFERS.get();
Bytes keyBytes = keyToBytes.apply(key, b.keyBuffer);
@Nullable BytesStore retBytes = kvStore.getAndRemove(keyBytes);
return retBytes == null ? null : bytesToValue.apply(retBytes, null);
}
@Nullable
@Override
public V getUsing(K key, Object value) {
Buffers b = BUFFERS.get();
Bytes keyBytes = keyToBytes.apply(key, b.keyBuffer);
@Nullable BytesStore retBytes = kvStore.getUsing(keyBytes, b.valueBuffer);
return retBytes == null ? null : bytesToValue.apply(retBytes, (V) value);
}
@Override
public long longSize() {
return kvStore.longSize();
}
@Override
public void keysFor(int segment, @NotNull SubscriptionConsumer<K> kConsumer) throws InvalidSubscriberException {
kvStore.keysFor(segment, k -> kConsumer.accept(bytesToKey.apply(k, null)));
}
@Override
public void entriesFor(int segment, @NotNull SubscriptionConsumer<MapEvent<K, V>> kvConsumer) throws InvalidSubscriberException {
kvStore.entriesFor(segment, e -> kvConsumer.accept(e.translate(bytesToKey, bytesToValue)));
}
@NotNull
@Override
public Iterator<Map.Entry<K, V>> entrySetIterator() {
throw new UnsupportedOperationException("todo");
}
@Override
public void clear() {
kvStore.clear();
}
@NotNull
@Override
public V replace(K key, V value) {
throw new UnsupportedOperationException("todo");
}
@Override
public boolean containsValue(final V value) {
throw new UnsupportedOperationException("todo");
}
@Override
public Asset asset() {
return asset;
}
@Override
public KeyValueStore underlying() {
return kvStore;
}
@Override
public void close() {
kvStore.close();
}
@Override
public void accept(final ReplicationEntry replicationEntry) {
throw new UnsupportedOperationException("todo");
}
}