class ReflectionUtil {

    public static void mergeObject(Object from, Object to, boolean ignoreNullValue, Set<String> ignores) {
        try {
            Map<String, Object> settablePropertiesMap = Maps.newHashMap();
            PropertyDescriptor[] propertyDescriptors = getPropertyDescriptors(from.getClass());
            for (PropertyDescriptor property : propertyDescriptors) {
                if (property.getReadMethod() == null || property.getWriteMethod() == null) {
                    continue;
                }
                Object value = property.getReadMethod().invoke(from);
                if ((value != null || !ignoreNullValue) && !ignores.contains(property.getName())) {
                    settablePropertiesMap.put(property.getName(), value);
                }
            }
            for (Map.Entry<String, Object> settableProperty : settablePropertiesMap.entrySet()) {
                // Set new values
                String propertyName = settableProperty.getKey();
                Object propertyValue = settableProperty.getValue();
                setPropertyValue(to, propertyName, propertyValue);
            }
        } catch (IllegalAccessException | InvocationTargetException | BeansException e) {
            throw new InvalidArgumentException("Cannot merge object", e);
        }
    }

    private  ReflectionUtil();

}