DataMap.java
package space.sunqian.fs.data;
import space.sunqian.annotation.Nonnull;
import space.sunqian.annotation.Nullable;
import space.sunqian.fs.Fs;
import space.sunqian.fs.base.option.Option;
import space.sunqian.fs.object.convert.ObjectConverter;
import space.sunqian.fs.reflect.TypeRef;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* This interface extends the {@link Map} interface with signature {@code Map<String, Object>}, provides methods to get
* and convert values to common types, such as {@link #getString(String)}, {@link #getInt(String)}, etc. The original
* methods of {@link Map} are also supported and without any conversion.
*
* @author sunqian
*/
public interface DataMap extends Map<String, Object> {
/**
* Returns a new {@link DataMap} based on the {@link LinkedHashMap} with the
* {@link ObjectConverter#defaultConverter()} to use for conversion values and empty options.
*
* @return the wrapped {@link DataMap}
*/
static @Nonnull DataMap newMap() {
return wrap(new LinkedHashMap<>());
}
/**
* Wraps the given {@link Map} to a {@link DataMap} with the {@link ObjectConverter#defaultConverter()} to use for
* conversion values and empty options.
*
* @param map the {@link Map} to wrap
* @return the wrapped {@link DataMap}
*/
static @Nonnull DataMap wrap(@Nonnull Map<String, Object> map) {
return wrap(map, ObjectConverter.defaultConverter(), Option.emptyOptions());
}
/**
* Wraps the given {@link Map} to a {@link DataMap} with the given {@link ObjectConverter} and default options.
*
* @param map the {@link Map} to wrap
* @param converter the {@link ObjectConverter} to use for conversion values
* @param defaultOptions the default options to use for conversion
* @return the wrapped {@link DataMap}
*/
static @Nonnull DataMap wrap(
@Nonnull Map<String, Object> map,
@Nonnull ObjectConverter converter,
@Nonnull Option<?, ?> @Nonnull ... defaultOptions
) {
return new DataMapImpl(map, converter, defaultOptions);
}
/**
* Gets the value for the specified key, then converts it to the type of the default value. If the key is not found,
* returns {@code defaultValue}.
* <p>
* Note that this method uses {@link Object#getClass()} to get the type of the default value, if the default value
* is {@code null}, the type to convert the value to will be {@link Object}.
*
* @param key the specified key
* @param defaultValue the default value
* @return the converted value of the specified key, or {@code defaultValue} if the key is not found
*/
default <T> T get(@Nonnull String key, T defaultValue) throws DataException {
return get(key, defaultValue == null ? Object.class : defaultValue.getClass(), defaultValue);
}
/**
* Gets the value for the specified key, then converts it to the specified type. If the key is not found, returns
* {@code defaultValue}.
* <p>
* Note the specified type must be the type of the default value.
*
* @param key the specified key
* @param type the type to convert the value to
* @param defaultValue the default value
* @return the converted value of the specified key, or {@code defaultValue} if the key is not found
*/
<T> T get(@Nonnull String key, @Nonnull Type type, T defaultValue) throws DataException;
/**
* Gets the value for the specified key, then converts it to the String type. If the key is not found, returns
* {@code null}.
*
* @param key the specified key
* @return the converted string value of the specified key, or {@code null} if the key is not found
* @throws DataException if an error occurs during the search or conversion
*/
default @Nullable String getString(@Nonnull String key) throws DataException {
return getString(key, null);
}
/**
* Gets the value for the specified key, then converts it to the String type. If the key is not found, returns
* {@code defaultValue}.
*
* @param key the specified key
* @param defaultValue the default value
* @return the converted string value of the specified key, or {@code defaultValue} if the key is not found
* @throws DataException if an error occurs during the search or conversion
*/
default String getString(@Nonnull String key, String defaultValue) throws DataException {
return get(key, String.class, defaultValue);
}
/**
* Gets the value for the specified key, then converts it to the int type. If the key is not found, returns
* {@code 0}.
*
* @param key the specified key
* @return the converted int value of the specified key, or {@code 0} if the key is not found
* @throws DataException if an error occurs during the search or conversion
*/
default int getInt(@Nonnull String key) throws DataException {
return getInt(key, 0);
}
/**
* Gets the value for the specified key, then converts it to the int type. If the key is not found, returns
* {@code defaultValue}.
*
* @param key the specified key
* @param defaultValue the default value
* @return the converted int value of the specified key, or {@code defaultValue} if the key is not found
* @throws DataException if an error occurs during the search or conversion
*/
default int getInt(@Nonnull String key, int defaultValue) throws DataException {
return get(key, int.class, defaultValue);
}
/**
* Gets the value for the specified key, then converts it to the long type. If the key is not found, returns
* {@code 0}.
*
* @param key the specified key
* @return the converted long value of the specified key, or {@code 0} if the key is not found
* @throws DataException if an error occurs during the search or conversion
*/
default long getLong(@Nonnull String key) throws DataException {
return getLong(key, 0L);
}
/**
* Gets the value for the specified key, then converts it to the long type. If the key is not found, returns
* {@code defaultValue}.
*
* @param key the specified key
* @param defaultValue the default value
* @return the converted long value of the specified key, or {@code defaultValue} if the key is not found
* @throws DataException if an error occurs during the search or conversion
*/
default long getLong(@Nonnull String key, long defaultValue) throws DataException {
return get(key, long.class, defaultValue);
}
/**
* Gets the value for the specified key, then converts it to the float type. If the key is not found, returns
* {@code 0.0f}.
*
* @param key the specified key
* @return the converted float value of the specified key, or {@code 0.0f} if the key is not found
* @throws DataException if an error occurs during the search or conversion
*/
default float getFloat(@Nonnull String key) throws DataException {
return getFloat(key, 0.0f);
}
/**
* Gets the value for the specified key, then converts it to the float type. If the key is not found, returns
* {@code defaultValue}.
*
* @param key the specified key
* @param defaultValue the default value
* @return the converted float value of the specified key, or {@code defaultValue} if the key is not found
* @throws DataException if an error occurs during the search or conversion
*/
default float getFloat(@Nonnull String key, float defaultValue) throws DataException {
return get(key, float.class, defaultValue);
}
/**
* Gets the value for the specified key, then converts it to the double type. If the key is not found, returns
* {@code 0.0}.
*
* @param key the specified key
* @return the converted double value of the specified key, or {@code 0.0} if the key is not found
* @throws DataException if an error occurs during the search or conversion
*/
default double getDouble(@Nonnull String key) throws DataException {
return getDouble(key, 0.0);
}
/**
* Gets the value for the specified key, then converts it to the double type. If the key is not found, returns
* {@code defaultValue}.
*
* @param key the specified key
* @param defaultValue the default value
* @return the converted double value of the specified key, or {@code defaultValue} if the key is not found
* @throws DataException if an error occurs during the search or conversion
*/
default double getDouble(@Nonnull String key, double defaultValue) throws DataException {
return get(key, double.class, defaultValue);
}
/**
* Gets the value for the specified key, then converts it to the {@link BigDecimal} type. If the key is not found,
* returns {@code null}.
*
* @param key the specified key
* @return the converted BigDecimal value of the specified key, or {@code null} if the key is not found
* @throws DataException if an error occurs during the search or conversion
*/
default @Nullable BigDecimal getBigDecimal(@Nonnull String key) throws DataException {
return getBigDecimal(key, null);
}
/**
* Gets the value for the specified key, then converts it to the {@link BigDecimal} type. If the key is not found,
* returns {@code defaultValue}.
*
* @param key the specified key
* @param defaultValue the default value
* @return the converted BigDecimal value of the specified key, or {@code defaultValue} if the key is not found
* @throws DataException if an error occurs during the search or conversion
*/
default @Nullable BigDecimal getBigDecimal(
@Nonnull String key, @Nullable BigDecimal defaultValue
) throws DataException {
return get(key, BigDecimal.class, defaultValue);
}
/**
* Converts this {@link DataMap} to a new object of the specified class.
*
* @param cls the specified class
* @param <T> the type of the object to be returned`
* @return a new object of the specified class
* @throws DataException if an error occurs during the conversion
*/
default <T> @Nonnull T toObject(@Nonnull Class<T> cls) throws DataException {
return Fs.as(toObject((Type) cls));
}
/**
* Converts this {@link DataMap} to a new object of the specified class.
*
* @param typeRef the reference of the specified class
* @param <T> the type of the object to be returned`
* @return a new object of the specified class
* @throws DataException if an error occurs during the conversion
*/
default <T> @Nonnull T toObject(@Nonnull TypeRef<T> typeRef) throws DataException {
return Fs.as(toObject(typeRef.type()));
}
/**
* Converts this {@link DataMap} to a new object of the specified type.
*
* @param type the specified type
* @return a new object of the specified type
* @throws DataException if an error occurs during the conversion
*/
@Nonnull
Object toObject(@Nonnull Type type) throws DataException;
/**
* Returns {@code true} if the given object is an instance of {@link DataMap } and their contents are equal,
* {@code false} otherwise.
*
* @param o object to be compared for equality with this
* @return {@code true} if the given object is an instance of {@link DataMap } and their contents are equal,
* {@code false} otherwise.
*/
@Override
boolean equals(@Nullable Object o);
/**
* Returns {@code true} if the content of this {@link DataMap } are equal to the content of the given map,
* {@code false} otherwise.
*
* @param o the given map to be compared with this
* @return {@code true} if the content of this {@link DataMap } are equal to the content of the given map,
* {@code false} otherwise.
*/
boolean contentEquals(@Nullable Map<@Nonnull String, ?> o);
}