Exemplo n.º 1
0
  /**
   * Returns a map of properties that differ (via {@link Object#equals(Object)}) between two
   * AutoBeans. The keys are property names and the values are the value of the property in <code>b
   * </code>. Properties present in <code>a</code> but missing in <code>b</code> will be represented
   * by <code>null</code> values. This implementation will compare AutoBeans of different
   * parameterizations, although the diff produced is likely meaningless.
   *
   * <p>This will work for both simple and wrapper AutoBeans.
   *
   * @param a an {@link AutoBean}
   * @param b an {@link AutoBean}
   * @return a {@link Map} of differing properties
   */
  public static Map<String, Object> diff(AutoBean<?> a, AutoBean<?> b) {
    // Fast check for comparing an object to itself
    if (a == b) {
      return Collections.emptyMap();
    }
    final Map<String, Object> toReturn = getAllProperties(b);

    // Remove the entries that are equal, adding nulls for missing properties
    a.accept(
        new AutoBeanVisitor() {
          @Override
          public boolean visitReferenceProperty(
              String propertyName, AutoBean<?> previousValue, PropertyContext ctx) {
            if (toReturn.containsKey(propertyName)) {
              if (equal(propertyName, previousValue)) {
                // No change
                toReturn.remove(propertyName);
              }
            } else {
              // The predecessor has a value that this object doesn't.
              toReturn.put(propertyName, null);
            }
            return false;
          }

          @Override
          public boolean visitValueProperty(
              String propertyName, Object previousValue, PropertyContext ctx) {
            if (toReturn.containsKey(propertyName)) {
              if (equal(propertyName, previousValue)) {
                // No change
                toReturn.remove(propertyName);
              }
            } else {
              // The predecessor has a value that this object doesn't.
              toReturn.put(propertyName, null);
            }
            return false;
          }

          private boolean equal(String propertyName, AutoBean<?> previousValue) {
            return previousValue == null && toReturn.get(propertyName) == null
                || previousValue != null && equal(propertyName, previousValue.as());
          }

          private boolean equal(String propertyName, Object previousValue) {
            Object currentValue = toReturn.get(propertyName);
            return previousValue == null && currentValue == null
                || previousValue != null && previousValue.equals(currentValue);
          }
        });
    return toReturn;
  }
Exemplo n.º 2
0
  /**
   * Returns a map that is a copy of the properties contained in an AutoBean. The returned map is
   * mutable, but editing it will not have any effect on the bean that produced it.
   *
   * @param bean an {@link AutoBean}
   * @return a {@link Map} of the bean's properties
   */
  public static Map<String, Object> getAllProperties(AutoBean<?> bean) {
    final Map<String, Object> toReturn = new LinkedHashMap<String, Object>();

    // Look at the previous value of all properties
    bean.accept(
        new AutoBeanVisitor() {
          @Override
          public boolean visitReferenceProperty(
              String propertyName, AutoBean<?> value, PropertyContext ctx) {
            toReturn.put(propertyName, value == null ? null : value.as());
            return false;
          }

          @Override
          public boolean visitValueProperty(
              String propertyName, Object value, PropertyContext ctx) {
            toReturn.put(propertyName, value);
            return false;
          }
        });
    return toReturn;
  }