Метод Commons для проверки на пустой граф объекта Java? - PullRequest
10 голосов
/ 24 марта 2011

Я обнаружил, что пишу такой метод:

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

А затем представьте эту структуру со множеством других свойств и других вложенных списков, и вы можете представить, что этот метод становится очень большим итесно связаны с моделью данных.

Может ли Apache Commons, Spring или какая-либо другая утилита FOSS рекурсивно рефлексивно обходить граф объектов и определять, что он в основном лишен каких-либо полезных данных, кроме держателей для списков, массивов, карт,и тому подобное?Так что я могу просто написать:

boolean isEmpty(MyStruct myStruct) {
  return MagicUtility.isObjectEmpty(myStruct);
}

Ответы [ 6 ]

8 голосов
/ 24 марта 2011

Спасибо Владимиру за то, что он указал мне правильное направление (я дал вам голос!), Хотя мое решение использует PropertyUtils вместо BeanUtils

Я должен был это реализовать, но это было не сложно. Вот решение. Я сделал это только для строк и списков, так как это все, что у меня сейчас есть. Может быть расширен для карт и массивов.

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);
      }
    }
  }

}
1 голос
/ 24 марта 2011

вы можете комбинировать метод Appache Common StringUtils.isEmpty() с BeanUtils.getProperties().

0 голосов
/ 24 марта 2011

Хотя ни один из вышеперечисленных служебных методов не может быть универсальным.Единственный способ (насколько мне известно) - это сравнение с пустым объектом.Создайте экземпляр объекта (без установленных свойств) и используйте метод «.equals» для сравнения.Убедитесь, что equals правильно реализовано в true для 2 равных непустых объектов и true для 2 пустых объектов.

0 голосов
/ 24 марта 2011

Я не могу себе представить ситуацию, когда что-то полностью лишенное какого-либо содержимого в целом графе объектов попадет в приложение. Кроме того, что именно будет считаться «пустым»? Будет ли это просто ссылаться на строки и коллекции? Будет ли считаться строка только с пробелами? Как насчет чисел ... будет ли любое число делать объект непустым, или определенные числа, такие как -1, будут считаться пустыми? Как еще одна проблема, не кажется, что в целом было бы полезно знать, есть ли в объекте НЕТ содержимого ... обычно вам нужно убедиться, что в определенных полях есть конкретные данные и т. Д. Существует слишком много возможностей для какой-то общий метод, подобный этому, имеет смысл, на мой взгляд.

Возможно, более полная система проверки, такая как JSR-303 , будет работать лучше. Эталонная реализация для этого - Hibernate Validator .

0 голосов
/ 24 марта 2011

Я не знаю библиотеку, которая делает это, но используя рефлексию, это не так сложно реализовать самостоятельно. Вы можете легко зацикливаться на методах-получателях класса и решать, имеет ли экземпляр значение, вы можете далее определять результат в зависимости от типа возвращаемого значения получателя.

Сложная задача - определить, какие члены класса вы считаете «полезными данными». Простое исключение из списков, карт и массивов, вероятно, не поможет вам.

Я бы на самом деле подумал о написании собственного типа аннотации, чтобы «пометить» подходящие «полезные» элементы (которые затем можно было бы заметить + обработать кодом отражения). Я не знаю, изящный ли это подход к вашей проблеме, так как я не знаю, сколько классов затронуто.

0 голосов
/ 24 марта 2011

Привет, Кевин, не видел ничего похожего на тот метод, о котором ты просил (мне тоже это интересно), но не рассматривал ли ты вопрос об использовании отражения для запроса объекта во время выполнения?

...