org.infinispan.functional.impl.EntryViews Maven / Gradle / Ivy
package org.infinispan.functional.impl;
import org.infinispan.commons.api.functional.EntryView.ReadEntryView;
import org.infinispan.commons.api.functional.EntryView.ReadWriteEntryView;
import org.infinispan.commons.api.functional.EntryView.WriteEntryView;
import org.infinispan.commons.api.functional.MetaParam;
import org.infinispan.commons.marshall.AbstractExternalizer;
import org.infinispan.commons.util.Experimental;
import org.infinispan.commons.util.Util;
import org.infinispan.container.entries.CacheEntry;
import org.infinispan.marshall.core.Ids;
import org.infinispan.metadata.Metadata;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.NoSuchElementException;
import java.util.Optional;
import java.util.Set;
/**
* Entry views implementation class holder.
*
* @since 8.0
*/
@Experimental
public final class EntryViews {
private EntryViews() {
// Cannot be instantiated, it's just a holder class
}
public static ReadEntryView readOnly(CacheEntry entry) {
return new EntryBackedReadOnlyView<>(entry);
}
public static ReadEntryView readOnly(K key, V value, Metadata metadata) {
return new ReadOnlySnapshotView<>(key, value, metadata);
}
public static WriteEntryView writeOnly(CacheEntry entry) {
return new EntryBackedWriteOnlyView<>(entry);
}
public static ReadWriteEntryView readWrite(CacheEntry entry) {
return new EntryBackedReadWriteView<>(entry);
}
public static ReadWriteEntryView readWrite(CacheEntry entry, V prevValue, Metadata prevMetadata) {
return new EntryAndPreviousReadWriteView<>(entry, prevValue, prevMetadata);
}
public static ReadEntryView noValue(K key) {
return new NoValueReadOnlyView<>(key);
}
/**
* For convenience, a lambda might decide to return the entry view it
* received as parameter, because that makes easy to return both value and
* meta parameters back to the client.
*
* If the lambda function decides to return an view, launder it into an
* immutable view to avoid the user trying apply any modifications to the
* entry view from outside the lambda function.
*
* If the view is read-only, capture its data into a snapshot from the
* cached entry and avoid changing underneath.
*/
@SuppressWarnings("unchecked")
public static R snapshot(R ret) {
if (ret instanceof EntryBackedReadWriteView) {
EntryBackedReadWriteView view = (EntryBackedReadWriteView) ret;
return (R) new ReadWriteSnapshotView(view.key(), view.entry.getValue(), view.entry.getMetadata());
} else if (ret instanceof EntryAndPreviousReadWriteView) {
EntryAndPreviousReadWriteView view = (EntryAndPreviousReadWriteView) ret;
return (R) new ReadWriteSnapshotView(view.key(), view.entry.getValue(), view.entry.getMetadata());
} else if (ret instanceof EntryBackedReadOnlyView) {
EntryBackedReadOnlyView view = (EntryBackedReadOnlyView) ret;
return (R) new ReadOnlySnapshotView(view.key(), view.entry.getValue(), view.entry.getMetadata());
}
return ret;
}
private static final class EntryBackedReadOnlyView implements ReadEntryView {
final CacheEntry entry;
private EntryBackedReadOnlyView(CacheEntry entry) {
this.entry = entry;
}
@Override
public K key() {
return entry.getKey();
}
@Override
public Optional find() {
return entry == null ? Optional.empty() : Optional.ofNullable(entry.getValue());
}
@Override
public V get() throws NoSuchElementException {
if (entry == null || entry.getValue() == null)
throw new NoSuchElementException("No value present");
return entry.getValue();
}
@Override
public Optional findMetaParam(Class type) {
Metadata metadata = entry.getMetadata();
if (metadata instanceof MetaParamsInternalMetadata) {
MetaParamsInternalMetadata metaParamsMetadata = (MetaParamsInternalMetadata) metadata;
return metaParamsMetadata.findMetaParam(type);
}
// TODO: Add interoperability support, e.g. able to retrieve lifespan for data stored in Cache via lifespan API
return Optional.empty();
}
@Override
public String toString() {
return "EntryBackedReadOnlyView{" + "entry=" + entry + '}';
}
}
private static final class ReadOnlySnapshotView implements ReadEntryView {
final K key;
final V value;
final Metadata metadata;
private ReadOnlySnapshotView(K key, V value, Metadata metadata) {
this.key = key;
this.value = value;
this.metadata = metadata;
}
@Override
public K key() {
return key;
}
@Override
public V get() throws NoSuchElementException {
if (value == null) throw new NoSuchElementException("No value");
return value;
}
@Override
public Optional find() {
return Optional.ofNullable(value);
}
// TODO: Duplication
@Override
public Optional findMetaParam(Class type) {
if (metadata instanceof MetaParamsInternalMetadata) {
MetaParamsInternalMetadata metaParamsMetadata = (MetaParamsInternalMetadata) metadata;
return metaParamsMetadata.findMetaParam(type);
}
// TODO: Add interoperability support, e.g. able to retrieve lifespan for data stored in Cache via lifespan API
return Optional.empty();
}
@Override
public String toString() {
return "ReadOnlySnapshotView{" +
"key=" + key +
", value=" + value +
", metadata=" + metadata +
'}';
}
}
private static final class EntryBackedWriteOnlyView implements WriteEntryView {
final CacheEntry entry;
private EntryBackedWriteOnlyView(CacheEntry entry) {
this.entry = entry;
}
@Override
public Void set(V value, MetaParam.Writable... metas) {
entry.setValue(value);
entry.setChanged(true);
updateMetaParams(entry, metas);
return null;
}
@Override
public Void remove() {
entry.setRemoved(true);
entry.setChanged(true);
return null;
}
@Override
public String toString() {
return "EntryBackedWriteOnlyView{" + "entry=" + entry + '}';
}
}
private static final class EntryBackedReadWriteView implements ReadWriteEntryView {
final CacheEntry entry;
private EntryBackedReadWriteView(CacheEntry entry) {
this.entry = entry;
}
@Override
public K key() {
return entry.getKey();
}
@Override
public Optional find() {
return entry == null ? Optional.empty() : Optional.ofNullable(entry.getValue());
}
@Override
public Void set(V value, MetaParam.Writable... metas) {
setOnly(value, metas);
return null;
}
private void setOnly(V value, MetaParam.Writable[] metas) {
entry.setValue(value);
entry.setChanged(true);
updateMetaParams(entry, metas);
}
@Override
public Void remove() {
if (!entry.isNull()) {
entry.setRemoved(true);
entry.setChanged(true);
}
return null;
}
@Override
public Optional findMetaParam(Class type) {
Metadata metadata = entry.getMetadata();
if (metadata instanceof MetaParamsInternalMetadata) {
MetaParamsInternalMetadata metaParamsMetadata = (MetaParamsInternalMetadata) metadata;
return metaParamsMetadata.findMetaParam(type);
}
// TODO: Add interoperability support, e.g. able to retrieve lifespan for data stored in Cache via lifespan API
return Optional.empty();
}
@Override
public V get() throws NoSuchElementException {
if (entry == null || entry.getValue() == null)
throw new NoSuchElementException("No value present");
return entry.getValue();
}
@Override
public String toString() {
return "EntryBackedReadWriteView{" + "entry=" + entry + '}';
}
}
private static final class EntryAndPreviousReadWriteView implements ReadWriteEntryView {
final CacheEntry entry;
final V prevValue;
final Metadata prevMetadata;
private EntryAndPreviousReadWriteView(CacheEntry entry, V prevValue, Metadata prevMetadata) {
this.entry = entry;
this.prevValue = prevValue;
this.prevMetadata = prevMetadata;
}
@Override
public K key() {
return entry.getKey();
}
@Override
public Optional find() {
return prevValue == null ? Optional.empty() : Optional.ofNullable(prevValue);
}
@Override
public Void set(V value, MetaParam.Writable... metas) {
setOnly(value, metas);
return null;
}
private void setOnly(V value, MetaParam.Writable[] metas) {
entry.setValue(value);
entry.setChanged(true);
updateMetaParams(entry, metas);
}
@Override
public Void remove() {
if (!entry.isNull()) {
entry.setRemoved(true);
entry.setChanged(true);
}
return null;
}
@Override
public Optional findMetaParam(Class type) {
Metadata metadata = prevMetadata; // Use previous metadata
if (metadata instanceof MetaParamsInternalMetadata) {
MetaParamsInternalMetadata metaParamsMetadata = (MetaParamsInternalMetadata) metadata;
return metaParamsMetadata.findMetaParam(type);
}
// TODO: Add interoperability support, e.g. able to retrieve lifespan for data stored in Cache via lifespan API
return Optional.empty();
}
@Override
public V get() throws NoSuchElementException {
return prevValue;
}
@Override
public String toString() {
return "EntryAndPreviousReadWriteView{" +
"entry=" + entry +
", prevValue=" + prevValue +
", prevMetadata=" + prevMetadata +
'}';
}
}
private static final class NoValueReadOnlyView implements ReadEntryView {
final K key;
public NoValueReadOnlyView(K key) {
this.key = key;
}
@Override
public K key() {
return key;
}
@Override
public V get() throws NoSuchElementException {
throw new NoSuchElementException("No value");
}
@Override
public Optional find() {
return Optional.empty();
}
@Override
public Optional findMetaParam(Class type) {
return Optional.empty();
}
@Override
public String toString() {
return "NoValueReadOnlyView{" + "key=" + key + '}';
}
}
private static final class ReadWriteSnapshotView implements ReadWriteEntryView {
final K key;
final V value;
final Metadata metadata;
public ReadWriteSnapshotView(K key, V value, Metadata metadata) {
this.key = key;
this.value = value;
this.metadata = metadata;
}
@Override
public K key() {
return key;
}
@Override
public V get() throws NoSuchElementException {
if (value == null)
throw new NoSuchElementException("No value present");
return value;
}
@Override
public Optional find() {
return Optional.ofNullable(value);
}
// TODO: Duplication
@Override
public Optional findMetaParam(Class type) {
if (metadata instanceof MetaParamsInternalMetadata) {
MetaParamsInternalMetadata metaParamsMetadata = (MetaParamsInternalMetadata) metadata;
return metaParamsMetadata.findMetaParam(type);
}
// TODO: Add interoperability support, e.g. able to retrieve lifespan for data stored in Cache via lifespan API
return Optional.empty();
}
@Override
public Void set(V value, MetaParam.Writable... metas) {
throw new IllegalStateException(
"A read-write entry view cannot be modified outside the scope of a lambda");
}
@Override
public Void remove() {
throw new IllegalStateException(
"A read-write entry view cannot be modified outside the scope of a lambda");
}
@Override
public String toString() {
return "ReadWriteSnapshotView{" +
"key=" + key +
", value=" + value +
", metadata=" + metadata +
'}';
}
}
private static MetaParams updateMetaParams(CacheEntry entry, MetaParam.Writable[] metas) {
// TODO: Deal with entry instances that are MetaParamsCacheEntry and merge meta params
// e.g. check if meta params exist and if so, merge, but also check for old metadata
// information and merge it individually
if (metas.length != 0) {
MetaParams metaParams = MetaParams.empty();
metaParams.addMany(metas);
entry.setMetadata(MetaParamsInternalMetadata.from(metaParams));
return metaParams;
}
MetaParams empty = MetaParams.empty();
entry.setMetadata(MetaParamsInternalMetadata.from(empty));
return empty;
}
private static MetaParams extractMetaParams(CacheEntry entry) {
// TODO: Deal with entry instances that are MetaParamsCacheEntry and merge meta params
// e.g. check if meta params exist and if so, merge, but also check for old metadata
// information and merge it individually
Metadata metadata = entry.getMetadata();
if (metadata instanceof MetaParamsInternalMetadata) {
MetaParamsInternalMetadata metaParamsMetadata = (MetaParamsInternalMetadata) metadata;
return metaParamsMetadata.params;
}
return MetaParams.empty();
}
// Externalizer class defined outside of externalized class to avoid having
// to making externalized class public, since that would leak internal impl.
public static final class ReadWriteSnapshotViewExternalizer
extends AbstractExternalizer {
@Override
public Integer getId() {
return Ids.READ_WRITE_SNAPSHOT_VIEW;
}
@Override @SuppressWarnings("unchecked")
public Set> getTypeClasses() {
return Util.asSet(ReadWriteSnapshotView.class);
}
@Override
public void writeObject(ObjectOutput output, ReadWriteSnapshotView obj) throws IOException {
output.writeObject(obj.key);
output.writeObject(obj.value);
output.writeObject(obj.metadata);
}
@Override @SuppressWarnings("unchecked")
public ReadWriteSnapshotView readObject(ObjectInput input) throws IOException, ClassNotFoundException {
Object key = input.readObject();
Object value = input.readObject();
Metadata metadata = (Metadata) input.readObject();
return new ReadWriteSnapshotView(key, value, metadata);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy