CommonCopierHandler.java
package space.sunqian.fs.object.convert.handlers;
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.annotation.DatePattern;
import space.sunqian.fs.object.annotation.NumPattern;
import space.sunqian.fs.object.convert.ConvertKit;
import space.sunqian.fs.object.convert.ConvertOption;
import space.sunqian.fs.object.convert.ObjectConverter;
import space.sunqian.fs.object.convert.ObjectCopier;
import space.sunqian.fs.object.schema.MapSchema;
import space.sunqian.fs.object.schema.ObjectProperty;
import space.sunqian.fs.object.schema.ObjectSchema;
import java.util.Map;
/**
* The common implementation of {@link ObjectCopier.Handler}, also be the default last handler of
* {@link ObjectCopier#defaultCopier()}. Using {@link #getInstance()} can get a same one instance of this handler.
* <p>
* This handler uses the default implementations of {@link ObjectCopier.Handler}, which directly copies properties from
* the source object to the target object, following the rules of the specified options defined in
* {@link ConvertOption}.
*
* @author sunqian
*/
public class CommonCopierHandler implements ObjectCopier.Handler {
private static final @Nonnull CommonCopierHandler INST = new CommonCopierHandler();
/**
* Returns a same one instance of this handler.
*/
public static @Nonnull CommonCopierHandler getInstance() {
return INST;
}
@Override
public boolean copyProperty(
@Nonnull Object srcKey,
@Nullable Object srcValue,
@Nonnull Map<Object, Object> src,
@Nonnull MapSchema srcSchema,
@Nonnull Map<Object, Object> dst,
@Nonnull MapSchema dstSchema,
@Nonnull ObjectConverter converter,
@Nonnull Option<?, ?> @Nonnull ... options
) throws Exception {
if (ConvertOption.isIgnoreProperty(srcKey, options)) {
return false;
}
if (srcValue == null && ConvertOption.isIgnoreNull(options)) {
return false;
}
if (srcKey instanceof String) {
srcKey = Fs.as(ConvertOption.getNameMapper(options).map((String) srcKey));
}
Object dstKey = converter.convert(srcKey, srcSchema.keyType(), dstSchema.keyType(), options);
Object dstValue = converter.convert(srcValue, srcSchema.valueType(), dstSchema.valueType(), options);
dst.put(dstKey, dstValue);
return false;
}
@Override
public boolean copyProperty(
@Nonnull Object srcKey,
@Nullable Object srcValue,
@Nonnull Map<Object, Object> src,
@Nonnull MapSchema srcSchema,
@Nonnull Object dst,
@Nonnull ObjectSchema dstSchema,
@Nonnull ObjectConverter converter,
@Nonnull Option<?, ?> @Nonnull ... options
) throws Exception {
if (ConvertOption.isIgnoreProperty(srcKey, options)) {
return false;
}
if (srcValue == null && ConvertOption.isIgnoreNull(options)) {
return false;
}
if (srcKey instanceof String) {
srcKey = ConvertOption.getNameMapper(options).map((String) srcKey);
}
String dstPropertyName = Fs.as(converter.convert(srcKey, srcSchema.keyType(), String.class, options));
ObjectProperty dstProperty = dstSchema.getProperty(dstPropertyName);
if (dstProperty == null || !dstProperty.isWritable()) {
return false;
}
DatePattern datePattern = dstProperty.getAnnotation(DatePattern.class);
NumPattern numPattern = dstProperty.getAnnotation(NumPattern.class);
Option<?, ?>[] actualOps = ConvertKit.mergeOptions(options, datePattern, numPattern);
Object dstPropertyValue = converter.convert(srcValue, srcSchema.valueType(), dstProperty.type(), actualOps);
dstProperty.setValue(dst, dstPropertyValue);
return false;
}
@Override
public boolean copyProperty(
@Nonnull String srcPropertyName,
@Nonnull ObjectProperty srcProperty,
@Nonnull Object src,
@Nonnull ObjectSchema srcSchema,
@Nonnull Map<Object, Object> dst,
@Nonnull MapSchema dstSchema,
@Nonnull ObjectConverter converter,
@Nonnull Option<?, ?> @Nonnull ... options
) throws Exception {
if (ConvertOption.isIgnoreProperty(srcProperty.name(), options)) {
return false;
}
if (!srcProperty.isReadable()) {
return false;
}
if ("class".equals(srcPropertyName) && !ConvertOption.isIncludeClass(options)) {
return false;
}
String actualSrcPropertyName = ConvertOption.getNameMapper(options).map(srcPropertyName);
Object srcPropertyValue = srcProperty.getValue(src);
if (srcPropertyValue == null && ConvertOption.isIgnoreNull(options)) {
return false;
}
Object dstKey = converter.convert(actualSrcPropertyName, String.class, dstSchema.keyType(), options);
Object dstValue = converter.convert(srcPropertyValue, srcProperty.type(), dstSchema.valueType(), options);
dst.put(dstKey, dstValue);
return false;
}
@Override
public boolean copyProperty(
@Nonnull String srcPropertyName,
@Nonnull ObjectProperty srcProperty,
@Nonnull Object src,
@Nonnull ObjectSchema srcSchema,
@Nonnull Object dst,
@Nonnull ObjectSchema dstSchema,
@Nonnull ObjectConverter converter,
@Nonnull Option<?, ?> @Nonnull ... options
) throws Exception {
if (ConvertOption.isIgnoreProperty(srcProperty.name(), options)) {
return false;
}
if (!srcProperty.isReadable()) {
return false;
}
if ("class".equals(srcPropertyName) && !ConvertOption.isIncludeClass(options)) {
return false;
}
String actualSrcPropertyName = ConvertOption.getNameMapper(options).map(srcPropertyName);
Object srcPropertyValue = srcProperty.getValue(src);
if (srcPropertyValue == null && ConvertOption.isIgnoreNull(options)) {
return false;
}
String dstPropertyName = Fs.as(converter.convert(actualSrcPropertyName, String.class, String.class, options));
ObjectProperty dstProperty = dstSchema.getProperty(dstPropertyName);
if (dstProperty == null || !dstProperty.isWritable()) {
return false;
}
DatePattern datePattern = ConvertKit.getAnnotation(
DatePattern.class, srcProperty, dstProperty
);
NumPattern numPattern = ConvertKit.getAnnotation(
NumPattern.class, srcProperty, dstProperty
);
Option<?, ?>[] actualOps = ConvertKit.mergeOptions(options, datePattern, numPattern);
Object dstPropertyValue = converter.convert(
srcPropertyValue, srcProperty.type(), dstProperty.type(), actualOps
);
dstProperty.setValue(dst, dstPropertyValue);
return false;
}
}