/*
* 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.remote;
import net.openhft.chronicle.core.annotation.NotNull;
import net.openhft.chronicle.core.util.SerializableBiFunction;
import net.openhft.chronicle.core.util.SerializableFunction;
import net.openhft.chronicle.core.util.SerializableUpdater;
import net.openhft.chronicle.core.util.SerializableUpdaterWithArg;
import net.openhft.chronicle.engine.api.map.KeyValueStore;
import net.openhft.chronicle.engine.api.map.MapView;
import net.openhft.chronicle.engine.api.pubsub.Reference;
import net.openhft.chronicle.engine.api.pubsub.Subscriber;
import net.openhft.chronicle.engine.api.tree.Asset;
import net.openhft.chronicle.engine.api.tree.RequestContext;
import net.openhft.chronicle.engine.map.KVSSubscription;
import net.openhft.chronicle.engine.map.VanillaMapView;
import net.openhft.chronicle.engine.query.Filter;
import org.jetbrains.annotations.Nullable;
import java.util.Map;
import java.util.Set;
import java.util.function.BiFunction;
import java.util.function.Function;
import static net.openhft.chronicle.core.util.ObjectUtils.convertTo;
/**
* Created by peter on 22/05/15.
*/
public class RemoteMapView<K, MV, V> extends VanillaMapView<K, V> {
@org.jetbrains.annotations.NotNull
private final RequestContext context;
public RemoteMapView(@org.jetbrains.annotations.NotNull @NotNull RequestContext context,
@org.jetbrains.annotations.NotNull @NotNull Asset asset,
@org.jetbrains.annotations.NotNull @NotNull KeyValueStore<K, V> kvStore) {
super(context, asset, kvStore);
this.context = context;
}
@Override
public boolean containsValue(Object value) {
return convertTo(Boolean.class, this.applyTo((SerializableBiFunction) MapFunction.CONTAINS_VALUE, value));
}
/* TODO CE-95
Map serialization not supported yet.
@Override
public void putAll(Map<? extends K, ? extends V> m) {
this.asyncUpdate((SerializableUpdaterWithArg) MapUpdate.PUT_ALL, m);
}
*/
@Override
public void registerKeySubscriber(@org.jetbrains.annotations.NotNull @NotNull Subscriber<K> subscriber,
@org.jetbrains.annotations.NotNull @NotNull Filter filter,
@org.jetbrains.annotations.NotNull @NotNull Set<RequestContext.Operation> contextOperations) {
@org.jetbrains.annotations.NotNull final KVSSubscription<K, V> subscription = (KVSSubscription<K, V>) asset.subscription(true);
@org.jetbrains.annotations.NotNull final RequestContext rc = RequestContext.requestContext().type(keyClass).type2(valueType);
contextOperations.forEach(e -> e.apply(rc));
subscription.registerKeySubscriber(rc, subscriber, filter);
}
@Override
public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
this.asyncUpdate((SerializableUpdaterWithArg) MapUpdate.REPLACE_ALL, function);
}
@Override
public boolean equals(Object o) {
return o instanceof Map &&
this.<Object, Boolean>applyTo((SerializableBiFunction) MapFunction.EQUALS, o);
}
@org.jetbrains.annotations.NotNull
@NotNull
@Override
public Reference<V> referenceFor(K key) {
// TODO CE-101
throw new UnsupportedOperationException("todo");
}
@Override
public int hashCode() {
return this.<Object, Integer>applyTo((SerializableBiFunction) MapFunction.HASH_CODE, null);
}
@Nullable
@Override
public V putIfAbsent(@NotNull K key, V value) {
checkKey(key);
checkValue(value);
return (V) this.applyTo((SerializableBiFunction) MapFunction.PUT_IF_ABSENT, KeyValuePair.of(key, value));
}
@Override
public boolean remove(@NotNull Object key, Object value) {
checkKey(key);
checkValue(value);
return (Boolean) this.applyTo((SerializableBiFunction) MapFunction.REMOVE, KeyValuePair.of(key, value));
}
@Override
public boolean replace(@NotNull K key, @NotNull V oldValue, @NotNull V newValue) {
checkKey(key);
checkValue(oldValue);
checkValue(newValue);
@Nullable Object o = this.applyTo((SerializableBiFunction) MapFunction.REPLACE, KeyValuesTuple.of(key, oldValue, newValue));
return convertTo(Boolean.class, o);
}
@Nullable
@Override
public V replace(@NotNull K key, @NotNull V value) {
checkKey(key);
checkValue(value);
return (V) this.applyTo((SerializableBiFunction) MapFunction.REPLACE, KeyValuePair.of(key, value));
}
@org.jetbrains.annotations.NotNull
@NotNull
@Override
public V computeIfAbsent(K key, @org.jetbrains.annotations.NotNull Function<? super K, ? extends V> mappingFunction) {
checkKey(key);
return (V) this.applyTo((SerializableBiFunction) MapFunction.COMPUTE_IF_ABSENT, KeyFunctionPair.of(key, mappingFunction));
}
@org.jetbrains.annotations.NotNull
@NotNull
@Override
public V computeIfPresent(K key, @org.jetbrains.annotations.NotNull BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
checkKey(key);
return (V) this.applyTo((SerializableBiFunction) MapFunction.COMPUTE_IF_PRESENT, KeyFunctionPair.of(key, remappingFunction));
}
@org.jetbrains.annotations.NotNull
@NotNull
@Override
public V compute(K key, @org.jetbrains.annotations.NotNull BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
checkKey(key);
return (V) this.applyTo((SerializableBiFunction) MapFunction.COMPUTE, KeyFunctionPair.of(key, remappingFunction));
}
@org.jetbrains.annotations.NotNull
@NotNull
@Override
public V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
checkKey(key);
checkValue(value);
return (V) this.applyTo((SerializableBiFunction) MapFunction.MERGE, KeyValueFunctionTuple.of(key, value, remappingFunction));
}
// core functionality.
@Nullable
@Override
public <A, R> R applyTo(@NotNull SerializableBiFunction<MapView<K, V>, A, R> function, A arg) {
@Nullable RemoteKeyValueStore<K, V> store = (RemoteKeyValueStore<K, V>) underlying();
return store.applyTo((SerializableBiFunction<MapView<K, V>, A, R>) (SerializableBiFunction) function, arg);
}
@Override
public <A> void asyncUpdate(@NotNull SerializableUpdaterWithArg<MapView<K, V>, A> updateFunction, A arg) {
@org.jetbrains.annotations.NotNull RemoteKeyValueStore<K, V> store = (RemoteKeyValueStore<K, V>) underlying();
store.asyncUpdate((SerializableUpdaterWithArg) updateFunction, arg);
}
@Nullable
@Override
public <UA, RA, R> R syncUpdate(@NotNull SerializableUpdaterWithArg<MapView<K, V>, UA>
updateFunction, UA ua, @NotNull
SerializableBiFunction<MapView<K, V>, RA, R> returnFunction, RA ra) {
@org.jetbrains.annotations.NotNull RemoteKeyValueStore<K, V> store = (RemoteKeyValueStore<K, V>) underlying();
return store.syncUpdate((SerializableUpdaterWithArg) updateFunction, ua, (SerializableBiFunction) returnFunction, ra);
}
// helper functions.
@Nullable
@Override
public <R> R applyTo(@NotNull SerializableFunction<MapView<K, V>, R> function) {
// TODO CE-95 handle this natively.
return applyTo((x, $) -> function.apply(x), null);
}
@Override
public void asyncUpdate(@NotNull SerializableUpdater<MapView<K, V>> updateFunction) {
// TODO CE-95 handle this natively.
asyncUpdate((x, $) -> updateFunction.accept(x), null);
}
@Nullable
@Override
public <R> R syncUpdate(@NotNull SerializableUpdater<MapView<K, V>> updateFunction, @NotNull
SerializableFunction<MapView<K, V>, R> returnFunction) {
// TODO CE-95 handle this natively.
return syncUpdate((x, $) -> updateFunction.accept(x), null, (x, $) -> returnFunction.apply(x), null);
}
@Nullable
@Override
public <R> R applyToKey(K key, @NotNull SerializableFunction<V, R> function) {
checkKey(key);
// TODO CE-95 handle this natively.
return applyTo((x, k) -> function.apply(x.get(k)), key);
}
@Nullable
@Override
public <T, R> R applyToKey(K key, @NotNull SerializableBiFunction<V, T, R> function, T argument) {
checkKey(key);
// TODO CE-95 handle this natively.
return applyTo((map, kv) -> function.apply(map.get(kv.key), (T) kv.value), KeyValuePair.of(key, argument));
}
@Override
public void asyncUpdateKey(K key, @NotNull SerializableFunction<V,
V> updateFunction) {
checkKey(key);
// TODO CE-95 handle this natively.
@org.jetbrains.annotations.NotNull SerializableBiFunction<K, V, V> kvvBiFunction = (k, v) -> updateFunction.apply(v);
compute(key, kvvBiFunction);
}
@Override
public <T> void asyncUpdateKey(K key, @NotNull SerializableBiFunction<V, T, V> updateFunction, T argument) {
checkKey(key);
// TODO CE-95 handle this natively.
@org.jetbrains.annotations.NotNull SerializableBiFunction<K, V, V> kvvBiFunction = (k, v) -> updateFunction.apply(v, argument);
compute(key, kvvBiFunction);
}
@Nullable
@Override
public <R> R syncUpdateKey(K key, @NotNull
SerializableFunction<V, V> updateFunction, @NotNull SerializableFunction<V, R>
returnFunction) {
checkKey(key);
// TODO CE-95 handle this natively.
@org.jetbrains.annotations.NotNull SerializableBiFunction<K, V, V> kvvBiFunction = (k, v) -> updateFunction.apply(v);
return applyTo((map, kvf) -> returnFunction.apply(map.compute(key, kvvBiFunction)), key);
}
@Nullable
@Override
public <T, RT, R> R syncUpdateKey(K key, @NotNull SerializableBiFunction<V, T, V>
updateFunction, @Nullable T updateArgument, @NotNull SerializableBiFunction<V, RT,
R> returnFunction, @Nullable RT returnArgument) {
checkKey(key);
// TODO CE-95 handle this natively.
@org.jetbrains.annotations.NotNull SerializableBiFunction<K, V, V> kvvBiFunction = (k, v) -> updateFunction.apply(v, updateArgument);
return applyTo((map, kvf) -> returnFunction.apply(map.compute(key, kvvBiFunction), returnArgument), key);
}
}