DataList.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.TypeKit;
import space.sunqian.fs.reflect.TypeRef;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
/**
* This interface extends the {@link List} interface with signature {@code List<Object>}, provides methods to get and
* convert values to common types, such as {@link #getString(int)}, {@link #getInt(int)}, etc. The original methods of
* {@link List} are also supported and without any conversion.
*
* @author sunqian
*/
public interface DataList extends List<Object> {
/**
* Returns a new {@link DataList} based on the {@link ArrayList} with the {@link ObjectConverter#defaultConverter()}
* to use for conversion values and empty options.
*
* @return the wrapped {@link DataList}
*/
static @Nonnull DataList newList() {
return wrap(new ArrayList<>());
}
/**
* Wraps the given {@link List} to a {@link DataList} with the {@link ObjectConverter#defaultConverter()} to use for
* conversion values and empty options.
*
* @param list the {@link List} to wrap
* @return the wrapped {@link DataList}
*/
static @Nonnull DataList wrap(@Nonnull List<?> list) {
return wrap(list, ObjectConverter.defaultConverter(), Option.emptyOptions());
}
/**
* Wraps the given {@link List} to a {@link DataList} with the given {@link ObjectConverter} and default options.
*
* @param list the {@link List} 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 DataList}
*/
static @Nonnull DataList wrap(
@Nonnull List<?> list,
@Nonnull ObjectConverter converter,
@Nonnull Option<?, ?> @Nonnull ... defaultOptions
) {
return new DataListImpl(list, converter, defaultOptions);
}
/**
* Gets the value at the specified index, then converts it to the type of the default value. If the key is out of
* bounds, 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 index the specified index
* @param defaultValue the default value
* @return the converted value of the specified index, or {@code defaultValue} if the key is out of bounds
*/
default <T> T get(int index, T defaultValue) throws DataException {
return get(index, defaultValue == null ? Object.class : defaultValue.getClass(), defaultValue);
}
/**
* Gets the value for the specified index, then converts it to the specified type. If the key is out of bounds,
* returns {@code defaultValue}.
* <p>
* Note the specified type must be the type of the default value.
*
* @param index the specified index
* @param type the type to convert the value to
* @param defaultValue the default value
* @return the converted value of the specified index, or {@code defaultValue} if the key is out of bounds
*/
<T> T get(int index, @Nonnull Type type, T defaultValue) throws DataException;
/**
* Gets the value for the specified index, then converts it to the String type. If the key is out of bounds, returns
* {@code null}.
*
* @param index the specified index
* @return the converted string value of the specified index, or {@code null} if the key is out of bounds
* @throws DataException if an error occurs during the search or conversion
*/
default @Nullable String getString(int index) throws DataException {
return getString(index, null);
}
/**
* Gets the value for the specified index, then converts it to the String type. If the key is out of bounds, returns
* {@code defaultValue}.
*
* @param index the specified index
* @param defaultValue the default value
* @return the converted string value of the specified index, or {@code defaultValue} if the key is out of bounds
* @throws DataException if an error occurs during the search or conversion
*/
default String getString(int index, String defaultValue) throws DataException {
return get(index, String.class, defaultValue);
}
/**
* Gets the value for the specified index, then converts it to the int type. If the key is out of bounds, returns
* {@code 0}.
*
* @param index the specified index
* @return the converted int value of the specified index, or {@code 0} if the key is out of bounds
* @throws DataException if an error occurs during the search or conversion
*/
default int getInt(int index) throws DataException {
return getInt(index, 0);
}
/**
* Gets the value for the specified index, then converts it to the int type. If the key is out of bounds, returns
* {@code defaultValue}.
*
* @param index the specified index
* @param defaultValue the default value
* @return the converted int value of the specified index, or {@code defaultValue} if the key is out of bounds
* @throws DataException if an error occurs during the search or conversion
*/
default int getInt(int index, int defaultValue) throws DataException {
return get(index, int.class, defaultValue);
}
/**
* Gets the value for the specified index, then converts it to the long type. If the key is out of bounds, returns
* {@code 0}.
*
* @param index the specified index
* @return the converted long value of the specified index, or {@code 0} if the key is out of bounds
* @throws DataException if an error occurs during the search or conversion
*/
default long getLong(int index) throws DataException {
return getLong(index, 0L);
}
/**
* Gets the value for the specified index, then converts it to the long type. If the key is out of bounds, returns
* {@code defaultValue}.
*
* @param index the specified index
* @param defaultValue the default value
* @return the converted long value of the specified index, or {@code defaultValue} if the key is out of bounds
* @throws DataException if an error occurs during the search or conversion
*/
default long getLong(int index, long defaultValue) throws DataException {
return get(index, long.class, defaultValue);
}
/**
* Gets the value for the specified index, then converts it to the float type. If the key is out of bounds, returns
* {@code 0.0f}.
*
* @param index the specified index
* @return the converted float value of the specified index, or {@code 0.0f} if the key is out of bounds
* @throws DataException if an error occurs during the search or conversion
*/
default float getFloat(int index) throws DataException {
return getFloat(index, 0.0f);
}
/**
* Gets the value for the specified index, then converts it to the float type. If the key is out of bounds, returns
* {@code defaultValue}.
*
* @param index the specified index
* @param defaultValue the default value
* @return the converted float value of the specified index, or {@code defaultValue} if the key is out of bounds
* @throws DataException if an error occurs during the search or conversion
*/
default float getFloat(int index, float defaultValue) throws DataException {
return get(index, float.class, defaultValue);
}
/**
* Gets the value for the specified index, then converts it to the double type. If the key is out of bounds, returns
* {@code 0.0}.
*
* @param index the specified index
* @return the converted double value of the specified index, or {@code 0.0} if the key is out of bounds
* @throws DataException if an error occurs during the search or conversion
*/
default double getDouble(int index) throws DataException {
return getDouble(index, 0.0);
}
/**
* Gets the value for the specified index, then converts it to the double type. If the key is out of bounds, returns
* {@code defaultValue}.
*
* @param index the specified index
* @param defaultValue the default value
* @return the converted double value of the specified index, or {@code defaultValue} if the key is out of bounds
* @throws DataException if an error occurs during the search or conversion
*/
default double getDouble(int index, double defaultValue) throws DataException {
return get(index, double.class, defaultValue);
}
/**
* Gets the value for the specified index, then converts it to the {@link BigDecimal} type. If the key is out of
* bounds, returns {@code null}.
*
* @param index the specified index
* @return the converted BigDecimal value of the specified index, or {@code null} if the key is out of bounds
* @throws DataException if an error occurs during the search or conversion
*/
default @Nullable BigDecimal getBigDecimal(int index) throws DataException {
return getBigDecimal(index, null);
}
/**
* Gets the value for the specified index, then converts it to the {@link BigDecimal} type. If the key is out of
* bounds, returns {@code defaultValue}.
*
* @param index the specified index
* @param defaultValue the default value
* @return the converted BigDecimal value of the specified index, or {@code defaultValue} if the key is out of
* bounds
* @throws DataException if an error occurs during the search or conversion
*/
default @Nullable BigDecimal getBigDecimal(
int index, @Nullable BigDecimal defaultValue
) throws DataException {
return get(index, BigDecimal.class, defaultValue);
}
/**
* Converts this {@link DataList} to a new list of which elements' type is the specified class.
*
* @param cls the specified class
* @param <T> the type of the object to be returned`
* @return a new list of which elements' type is the specified class
* @throws DataException if an error occurs during the conversion
*/
default <T> @Nonnull List<T> toList(@Nonnull Class<T> cls) throws DataException {
return Fs.as(toList((Type) cls));
}
/**
* Converts this {@link DataList} to a new list of which elements' type is the specified class.
*
* @param typeRef the reference of the specified class
* @param <T> the type of the object to be returned`
* @return a new list of which elements' type is the specified class
* @throws DataException if an error occurs during the conversion
*/
default <T> @Nonnull List<T> toList(@Nonnull TypeRef<T> typeRef) throws DataException {
return Fs.as(toList(typeRef.type()));
}
/**
* Converts this {@link DataList} to a new list of which elements' type is the specified type.
*
* @param type the specified type
* @return a new list of which elements' type is the specified type
* @throws DataException if an error occurs during the conversion
*/
default @Nonnull List<Object> toList(@Nonnull Type type) throws DataException {
ParameterizedType listType = TypeKit.parameterizedType(List.class, new Type[]{type});
return Fs.as(toObject(listType));
}
/**
* Converts this {@link DataList} to a new object of the specified class, the type must be a collection or array
* type.
*
* @param cls the specified class
* @param <T> the type of the object to be returned`
* @return a new object of the specified class, the type must be a collection or array type.
* @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 DataList} to a new object of the specified class, the type must be a collection or array
* type.
*
* @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, the type must be a collection or array type.
* @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 DataList} to a new object of the specified type, the type must be a collection or array
* type.
*
* @param type the specified type
* @return a new object of the specified type, the type must be a collection or array 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 DataList} 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 DataList} and their contents are equal,
* {@code false} otherwise.
*/
@Override
boolean equals(@Nullable Object o);
/**
* Returns {@code true} if the content of this {@link DataList } are equal to the content of the given list,
* {@code false} otherwise.
*
* @param o the given list to be compared with this
* @return {@code true} if the content of this {@link DataList } are equal to the content of the given list,
* {@code false} otherwise.
*/
boolean contentEquals(@Nullable List<?> o);
}