net.openhft.chronicle.wire.SerializationStrategies Maven / Gradle / Ivy
The newest version!
/*
* Copyright 2016-2020 chronicle.software
*
* https://chronicle.software
*
* 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.wire;
import net.openhft.chronicle.bytes.Bytes;
import net.openhft.chronicle.bytes.CommonMarshallable;
import net.openhft.chronicle.bytes.ReadBytesMarshallable;
import net.openhft.chronicle.core.Jvm;
import net.openhft.chronicle.core.UnsafeMemory;
import net.openhft.chronicle.core.io.IORuntimeException;
import net.openhft.chronicle.core.io.InvalidMarshallableException;
import net.openhft.chronicle.core.pool.EnumCache;
import net.openhft.chronicle.core.util.ObjectUtils;
import net.openhft.chronicle.core.util.ReadResolvable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.Externalizable;
import java.io.IOException;
import java.io.Serializable;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.*;
import static net.openhft.chronicle.wire.BracketType.UNKNOWN;
/**
* Enumerates the available serialization strategies, each implementing the {@link SerializationStrategy} interface.
* These strategies cater to different serialization requirements and support specific object types.
*/
@SuppressWarnings({"rawtypes", "unchecked", "deprecation"})
public enum SerializationStrategies implements SerializationStrategy {
/**
* A serialization strategy for objects implementing the {@link Marshallable} interface.
* This strategy supports both self-describing messages and raw byte data serialization.
*/
MARSHALLABLE {
/**
* Reads an object from the provided input source using a wire format.
* The object can be deserialized either as a self-describing message or as raw byte data,
* based on its type.
*
* @return The populated object.
*/
@NotNull
@Override
public Object readUsing(Class clazz, @NotNull Object o, @NotNull ValueIn in, BracketType bracketType) throws InvalidMarshallableException {
WireIn wireIn = in.wireIn();
if (wireIn.useSelfDescribingMessage((CommonMarshallable) o) && o instanceof ReadMarshallable) {
((ReadMarshallable) o).readMarshallable(wireIn);
} else {
((ReadBytesMarshallable) o).readMarshallable(wireIn.bytes());
}
return o;
}
/**
* Returns the type of object this serialization strategy supports, which is {@link Marshallable}.
*
* @return The {@link Marshallable} class.
*/
@NotNull
@Override
public Class type() {
return Marshallable.class;
}
/**
* Creates a new instance of the specified type.
* If the type represents an interface or an abstract class, {@code null} is returned.
*
* @return A new instance of the provided type or {@code null} if the type is an interface or abstract.
*/
@Nullable
@Override
public Object newInstanceOrNull(@NotNull Class type) {
return type.isInterface() || Modifier.isAbstract(type.getModifiers()) ? null : super.newInstanceOrNull(type);
}
},
/**
* A serialization strategy that supports any object type.
* This strategy infers the object type during deserialization.
*/
ANY_OBJECT {
/**
* Reads an object from the provided input source, inferring its type.
* The type is not explicitly described in the serialized data.
*
* @return The populated object with its type inferred from the input.
*/
@Nullable
@Override
public Object readUsing(Class clazz, Object o, @NotNull ValueIn in, BracketType bracketType) throws InvalidMarshallableException {
return in.objectWithInferredType(o, ANY_NESTED, null);
}
/**
* Returns the most generic type of object this serialization strategy supports, which is {@link Object}.
*
* @return The {@link Object} class.
*/
@NotNull
@Override
public Class type() {
return Object.class;
}
/**
* Indicates that the bracket type for this strategy is unknown.
*
* @return The {@link BracketType#UNKNOWN}.
*/
@NotNull
@Override
public BracketType bracketType() {
return UNKNOWN;
}
},
/**
* A serialization strategy that supports any scalar value.
* Scalar values are typically primitive types or their boxed equivalents.
*/
ANY_SCALAR {
/**
* Reads a scalar object from the provided input source, inferring its type.
*
* @return The populated scalar object with its type inferred from the input.
*/
@Nullable
@Override
public Object readUsing(Class clazz, Object o, @NotNull ValueIn in, BracketType bracketType) throws InvalidMarshallableException {
return in.objectWithInferredType(o, ANY_NESTED, null);
}
/**
* Returns the most generic type of scalar this serialization strategy supports, which is {@link Object}.
*
* @return The {@link Object} class.
*/
@NotNull
@Override
public Class type() {
return Object.class;
}
/**
* Indicates that this strategy does not use any bracketing for serialization.
*
* @return The {@link BracketType#NONE}.
*/
@NotNull
@Override
public BracketType bracketType() {
return BracketType.NONE;
}
},
/**
* A serialization strategy specifically designed for handling enumerations (enums).
*/
ENUM {
/**
* Reads an enum value from the provided input source, represented as text.
*
* @return The textual representation of the enum value.
*/
@Nullable
@Override
public Object readUsing(Class clazz, Object o, @NotNull ValueIn in, BracketType bracketType) {
return in.text();
}
/**
* Returns the type of object this serialization strategy supports, which is {@link Enum}.
*
* @return The {@link Enum} class.
*/
@NotNull
@Override
public Class type() {
return Enum.class;
}
/**
* Indicates that this strategy does not use any bracketing for serialization.
*
* @return The {@link BracketType#NONE}.
*/
@NotNull
@Override
public BracketType bracketType() {
return BracketType.NONE;
}
},
/**
* A serialization strategy designed for handling dynamic enumerations (enums).
* Dynamic enums are enums whose values can be altered or enhanced at runtime.
* This strategy incorporates custom handling to ensure proper deserialization
* of dynamic enums from the input source.
*/
DYNAMIC_ENUM {
// Reflective field access to the ordinal of the Enum class
private Field ordinal = Jvm.getField(Enum.class, "ordinal");
/**
* Reads a dynamic enum value from the provided input source.
* This method accounts for multiple input representations,
* such as direct textual names or custom serialized formats
* for more complex dynamic enums.
*
* @return The deserialized dynamic enum object or its textual representation.
*/
@Nullable
@Override
public Object readUsing(Class clazz, Object o, @NotNull ValueIn in, BracketType bracketType) throws InvalidMarshallableException {
if (bracketType != BracketType.MAP || !(o instanceof ReadMarshallable)) {
String text = in.text();
if (o != null) {
EnumCache> cache = EnumCache.of(o.getClass());
Object ret = cache.valueOf(text);
if (ret == null)
throw new IORuntimeException("No enum value '" + text + "' defined for " + o.getClass());
return ret;
}
return text;
}
((ReadMarshallable) o).readMarshallable(in.wireIn());
return o;
}
/**
* Returns the type of object this serialization strategy supports, which is {@link Enum}.
*
* @return The {@link Enum} class.
*/
@NotNull
@Override
public Class type() {
return Enum.class;
}
/**
* Indicates that the bracket type used for serialization is unknown.
*
* @return The {@link BracketType#UNKNOWN}.
*/
@NotNull
@Override
public BracketType bracketType() {
return UNKNOWN;
}
/**
* Constructs a new instance of a dynamic enum.
* The constructed instance is left in an unset state, where the name is
* marked as "[unset]" and the ordinal is set to -1.
*
* @return The constructed dynamic enum instance.
*/
@Override
public Object newInstanceOrNull(Class type) {
try {
DynamicEnum o = (DynamicEnum) UnsafeMemory.INSTANCE.allocateInstance(type);
o.setField("name", "[unset]");
if (o instanceof Enum)
ordinal.set(o, -1);
return o;
} catch (Exception e) {
throw new IORuntimeException(e);
}
}
},
/**
* A serialization strategy designed for handling nested objects.
* This strategy reads nested objects without explicitly knowing
* their exact type, treating them as generic objects and performing
* a generic deserialization.
*/
ANY_NESTED {
/**
* Reads the nested object from the provided input source.
* If the input is null, it returns null. Otherwise, it
* deserializes the object and returns the constructed instance.
*
* @return The deserialized nested object.
*/
@Override
public Object readUsing(Class clazz, Object o, @NotNull ValueIn in, BracketType bracketType) throws InvalidMarshallableException {
if (in.isNull()) {
return null;
}
if (o == null)
o = ObjectUtils.newInstance(clazz);
Wires.readMarshallable(clazz, o, in.wireIn(), true);
return o;
}
/**
* Returns the type of object this serialization strategy supports, which is {@link Object}.
*
* @return The {@link Object} class.
*/
@NotNull
@Override
public Class type() {
return Object.class;
}
/**
* Indicates that the bracket type used for serialization is unknown.
*
* @return The {@link BracketType#UNKNOWN}.
*/
@Override
public @NotNull BracketType bracketType() {
return UNKNOWN;
}
},
/**
* A serialization strategy specifically designed for handling
* {@link Demarshallable} objects. {@link Demarshallable} represents
* an object that can be deserialized from a wire format.
*/
DEMARSHALLABLE {
/**
* Reads the {@link Demarshallable} object from the provided input source.
* This method has logic to handle multiple formats of input including
* wrapped objects and direct serialized formats.
*
* @return The deserialized {@link Demarshallable} object or wrapper.
*/
@NotNull
@Override
public Object readUsing(Class clazz, Object using, @NotNull ValueIn in, BracketType bracketType) throws InvalidMarshallableException {
if (using instanceof DemarshallableWrapper) {
@NotNull final DemarshallableWrapper wrapper = (DemarshallableWrapper) using;
wrapper.demarshallable = Demarshallable.newInstance(wrapper.type, in.wireIn());
return wrapper;
} else if (using instanceof ReadMarshallable) {
return in.object(using, Object.class);
} else {
return Demarshallable.newInstance((Class) using.getClass(), in.wireIn());
}
}
/**
* Returns the type of object this serialization strategy supports, which is {@link Demarshallable}.
*
* @return The {@link Demarshallable} class.
*/
@NotNull
@Override
public Class type() {
return Demarshallable.class;
}
/**
* Constructs a new instance of a {@link Demarshallable} wrapped in a {@link DemarshallableWrapper}.
*
* @return The constructed {@link DemarshallableWrapper}.
*/
@NotNull
@Override
public Object newInstanceOrNull(@NotNull Class type) {
return new DemarshallableWrapper(type);
}
},
/**
* A serialization strategy for handling objects that implement the
* {@link java.io.Serializable} interface. This strategy checks if the object
* is also an instance of {@link Externalizable}, and if so, uses the
* {@link #EXTERNALIZABLE} strategy. Otherwise, it defaults to the
* {@link #ANY_OBJECT} strategy.
*/
SERIALIZABLE {
/**
* Reads the {@link Serializable} object from the provided input source.
* Delegates the deserialization to the appropriate strategy based on
* whether the object is an instance of {@link Externalizable}.
*
* @return The deserialized {@link Serializable} object.
*/
@Override
public Object readUsing(Class clazz, Object o, ValueIn in, BracketType bracketType) throws InvalidMarshallableException {
SerializationStrategies strategies = o instanceof Externalizable ? EXTERNALIZABLE : ANY_OBJECT;
strategies.readUsing(clazz, o, in, bracketType);
return o;
}
/**
* Returns the type of object this serialization strategy supports,
* which is {@link Serializable}.
*
* @return The {@link Serializable} class.
*/
@NotNull
@Override
public Class type() {
return Serializable.class;
}
},
/**
* A serialization strategy specifically designed for handling
* {@link Externalizable} objects. Externalizable objects provide their
* own custom serialization mechanism that this strategy leverages.
*/
EXTERNALIZABLE {
/**
* Reads the {@link Externalizable} object from the provided input source
* using the object's custom serialization logic.
*
* @return The deserialized {@link Externalizable} object.
*/
@NotNull
@Override
public Object readUsing(Class clazz, @NotNull Object o, @NotNull ValueIn in, BracketType bracketType) {
try {
((Externalizable) o).readExternal(in.wireIn().objectInput());
} catch (@NotNull IOException | ClassNotFoundException e) {
throw new IORuntimeException(e);
}
return o;
}
/**
* Returns the type of object this serialization strategy supports,
* which is {@link Externalizable}.
*
* @return The {@link Externalizable} class.
*/
@NotNull
@Override
public Class type() {
return Externalizable.class;
}
/**
* Indicates that the bracket type used for serialization is SEQ.
*
* @return The {@link BracketType#SEQ}.
*/
@NotNull
@Override
public BracketType bracketType() {
return BracketType.SEQ;
}
},
/**
* A serialization strategy for handling objects that implement the
* {@link java.util.Map} interface. This strategy deserializes a sequence
* of key-value pairs into a Map instance.
*/
MAP {
/**
* Reads the {@link Map} object from the provided input source, mapping
* each key-value pair in the sequence.
*
* @return The deserialized {@link Map} object.
*/
@Override
public Object readUsing(Class clazz, Object o, @NotNull ValueIn in, BracketType bracketType) throws InvalidMarshallableException {
@NotNull Map
© 2015 - 2024 Weber Informatics LLC | Privacy Policy