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

es.prodevelop.pui9.utils.PuiObjectUtils Maven / Gradle / Ivy

The newest version!
package es.prodevelop.pui9.utils;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.security.SecureRandom;
import java.time.Instant;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.reflect.FieldUtils;

import com.google.common.primitives.Primitives;

import es.prodevelop.pui9.json.GsonSingleton;

/**
 * Utility class to manage objects: copy properties, copy objects...
 * 
 * @author Marc Gil - [email protected]
 */
public class PuiObjectUtils {

	private static Map, Map> mapCache = new LinkedHashMap<>();

	/**
	 * Copy a whole object into another one (external references are copied by
	 * reference. If you need a deep copy, use {@link #copyDeepObject(Object)})
	 * 
	 * @param   The type of the object
	 * @param orig The original object
	 * @return A copy of the given object
	 */
	@SuppressWarnings("unchecked")
	public static  T copyObject(T orig) {
		if (orig == null) {
			return null;
		}

		try {
			T dest = (T) orig.getClass().newInstance();
			copyProperties(dest, orig);
			return dest;
		} catch (InstantiationException | IllegalAccessException e) {
			return null;
		}
	}

	/**
	 * Copy a whole object and its references into another one. References are also
	 * copied. This is a deep copy of the object
	 * 
	 * @param   The type of the object
	 * @param orig The original object
	 * @return A deep copy of the given object
	 */
	@SuppressWarnings("unchecked")
	public static  T copyDeepObject(T orig) {
		if (orig == null) {
			return null;
		}

		String origJson = GsonSingleton.getSingleton().getGson().toJson(orig);
		return GsonSingleton.getSingleton().getGson().fromJson(origJson, (Class) orig.getClass());
	}

	/**
	 * Copy all the attributes from the original object to the destination object
	 * 
	 * @param dest The destination object
	 * @param orig The original object
	 */
	public static void copyProperties(Object dest, Object orig) {
		if (dest == null || orig == null) {
			return;
		}

		Map destFields = getFields(dest.getClass());
		Map origFields = getFields(orig.getClass());

		for (Entry entry : destFields.entrySet()) {
			try {
				String destFieldName = entry.getKey();
				Field destField = entry.getValue();

				if (!origFields.containsKey(destFieldName)) {
					continue;
				}

				Field origField = origFields.get(destFieldName);

				if (!destField.getType().equals(origField.getType())) {
					continue;
				}

				Object value = origField.get(orig);
				destField.set(dest, value);
			} catch (IllegalArgumentException | IllegalAccessException e) {
				// do nothing
			}
		}
	}

	public static void populateObject(Object object, Map fieldValuesMap) {
		if (object == null || fieldValuesMap == null || fieldValuesMap.isEmpty()) {
			return;
		}

		Map fields = getFields(object.getClass());

		for (Entry entry : fieldValuesMap.entrySet()) {
			if (!fields.containsKey(entry.getKey())) {
				continue;
			}

			Field field = fields.get(entry.getKey());
			try {
				Object val = entry.getValue();
				Class fieldType = field.getType();
				if (field.getType().equals(BigDecimal.class) && (val instanceof Double)) {
					val = BigDecimal.valueOf((Double) val);
				}
				if (field.getType().equals(Integer.class) && (val instanceof Double)) {
					val = Integer.valueOf(((Double) val).intValue());
				}
				if (field.getType().equals(Instant.class) && (val instanceof String)) {
					val = PuiDateUtil.stringToInstant((String) val);
				}
				if (Enum.class.isAssignableFrom(fieldType)) {
					for (Object enumVal : fieldType.getEnumConstants()) {
						if (enumVal.toString().equals(val)) {
							val = enumVal;
							break;
						}
					}
				}

				if (val != null && !field.getType().isAssignableFrom(val.getClass()) && val instanceof String) {
					val = guessValueType((String) val, field.getType());
				}

				if (val != null) {
					if (Primitives.isWrapperType(fieldType) && !Primitives.isWrapperType(val.getClass())) {
						val = convertToWrapper(val);
					} else if (!Primitives.isWrapperType(fieldType) && Primitives.isWrapperType(val.getClass())) {
						val = convertToPrimitive(val);
					}
				}

				field.setAccessible(true);

				if (val == null || field.getType().isAssignableFrom(val.getClass())) {
					field.set(object, val);
				}
			} catch (IllegalArgumentException | IllegalAccessException e) {
				// do nothing
			}
		}
	}

	public static int computeHashCode(IPuiObject object) {
		Map fields = getFields(object.getClass());
		if (ObjectUtils.isEmpty(fields)) {
			return new SecureRandom().nextInt();
		}

		HashCodeBuilder hcBuilder = new HashCodeBuilder();
		fields.entrySet().forEach(entry -> {
			try {
				Field field = entry.getValue();
				Object value = FieldUtils.readField(field, object, true);
				if (value instanceof IPuiObject) {
					hcBuilder.append(computeHashCode((IPuiObject) value));
				} else {
					hcBuilder.append(value);
				}
			} catch (IllegalArgumentException | IllegalAccessException e) {
				// do nothing
			}
		});

		return hcBuilder.toHashCode();
	}

	/**
	 * Get all the fields from the Class, including the inherited ones
	 * 
	 * @param clazz The class type of the object
	 * @return A map with the name and Field
	 */
	public static Map getFields(Class clazz) {
		if (!mapCache.containsKey(clazz)) {
			synchronized (mapCache) {
				if (!mapCache.containsKey(clazz)) {
					Map map = new LinkedHashMap<>();

					Class toRegister = clazz;
					while (toRegister != null) {
						List fields = Arrays.asList(toRegister.getDeclaredFields());
						for (Field field : fields) {
							field.setAccessible(true);
							map.put(field.getName(), field);
						}
						toRegister = toRegister.getSuperclass();
					}

					mapCache.put(clazz, map);
				}
			}
		}

		return mapCache.get(clazz);
	}

	private static Object convertToPrimitive(Object value) {
		if (value == null) {
			return null;
		}

		if (Integer.class.equals(value.getClass())) {
			return ((Integer) value).intValue();
		} else if (Long.class.equals(value.getClass())) {
			return ((Long) value).longValue();
		} else if (Float.class.equals(value.getClass())) {
			return ((Float) value).floatValue();
		} else if (Double.class.equals(value.getClass())) {
			return ((Double) value).doubleValue();
		} else if (Boolean.class.equals(value.getClass())) {
			return ((Boolean) value).booleanValue();
		} else {
			return null;
		}
	}

	private static Object convertToWrapper(Object value) {
		if (value == null) {
			return null;
		}

		if (int.class.equals(value.getClass())) {
			return Integer.valueOf((int) value);
		} else if (long.class.equals(value.getClass())) {
			return Long.valueOf((long) value);
		} else if (float.class.equals(value.getClass())) {
			return Float.valueOf((float) value);
		} else if (double.class.equals(value.getClass())) {
			return Double.valueOf((double) value);
		} else if (boolean.class.equals(value.getClass())) {
			return Boolean.valueOf((boolean) value);
		} else {
			return null;
		}
	}

	private static Object guessValueType(String value, Class type) {
		if (value == null) {
			return null;
		}

		if (Integer.class.equals(type)) {
			return Integer.valueOf(value);
		} else if (int.class.equals(type)) {
			return Integer.parseInt(value);
		} else if (Long.class.equals(type)) {
			return Long.valueOf(value);
		} else if (long.class.equals(type)) {
			return Long.parseLong(value);
		} else if (Float.class.equals(type)) {
			return Float.valueOf(value);
		} else if (float.class.equals(type)) {
			return Float.parseFloat(value);
		} else if (Double.class.equals(type)) {
			return Double.valueOf(value);
		} else if (double.class.equals(type)) {
			return Double.parseDouble(value);
		} else if (Boolean.class.equals(type)) {
			return Boolean.valueOf(value);
		} else if (boolean.class.equals(type)) {
			return Boolean.parseBoolean(value);
		} else if (BigDecimal.class.equals(type)) {
			return new BigDecimal(value);
		} else {
			return null;
		}
	}

	private PuiObjectUtils() {
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy