org.infinispan.encoding.DataConversion Maven / Gradle / Ivy
package org.infinispan.encoding;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.Objects;
import java.util.Set;
import org.infinispan.commons.dataconversion.ByteArrayWrapper;
import org.infinispan.commons.dataconversion.Encoder;
import org.infinispan.commons.dataconversion.EncoderIds;
import org.infinispan.commons.dataconversion.EncodingException;
import org.infinispan.commons.dataconversion.IdentityEncoder;
import org.infinispan.commons.dataconversion.IdentityWrapper;
import org.infinispan.commons.dataconversion.MediaType;
import org.infinispan.commons.dataconversion.Transcoder;
import org.infinispan.commons.dataconversion.Wrapper;
import org.infinispan.commons.dataconversion.WrapperIds;
import org.infinispan.commons.marshall.AbstractExternalizer;
import org.infinispan.commons.marshall.Ids;
import org.infinispan.commons.util.Util;
import org.infinispan.encoding.impl.StorageConfigurationManager;
import org.infinispan.factories.ComponentRegistry;
import org.infinispan.factories.annotations.Inject;
import org.infinispan.factories.scopes.Scope;
import org.infinispan.factories.scopes.Scopes;
import org.infinispan.marshall.core.EncoderRegistry;
/**
* Handle conversions for Keys or values.
*
* @since 9.2
*/
@Scope(Scopes.NONE)
public final class DataConversion {
/**
* @deprecated Since 11.0. To be removed in 14.0, with no replacement.
*/
@Deprecated(forRemoval=true, since = "11.0")
public static final DataConversion DEFAULT_KEY = new DataConversion(IdentityEncoder.INSTANCE, ByteArrayWrapper.INSTANCE, true);
/**
* @deprecated Since 11.0. To be removed in 14.0, with no replacement.
*/
@Deprecated(forRemoval=true, since = "11.0")
public static final DataConversion DEFAULT_VALUE = new DataConversion(IdentityEncoder.INSTANCE, ByteArrayWrapper.INSTANCE, false);
/**
* @deprecated Since 11.0. To be removed in 14.0. For internal use only.
*/
@Deprecated(forRemoval=true, since = "11.0")
public static final DataConversion IDENTITY_KEY = new DataConversion(IdentityEncoder.INSTANCE, IdentityWrapper.INSTANCE, true);
/**
* @deprecated Since 11.0. To be removed in 14.0. For internal use only.
*/
@Deprecated(forRemoval=true, since = "11.0")
public static final DataConversion IDENTITY_VALUE = new DataConversion(IdentityEncoder.INSTANCE, IdentityWrapper.INSTANCE, false);
// On the origin node the conversion is initialized with the encoder/wrapper classes, on remote nodes with the ids
private final transient Class extends Encoder> encoderClass;
// TODO Make final after removing overrideWrapper()
private transient Class extends Wrapper> wrapperClass;
private final short encoderId;
private final byte wrapperId;
private final MediaType requestMediaType;
private final boolean isKey;
private transient MediaType storageMediaType;
private transient Encoder encoder;
private transient Wrapper customWrapper;
private transient Transcoder transcoder;
private transient EncoderRegistry encoderRegistry;
private transient StorageConfigurationManager storageConfigurationManager;
private DataConversion(Class extends Encoder> encoderClass, Class extends Wrapper> wrapperClass,
MediaType requestMediaType, boolean isKey) {
this.encoderClass = encoderClass;
this.wrapperClass = wrapperClass;
this.requestMediaType = requestMediaType;
this.isKey = isKey;
this.encoderId = EncoderIds.NO_ENCODER;
this.wrapperId = WrapperIds.NO_WRAPPER;
}
/**
* Used for de-serialization
*/
private DataConversion(Short encoderId, Byte wrapperId, MediaType requestMediaType, boolean isKey) {
this.encoderId = encoderId;
this.wrapperId = wrapperId;
this.requestMediaType = requestMediaType;
this.isKey = isKey;
this.encoderClass = null;
this.wrapperClass = null;
}
private DataConversion(Encoder encoder, Wrapper wrapper, boolean isKey) {
this.encoder = encoder;
this.customWrapper = wrapper;
this.encoderClass = encoder.getClass();
this.wrapperClass = wrapper.getClass();
this.isKey = isKey;
this.storageMediaType = MediaType.APPLICATION_OBJECT;
this.requestMediaType = MediaType.APPLICATION_OBJECT;
encoderId = EncoderIds.NO_ENCODER;
wrapperId = WrapperIds.NO_WRAPPER;
}
public DataConversion withRequestMediaType(MediaType requestMediaType) {
if (Objects.equals(this.requestMediaType, requestMediaType)) return this;
return new DataConversion(this.encoderClass, this.wrapperClass, requestMediaType, this.isKey);
}
/**
* @deprecated Since 12.1, to be removed in a future version.
*/
@Deprecated(forRemoval=true, since = "12.1")
public DataConversion withEncoding(Class extends Encoder> encoderClass) {
if (this.encoderClass == encoderClass) return this;
return new DataConversion(encoderClass, this.wrapperClass, this.requestMediaType, this.isKey);
}
/**
* @deprecated Since 11.0. To be removed in 14.0, with no replacement.
*/
@Deprecated(forRemoval=true, since = "11.0")
public DataConversion withWrapping(Class extends Wrapper> wrapperClass) {
if (this.wrapperClass == wrapperClass) return this;
return new DataConversion(this.encoderClass, wrapperClass, this.requestMediaType, this.isKey);
}
/**
* @deprecated Since 11.0, will be removed with no replacement
*/
@Deprecated(forRemoval=true, since = "11.0")
public void overrideWrapper(Class extends Wrapper> newWrapper, ComponentRegistry cr) {
this.customWrapper = null;
this.wrapperClass = newWrapper;
cr.wireDependencies(this);
}
/**
* @deprecated Since 11.0, with no replacement.
*/
@Deprecated(forRemoval=true, since = "11.0")
public boolean isConversionSupported(MediaType mediaType) {
return storageMediaType == null || encoderRegistry.isConversionSupported(storageMediaType, mediaType);
}
/**
* @deprecated Since 11.0, with no replacement.
*/
@Deprecated(forRemoval=true, since = "11.0")
public Object convert(Object o, MediaType from, MediaType to) {
if (o == null) return null;
if (encoderRegistry == null) return o;
Transcoder transcoder = encoderRegistry.getTranscoder(from, to);
return transcoder.transcode(o, from, to);
}
/**
* @deprecated Since 11.0, with no replacement.
*/
@Deprecated(forRemoval=true, since = "11.0")
public Object convertToRequestFormat(Object o, MediaType contentType) {
if (o == null) return null;
if (requestMediaType == null) return fromStorage(o);
Transcoder transcoder = encoderRegistry.getTranscoder(contentType, requestMediaType);
return transcoder.transcode(o, contentType, requestMediaType);
}
@Inject
void injectDependencies(StorageConfigurationManager storageConfigurationManager, EncoderRegistry encoderRegistry) {
if (this.encoder != null && this.customWrapper != null) {
// This must be one of the static encoders, we can't inject any component in it
return;
}
this.storageMediaType = storageConfigurationManager.getStorageMediaType(isKey);
this.encoderRegistry = encoderRegistry;
this.storageConfigurationManager = storageConfigurationManager;
this.customWrapper = encoderRegistry.getWrapper(wrapperClass, wrapperId);
this.lookupEncoder();
this.lookupTranscoder();
}
private void lookupEncoder() {
boolean isEncodingEmpty = encoderClass == null && encoderId == EncoderIds.NO_ENCODER;
Class extends Encoder> actualEncoderClass = isEncodingEmpty ? IdentityEncoder.class : encoderClass;
this.encoder = encoderRegistry.getEncoder(actualEncoderClass, encoderId);
}
private void lookupTranscoder() {
boolean needsTranscoding = storageMediaType != null && requestMediaType != null && !requestMediaType.matchesAll() && !requestMediaType.equals(storageMediaType);
if (needsTranscoding) {
Transcoder directTranscoder = null;
if (encoder.getStorageFormat() != null) {
try {
directTranscoder = encoderRegistry.getTranscoder(requestMediaType, encoder.getStorageFormat());
} catch (EncodingException ignored) {
}
}
if (directTranscoder != null) {
if (encoder.getStorageFormat().equals(MediaType.APPLICATION_OBJECT)) {
encoder = IdentityEncoder.INSTANCE;
}
transcoder = directTranscoder;
} else {
transcoder = encoderRegistry.getTranscoder(requestMediaType, storageMediaType);
}
}
}
public Object fromStorage(Object stored) {
if (stored == null) return null;
Object fromStorage = encoder.fromStorage(getWrapper().unwrap(stored));
return transcoder == null ? fromStorage : transcoder.transcode(fromStorage, storageMediaType, requestMediaType);
}
public Object toStorage(Object toStore) {
if (toStore == null) return null;
toStore = transcoder == null ? toStore : transcoder.transcode(toStore, requestMediaType, storageMediaType);
return getWrapper().wrap(encoder.toStorage(toStore));
}
/**
* Convert the stored object in a format suitable to be indexed.
*/
public Object extractIndexable(Object stored, boolean javaEmbeddedEntities) {
if (stored == null) return null;
// Keys are indexed as stored, without the wrapper
Wrapper wrapper = getWrapper();
if (isKey) return wrapper.unwrap(stored);
if (wrapper.isFilterable() && !javaEmbeddedEntities) {
// If the value wrapper is indexable, return the already wrapped value or wrap it otherwise
return stored.getClass() == wrapperClass ? stored : wrapper.wrap(stored);
}
// Otherwise convert to the request format
Object unencoded = encoder.fromStorage(wrapper.unwrap(stored));
return transcoder == null ? unencoded : transcoder.transcode(unencoded, storageMediaType, requestMediaType);
}
public MediaType getRequestMediaType() {
return requestMediaType;
}
public MediaType getStorageMediaType() {
return storageMediaType;
}
public Encoder getEncoder() {
return encoder;
}
/**
* @deprecated Since 11.0. To be removed in 14.0, with no replacement.
*/
@Deprecated(forRemoval=true, since = "11.0")
public Wrapper getWrapper() {
if (customWrapper != null)
return customWrapper;
return storageConfigurationManager.getWrapper(isKey);
}
public Class extends Encoder> getEncoderClass() {
return encoderClass;
}
/**
* @deprecated Since 11.0. To be removed in 14.0, with no replacement.
*/
@Deprecated(forRemoval=true, since = "11.0")
public Class extends Wrapper> getWrapperClass() {
return wrapperClass;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
DataConversion that = (DataConversion) o;
return isKey == that.isKey &&
Objects.equals(encoder, that.encoder) &&
Objects.equals(customWrapper, that.customWrapper) &&
Objects.equals(transcoder, that.transcoder) &&
Objects.equals(requestMediaType, that.requestMediaType);
}
@Override
public String toString() {
return "DataConversion{" +
"encoderClass=" + encoderClass +
", wrapperClass=" + wrapperClass +
", requestMediaType=" + requestMediaType +
", storageMediaType=" + storageMediaType +
", encoderId=" + encoderId +
", wrapperId=" + wrapperId +
", encoder=" + encoder +
", wrapper=" + customWrapper +
", isKey=" + isKey +
", transcoder=" + transcoder +
'}';
}
@Override
public int hashCode() {
return Objects.hash(encoderClass, wrapperClass, requestMediaType, isKey);
}
/**
* @return A new instance with an {@link IdentityEncoder} and request type {@link MediaType#APPLICATION_OBJECT}.
* @since 11.0
*/
public static DataConversion newKeyDataConversion() {
return new DataConversion(IdentityEncoder.class, null, MediaType.APPLICATION_OBJECT, true);
}
/**
* @return A new instance with an {@link IdentityEncoder} and request type {@link MediaType#APPLICATION_OBJECT}.
* @since 11.0
*/
public static DataConversion newValueDataConversion() {
return new DataConversion(IdentityEncoder.class, null, MediaType.APPLICATION_OBJECT, false);
}
/**
* @deprecated Since 11.0. To be removed in 14.0. Replaced by {@link #newKeyDataConversion()}.
*/
@Deprecated(forRemoval=true, since = "11.0")
public static DataConversion newKeyDataConversion(Class extends Encoder> encoderClass,
Class extends Wrapper> wrapperClass) {
return new DataConversion(encoderClass, wrapperClass, MediaType.APPLICATION_OBJECT, true);
}
/**
* @deprecated Since 11.0. To be removed in 14.0. Replaced by {@link #newValueDataConversion()}.
*/
@Deprecated(forRemoval=true, since = "11.0")
public static DataConversion newValueDataConversion(Class extends Encoder> encoderClass,
Class extends Wrapper> wrapperClass) {
return new DataConversion(encoderClass, wrapperClass, MediaType.APPLICATION_OBJECT, false);
}
public static void writeTo(ObjectOutput output, DataConversion dataConversion) throws IOException {
byte flags = 0;
if (dataConversion.isKey) flags = (byte) (flags | 2);
output.writeByte(flags);
output.writeShort(dataConversion.encoder.id());
if (dataConversion.customWrapper != null) {
output.writeByte(dataConversion.customWrapper.id());
} else {
output.writeByte(WrapperIds.NO_WRAPPER);
}
output.writeObject(dataConversion.requestMediaType);
}
public static DataConversion readFrom(ObjectInput input) throws IOException, ClassNotFoundException {
byte flags = input.readByte();
boolean isKey = ((flags & 2) == 2);
short encoderId = input.readShort();
byte wrapperId = input.readByte();
MediaType requestMediaType = (MediaType) input.readObject();
return new DataConversion(encoderId, wrapperId, requestMediaType, isKey);
}
public static class Externalizer extends AbstractExternalizer {
@Override
public Set> getTypeClasses() {
return Util.asSet(DataConversion.class);
}
@Override
public void writeObject(ObjectOutput output, DataConversion dataConversion) throws IOException {
writeTo(output, dataConversion);
}
@Override
public DataConversion readObject(ObjectInput input) throws IOException, ClassNotFoundException {
return readFrom(input);
}
@Override
public Integer getId() {
return Ids.DATA_CONVERSION;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy