Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.fulib.scenarios.debug.ASTDumper Maven / Gradle / Ivy
package org.fulib.scenarios.debug;
import java.beans.Introspector;
import java.io.PrintWriter;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.*;
// TODO move to gentreesrc runtime library
public class ASTDumper
{
private final Class>[] rootClasses;
public ASTDumper(Class>... rootClasses)
{
this.rootClasses = rootClasses;
}
public ASTDumper(Collection extends Class>> rootClasses)
{
this.rootClasses = rootClasses.toArray(new Class[0]);
}
private boolean isNode(Object object)
{
for (Class> rootClass : this.rootClasses)
{
if (rootClass.isInstance(object))
{
return true;
}
}
return false;
}
public void dump(Object object, PrintWriter out)
{
this.dump(object, "", out, Collections.newSetFromMap(new IdentityHashMap<>()));
}
private void dump(Object object, String indent, PrintWriter out, Set dejaVu)
{
if (object == null)
{
out.println("null");
return;
}
if (!this.isNode(object))
{
out.println(object);
return;
}
this.dumpNode(object, indent, out, dejaVu);
}
private void dumpNode(Object object, String indent, PrintWriter out, Set dejaVu)
{
final Class> type = object.getClass();
out.print(getID(object));
if (!dejaVu.add(object))
{
// already seen.
out.println(" (s.a.)");
return;
}
final Map attributes = new TreeMap<>();
final Map children = new TreeMap<>();
this.collectProperties(object, type, attributes, children);
if (!attributes.isEmpty())
{
this.printAttributes(out, attributes);
}
out.println();
if (!children.isEmpty())
{
this.printChildren(indent, out, dejaVu, children);
}
}
private void collectProperties(Object object, Class> type, Map attributes,
Map children)
{
for (Method method : type.getDeclaredMethods())
{
if ((method.getModifiers() & Modifier.PUBLIC) == 0 || !method.getName().startsWith("get")
|| method.getParameterCount() != 0)
{
continue;
}
this.collectProperty(object, method, attributes, children);
}
}
private void collectProperty(Object object, Method method, Map attributes,
Map children)
{
final String key = Introspector.decapitalize(method.getName().substring(3));
Object value;
try
{
value = method.invoke(object);
}
catch (Exception ignored)
{
value = "";
}
this.collectProperty(key, value, attributes, children);
}
private void collectProperty(String key, Object value, Map attributes, Map children)
{
if (value instanceof Collection)
{
this.collectProperties(key, (Collection) value, attributes, children);
}
else if (value instanceof Map)
{
this.collectProperties(key, (Map) value, attributes, children);
}
else
{
(this.isNode(value) ? children : attributes).put(key, value);
}
}
private void collectProperties(String key, Map, ?> value, Map attributes, Map children)
{
if (value.isEmpty())
{
attributes.put(key, "{}");
return;
}
final int maxKeyLength = value.keySet().stream().map(Object::toString).mapToInt(String::length).max()
.getAsInt();
final String format = key + "[%" + maxKeyLength + "s]";
final Map rest = new TreeMap<>();
for (Map.Entry, ?> entry : value.entrySet())
{
final String entryKey = entry.getKey().toString();
final Object entryValue = entry.getValue();
if (this.isNode(entryValue))
{
children.put(String.format(format, entryKey), entryValue);
rest.put(entryKey, getID(entryValue));
}
else
{
rest.put(entryKey, entryValue);
}
}
attributes.put(key, rest.toString());
}
private void collectProperties(String key, Collection> value, Map attributes,
Map children)
{
if (value.isEmpty())
{
attributes.put(key, "[]");
return;
}
final int size = value.size();
final String format = key + "[%" + ((int) Math.log10(size) + 1) + "d]";
final Object[] rest = new Object[size];
int index = 0;
for (Object item : value)
{
if (this.isNode(item))
{
children.put(String.format(format, index), item);
rest[index] = getID(item);
}
else
{
rest[index] = item;
}
index++;
}
attributes.put(key, Arrays.toString(rest));
}
private static String getID(Object item)
{
final Class> itemClass = item.getClass();
final Class> enclosingClass = itemClass.getEnclosingClass();
final String simpleName = itemClass.getSimpleName();
final String idNum = Integer.toHexString(System.identityHashCode(item));
return ("Impl".equals(simpleName) ? enclosingClass.getSimpleName() : simpleName) + "@" + idNum;
}
private void printAttributes(PrintWriter out, Map attributes)
{
out.print('(');
final Iterator> iterator = attributes.entrySet().iterator();
Map.Entry entry = iterator.next();
out.print(entry.getKey());
out.print(": ");
out.print(entry.getValue());
while (iterator.hasNext())
{
entry = iterator.next();
out.print(", ");
out.print(entry.getKey());
out.print(": ");
out.print(entry.getValue());
}
out.print(')');
}
private void printChildren(String indent, PrintWriter out, Set dejaVu, Map children)
{
for (Iterator> iterator = children.entrySet().iterator(); iterator.hasNext(); )
{
final Map.Entry entry = iterator.next();
final String key = entry.getKey();
out.print(indent + "+- ");
out.print(key);
out.print(": ");
final StringBuilder newIndent = new StringBuilder(indent.length() + key.length() + 2 + 3);
newIndent.append(indent);
newIndent.append(iterator.hasNext() ? "| " : " ");
for (int i = 0; i < key.length(); i++)
{
newIndent.append(' ');
}
newIndent.append(" ");
this.dumpNode(entry.getValue(), newIndent.toString(), out, dejaVu);
}
}
}