All Downloads are FREE. Search and download functionalities are using the official Maven repository.

us.fatehi.utility.ObjectToString Maven / Gradle / Ivy

Go to download

SchemaCrawler is an open-source Java API that makes working with database metadata as easy as working with plain old Java objects. SchemaCrawler is also a database schema discovery and comprehension, and schema documentation tool. You can search for database schema objects using regular expressions, and output the schema and data in a readable text format. The output is designed to be diff-ed against other database schemas.

There is a newer version: 16.24.2
Show newest version
/*
========================================================================
SchemaCrawler
http://www.schemacrawler.com
Copyright (c) 2000-2024, Sualeh Fatehi .
All rights reserved.
------------------------------------------------------------------------

SchemaCrawler is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

SchemaCrawler and the accompanying materials are made available under
the terms of the Eclipse Public License v1.0, GNU General Public License
v3 or GNU Lesser General Public License v3.

You may elect to redistribute this code under any of these licenses.

The Eclipse Public License is available at:
http://www.eclipse.org/legal/epl-v10.html

The GNU General Public License v3 and the GNU Lesser General Public
License v3 are available at:
http://www.gnu.org/licenses/

========================================================================
*/

package us.fatehi.utility;

import static java.lang.System.lineSeparator;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.StringJoiner;
import java.util.TreeMap;

public class ObjectToString {

  public static List arrayToList(final Object array) {
    if (array == null || !array.getClass().isArray()) {
      return null;
    }

    final int length = Array.getLength(array);
    final List objectList = new ArrayList<>();
    for (int i = 0; i < length; i++) {
      objectList.add(Array.get(array, i));
    }
    return objectList;
  }

  public static List> classHierarchy(final Object object) {
    final List> classHierarchy = new ArrayList<>();
    if (object != null) {
      Class clazz = object.getClass();
      classHierarchy.add(clazz);
      while (clazz.getSuperclass() != null) {
        clazz = clazz.getSuperclass();
        if (clazz.getSuperclass() != null) {
          classHierarchy.add(clazz);
        }
      }
    }
    return classHierarchy;
  }

  public static List collectionOrArrayToList(final Object object) {

    if (!isCollectionOrArray(object)) {
      return new ArrayList<>();
    }

    if (object instanceof List) {
      return (List) object;
    } else if (object instanceof Collection) {
      return new ArrayList<>((Collection) object);
    } else {
      // We have checked earlier if this was an array, so at this point we are pretty sure it is an
      // array
      return arrayToList(object);
    }
  }

  public static List fields(final Object object) {
    final List> classes = classHierarchy(object);
    final List allFields = new ArrayList<>();
    for (final Class clazz : classes) {
      if (clazz.isArray()
          || clazz.isPrimitive()
          || clazz.isEnum()
          || String.class.isAssignableFrom(clazz)) {
        break;
      }
      Field[] fields = {};
      try {
        fields = clazz.getDeclaredFields();
        AccessibleObject.setAccessible(fields, true);
      } catch (final Exception e) {
        // Ignore
      }
      allFields.addAll(Arrays.asList(fields));
    }

    // Remove static and transient fields
    for (final Iterator iterator = allFields.iterator(); iterator.hasNext(); ) {
      final Field field = iterator.next();
      final int modifiers = field.getModifiers();
      if (Modifier.isTransient(modifiers) || Modifier.isStatic(modifiers)) {
        iterator.remove();
      }
    }
    // Sort fields
    Collections.sort(allFields, Comparator.comparing(Field::getName));

    return allFields;
  }

  public static boolean isCollectionOrArray(final Object object) {

    if (object == null) {
      return false;
    }

    final Class objectClass = object.getClass();
    if (Collection.class.isAssignableFrom(objectClass) || objectClass.isArray()) {
      return true;
    } else {
      return false;
    }
  }

  public static boolean isPrimitive(final Object object) {

    if (object == null) {
      return false;
    }

    final Class objectClass = object.getClass();
    return Arrays.asList(
            Integer.class,
            Long.class,
            Double.class,
            Float.class,
            Boolean.class,
            Byte.class,
            Void.class,
            Short.class)
        .contains(objectClass);
  }

  public static boolean isSimpleObject(final Object object) {

    if (object == null) {
      return false;
    }

    final Class objectClass = object.getClass();
    return isPrimitive(object)
        || object instanceof String
        || object instanceof Character
        || objectClass.isEnum();
  }

  public static String listOrObjectToString(final Object object) {
    if (isCollectionOrArray(object)) {
      final List list = collectionOrArrayToList(object);
      final StringJoiner listJoiner = new StringJoiner(", ");
      for (final Object element : list) {
        listJoiner.add(String.valueOf(element));
      }
      return listJoiner.toString();
    }

    return String.valueOf(object);
  }

  public static Map objectMap(final Object object) {

    final Map objectMap = new TreeMap<>();
    if (object == null || isCollectionOrArray(object) || isSimpleObject(object)) {
      return objectMap;
    }

    final Class objectClass = object.getClass();
    if (Map.class.isAssignableFrom(objectClass)) {
      final Set> mapEntries = ((Map) object).entrySet();
      for (final Map.Entry mapEntry : mapEntries) {
        objectMap.put(String.valueOf(mapEntry.getKey()), mapEntry.getValue());
      }
    } else {
      objectMap.put("@object", object.getClass().getName());
      // objectMap.put("@hash", Integer.toHexString(System.identityHashCode(object)));
      for (final Field field : fields(object)) {
        try {
          Object value = field.get(object);
          if (isCollectionOrArray(value)) {
            value = collectionOrArrayToList(value);
          }
          objectMap.put(field.getName(), value);
        } catch (final Exception e) {
          // Ignore
        }
      }
    }

    return objectMap;
  }

  public static String toString(final Object object) {
    if (object == null || isSimpleObject(object)) {
      return String.valueOf(object);
    } else if (isCollectionOrArray(object)) {
      return printList(collectionOrArrayToList(object));
    }

    return printMap(0, objectMap(object));
  }

  private static char[] indent(final int indent) {
    // assert indent >= 0;

    final char[] indentChars = new char[indent * 2];
    Arrays.fill(indentChars, ' ');
    return indentChars;
  }

  private static String printList(final List list) {
    // assert list != null;

    final StringBuilder buffer = new StringBuilder();
    buffer.append('[');
    for (final Iterator iterator = list.iterator(); iterator.hasNext(); ) {
      final Object object = iterator.next();
      if (isPrimitive(object)) {
        buffer.append(String.valueOf(object));
      } else {
        buffer.append('\"').append(String.valueOf(object)).append('\"');
      }
      if (iterator.hasNext()) {
        buffer.append(", ");
      }
    }
    buffer.append(']');

    return buffer.toString();
  }

  private static String printMap(final int indent, final Map objectMap) {
    // assert objectMap != null;

    final StringBuilder buffer = new StringBuilder();

    buffer.append(indent(indent)).append('{').append(lineSeparator());
    final Set> entrySet = objectMap.entrySet();
    for (final Iterator> iterator = entrySet.iterator();
        iterator.hasNext(); ) {
      final Entry entry = iterator.next();
      Object value = entry.getValue();
      if (value != null) {
        final Class valueClass = value.getClass();
        if (List.class.isAssignableFrom(valueClass)) {
          value = printList((List) value);
        } else if (Map.class.isAssignableFrom(valueClass)) {
          value = printMap(indent + 1, objectMap(value));
        } else if (!isPrimitive(value) || value instanceof String || valueClass.isEnum()) {
          value = String.format("\"%s\"", value);
        }
      }
      buffer
          .append(indent(indent + 1))
          .append("\"")
          .append(entry.getKey())
          .append("\": ")
          .append(String.valueOf(value));
      if (iterator.hasNext()) {
        buffer.append(",");
      }
      buffer.append(lineSeparator());
    }
    buffer.append(indent(indent)).append('}');

    return buffer.toString();
  }

  private ObjectToString() {
    // Prevent instantiation
  }
}