package org.infinispan.commands.functional;
import static org.infinispan.functional.impl.EntryViews.snapshot;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.ArrayList;
import java.util.Collection;
import java.util.function.Function;
import org.infinispan.commands.AbstractTopologyAffectedCommand;
import org.infinispan.commands.LocalCommand;
import org.infinispan.commands.Visitor;
import org.infinispan.commons.api.functional.EntryView.ReadEntryView;
import org.infinispan.commons.marshall.MarshallUtil;
import org.infinispan.container.entries.CacheEntry;
import org.infinispan.context.InvocationContext;
import org.infinispan.functional.impl.EntryViews;
public class ReadOnlyManyCommand<K, V, R> extends AbstractTopologyAffectedCommand implements LocalCommand {
public static final int COMMAND_ID = 63;
protected Collection<? extends K> keys;
protected Function<ReadEntryView<K, V>, R> f;
public ReadOnlyManyCommand(Collection<? extends K> keys, Function<ReadEntryView<K, V>, R> f) {
this.keys = keys;
this.f = f;
}
public ReadOnlyManyCommand() {
}
public ReadOnlyManyCommand(ReadOnlyManyCommand c) {
this.keys = c.keys;
this.f = c.f;
}
public Collection<? extends K> getKeys() {
return keys;
}
public void setKeys(Collection<? extends K> keys) {
this.keys = keys;
}
public final ReadOnlyManyCommand<K, V, R> withKeys(Collection<? extends K> keys) {
setKeys(keys);
return this;
}
@Override
public byte getCommandId() {
return COMMAND_ID;
}
@Override
public boolean isReturnValueExpected() {
return true;
}
@Override
public boolean canBlock() {
return false;
}
@Override
public void writeTo(ObjectOutput output) throws IOException {
MarshallUtil.marshallCollection(keys, output);
output.writeObject(f);
}
@Override
public void readFrom(ObjectInput input) throws IOException, ClassNotFoundException {
this.keys = MarshallUtil.unmarshallCollection(input, ArrayList::new);
this.f = (Function<ReadEntryView<K, V>, R>) input.readObject();
}
@Override
public Object perform(InvocationContext ctx) throws Throwable {
// lazy execution triggers exceptions on unexpected places
ArrayList<R> retvals = new ArrayList<R>(keys.size());
for (K k : keys) {
CacheEntry<K, V> me = lookupCacheEntry(ctx, k);
R ret = f.apply(me.isNull() ? EntryViews.noValue(k) : EntryViews.readOnly(me));
retvals.add(snapshot(ret));
}
return retvals.stream();
}
protected CacheEntry<K, V> lookupCacheEntry(InvocationContext ctx, Object key) {
return ctx.lookupEntry(key);
}
@Override
public Object acceptVisitor(InvocationContext ctx, Visitor visitor) throws Throwable {
return visitor.visitReadOnlyManyCommand(ctx, this);
}
@Override
public LoadType loadType() {
return LoadType.OWNER;
}
@Override
public String toString() {
return "ReadOnlyManyCommand{" +
"keys=" + keys +
", f=" + f +
'}';
}
}