private Map<String,Object> extractValues(Object object){
  final Map<String,Object> result=new HashMap<>();
  final BeanWrapper wrapper=new BeanWrapperImpl(object);
  for (  PropertyDescriptor descriptor : wrapper.getPropertyDescriptors()) {
    if (descriptor.getReadMethod() == null || descriptor.getWriteMethod() == null) {
      continue;
    }
    final String propertyName=descriptor.getName();
    final Object value=PropertyUtils.getPropertyValue(object,propertyName);
    if (value == null) {
      result.put(propertyName,null);
      continue;
    }
    if (isIntractable(descriptor,value)) {
      result.put(propertyName,value);
      continue;
    }
    final Map<String,Object> children=extractValues(value);
    for (    Map.Entry<String,Object> entry : children.entrySet()) {
      result.put(propertyName + "." + entry.getKey(),entry.getValue());
    }
  }
  return result;
}

private Map < String , Object > extractValues ( Object object ) { final Map < String , Object > result = new HashMap < > ( ) ; final BeanWrapper wrapper = new BeanWrapperImpl ( object ) ; for ( PropertyDescriptor descriptor : wrapper . getPropertyDescriptors ( ) ) { if ( descriptor . getReadMethod ( ) == null || descriptor . getWriteMethod ( ) == null ) { continue ; } final String propertyName = descriptor . getName ( ) ; final Object value = PropertyUtils . getPropertyValue ( object , propertyName ) ; if ( value == null ) { result . put ( propertyName , null ) ; continue ; } if ( isIntractable ( descriptor , value ) ) { result . put ( propertyName , value ) ; continue ; } final Map < String , Object > children = extractValues ( value ) ; for ( Map . Entry < String , Object > entry : children . entrySet ( ) ) { result . put ( propertyName + "." + entry . getKey ( ) , entry . getValue ( ) ) ; } } return result ; }
given an input object , this method will return a map from the property paths to their corresponding values
