All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.wuba.wsilk.producer.mapper.MapperSerializer Maven / Gradle / Ivy

package com.wuba.wsilk.producer.mapper;

import com.google.common.collect.Sets;
import com.wuba.wsilk.codegen.AnnotationMapValue;
import com.wuba.wsilk.codegen.JavaWriter;
import com.wuba.wsilk.codegen.Modifier;
import com.wuba.wsilk.codegen.PropertyMeta;
import com.wuba.wsilk.codegen.model.ClassType;
import com.wuba.wsilk.codegen.model.Parameter;
import com.wuba.wsilk.codegen.model.Type;
import com.wuba.wsilk.core.*;
import com.wuba.wsilk.core.serializer.java.AbstractSingleJavaSerializer;

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 
 * 两个对象字段影射
 * 
 * @author mindashuang
 */

@SuppressWarnings({ "unchecked", "rawtypes" })
@Support(value = Mapper.class, suffix = "Mapper")
public class MapperSerializer extends AbstractSingleJavaSerializer {

	private boolean classCastInit = false;

	private final Map, Set>> classCastMap = new HashMap<>();

	public MapperSerializer(WsilkConfiguration configuration, Class annClass) {
		super(configuration, annClass);
	}

	SourceEntityMeta target;

	@Override
	public SourceEntityMeta init(SourceEntityMeta em) {
		AnnotationMapValue info = em.findAnnotation(Mapper.class);
 		target = this.getEntityTypeFactory().createEntityMeta(info.type());
		if (!classCastInit) {
			registerClassCastMap();
		}
		return super.init(em);
	}

	@Override
	public void methods(JavaWriter writer, SourceEntityMeta em) throws IOException {
		this.cloneMethod().clone(writer, em.getOriginal(), target);
	}

	private CloneConsumer cloneMethod() {
		return ((writer, src, des) -> {
			try {
				ClassType srcCt = new ClassType(src.getJavaClass());
				ClassType desCt = new ClassType(des.getJavaClass());
				String srcName = "src";
				String desName = "des";

				writer.beginMethod(Modifier.Field.PUBLIC_STATIC, new ClassType(void.class), "copy",
						new Parameter(srcName, srcCt), new Parameter(desName, desCt));
				writer.line("    if(", srcName, " != null && ", desName, " != null) { ");

				Set allProperties = src.getAllProperties();

				Map desMap = des.getAllProperties().stream()
						.collect(Collectors.toMap(PropertyMeta::getName, Function.identity(), (k1, k2) -> k1));

				if (allProperties != null) {

					for (PropertyMeta f : allProperties) {

						if (desMap.containsKey(f.getName()) && cast(f.getType(), desMap.get(f.getName()).getType())) {
							writer.line(fieldSimpleCopy(srcName, desName, f, desMap.get(f.getName())));
						}
					}
				}

				writer.line("    }");
				writer.end();
			} catch (IOException e) {
				e.printStackTrace();
			}
		});
	}

	private boolean cast(Type src, Type des) {
		Class srcClz = src.getJavaClass();
		Class desClz = des.getJavaClass();
		if (srcClz == desClz) {
			return true;
		}
		if (classCastMap.containsKey(srcClz) && classCastMap.get(srcClz).contains(desClz)) {
			return true;
		}
		return isInstanceof(srcClz, desClz);
	}

	private boolean isInstanceof(Class c, Class p) {
		if (c == p) {
			return true;
		}
		if (c.isAssignableFrom(p)) {
			return true;
		}
		if (c != Object.class) {
			SourceEntityMeta em = getEntityTypeFactory().createEntityMeta(c.getSuperclass());
			if (em != null) {
				return isInstanceof(em.getJavaClass(), p);
			}
		}
		return false;
	}

	private String fieldSimpleCopy(String src, String des, PropertyMeta fsrc, PropertyMeta fdes) {
		return new StringBuilder("    ").append(des).append(".").append(fieldStName(fdes)).append("(").append(src)
				.append(".").append(fieldGetName(fsrc)).append("());").toString();
	}

	private String fieldGetName(PropertyMeta f) {
		String prefix = f.getType().getJavaClass().equals(boolean.class) ? "is" : "get";
		return prefix + upperFirstChar(f.getName());
	}

	private String upperFirstChar(String name) {
		String str1 = name.substring(0, 1);
		String str2 = name.substring(1);
		return str1.toUpperCase() + str2;
	}

	private String fieldStName(PropertyMeta f) {
		return "set" + upperFirstChar(f.getName());
	}

	private void registerClassCastMap() {
		// Widening Casting (automatically) - converting a smaller type to a larger type
		// size
		// byte-> short-> char-> int-> long-> float->double
		// Primitive type Wrapper class
		// boolean Boolean
		// byte Byte
		// short Short
		// char Character
		// int Integer
		// long Long
		// float Float
		// double Double

		classCastMap.put(boolean.class, Sets.newHashSet(Boolean.class, boolean.class));
		classCastMap.put(byte.class, Sets.newHashSet(Byte.class, byte.class));
		classCastMap.put(short.class, Sets.newHashSet(Short.class, short.class, byte.class));
		classCastMap.put(char.class, Sets.newHashSet(Character.class, char.class, short.class, byte.class));
		classCastMap.put(int.class, Sets.newHashSet(Integer.class, int.class, char.class, short.class, byte.class));
		classCastMap.put(long.class,
				Sets.newHashSet(Long.class, long.class, int.class, char.class, short.class, byte.class));
		classCastMap.put(float.class,
				Sets.newHashSet(Float.class, float.class, long.class, int.class, char.class, short.class, byte.class));
		classCastMap.put(double.class, Sets.newHashSet(Double.class, double.class, float.class, long.class, int.class,
				char.class, short.class, byte.class));

		classCastMap.put(Boolean.class, Sets.newHashSet(boolean.class, Boolean.class));
		classCastMap.put(Byte.class, Sets.newHashSet(byte.class, Byte.class));
		classCastMap.put(Short.class, Sets.newHashSet(short.class, Short.class));
		classCastMap.put(Character.class, Sets.newHashSet(char.class, Character.class));
		classCastMap.put(Integer.class, Sets.newHashSet(int.class, Integer.class));
		classCastMap.put(Long.class, Sets.newHashSet(long.class, Long.class));
		classCastMap.put(Float.class, Sets.newHashSet(float.class, Float.class));
		classCastMap.put(Double.class, Sets.newHashSet(double.class, Double.class));
		classCastInit = true;
	}

	/**
	 * 克隆对象
	 * 
	 * @author mindashuang
	 */
	@FunctionalInterface
	public static interface CloneConsumer {
		/**
		 * 克隆
		 * 
		 * @param w 输出
		 * @param c 来源
		 * @param m
		 */
		void clone(W w, C c, M m);
	}

	@Override
	public void importPackage(JavaWriter writer, SourceEntityMeta em) throws IOException {
		Class src = em.getOriginal().getJavaClass();
		writer.imports(src);
		Class des = target.getJavaClass();
		if (src != des) {
			writer.imports(des);
		}
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy