Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Commons method to test for an empty Java object graph?

I've found myself writing a method like this:

boolean isEmpty(MyStruct myStruct) {
  return (myStruct.getStringA() == null || myStruct.getStringA().isEmpty())
    && (myStruct.getListB() == null || myStruct.getListB().isEmpty());
}

And then imagine this struct with lots of other properties and other nested lists, and you can imagine that this method gets very big and is tightly coupled to the data model.

Does Apache Commons, or Spring, or some other FOSS utility have the ability to recursively reflectively walk an object graph and determine that it's basically devoid of any useful data, other than the holders for Lists, Arrays, Maps, and such? So that I can just write:

boolean isEmpty(MyStruct myStruct) {
  return MagicUtility.isObjectEmpty(myStruct);
}
like image 754
Kevin Pauli Avatar asked Mar 24 '11 15:03

Kevin Pauli


People also ask

How do you check if all fields of an object are null in Java?

allNull() is a static method of the ObjectUtils class that is used to check if all the values in the array point to a null reference. The method returns false if any value in the array of values is not null . The method returns true if all the values in the passed array are null or the array is null or empty.

How do you know if a class object is empty?

hasOwnProperty(key): A function is created where the object is looped over and checked if it contains the 'key' property using the object. hasOwnProperty() method. This function would return true if it could find no keys in the loop, which means that the object is empty.

Does ObjectUtils isEmpty checks for null?

isEmpty. Checks if an Object is empty or null. The following types are supported: CharSequence : Considered empty if its length is zero.


2 Answers

Thanks to Vladimir for pointing me in the right direction (I gave you an upvote!) although my solution uses PropertyUtils rather than BeanUtils

I did have to implement it but it wasn't hard. Here's the solution. I only did it for Strings and Lists since that's all I happen to have at the moment. Could be extended for Maps and Arrays.

import java.lang.reflect.InvocationTargetException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang.StringUtils;

public class ObjectUtils {

  /**
   * Tests an object for logical emptiness. An object is considered logically empty if its public gettable property
   * values are all either null, empty Strings or Strings with just whitespace, or lists that are either empty or
   * contain only other logically empty objects.  Currently does not handle Maps or Arrays, just Lists.
   * 
   * @param object
   *          the Object to test
   * @return whether object is logically empty
   * 
   * @author Kevin Pauli
   */
  @SuppressWarnings("unchecked")
  public static boolean isObjectEmpty(Object object) {

    // null
    if (object == null) {
      return true;
    }

    // String
    else if (object instanceof String) {
      return StringUtils.isEmpty(StringUtils.trim((String) object));
    }

    // List
    else if (object instanceof List) {
      boolean allEntriesStillEmpty = true;
      final Iterator<Object> iter = ((List) object).iterator();
      while (allEntriesStillEmpty && iter.hasNext()) {
        final Object listEntry = iter.next();
        allEntriesStillEmpty = isObjectEmpty(listEntry);
      }
      return allEntriesStillEmpty;
    }

    // arbitrary Object
    else {
      try {
        boolean allPropertiesStillEmpty = true;
        final Map<String, Object> properties = PropertyUtils.describe(object);
        final Iterator<Entry<String, Object>> iter = properties.entrySet().iterator();
        while (allPropertiesStillEmpty && iter.hasNext()) {
          final Entry<String, Object> entry = iter.next();
          final String key = entry.getKey();
          final Object value = entry.getValue();

          // ignore the getClass() property
          if ("class".equals(key))
            continue;

          allPropertiesStillEmpty = isObjectEmpty(value);
        }
        return allPropertiesStillEmpty;
      } catch (IllegalAccessException e) {
        throw new RuntimeException(e);
      } catch (InvocationTargetException e) {
        throw new RuntimeException(e);
      } catch (NoSuchMethodException e) {
        throw new RuntimeException(e);
      }
    }
  }

}
like image 186
Kevin Pauli Avatar answered Sep 27 '22 23:09

Kevin Pauli


you can combine Appache Common StringUtils.isEmpty() method with BeanUtils.getProperties().

like image 30
Vladimir Ivanov Avatar answered Sep 27 '22 22:09

Vladimir Ivanov