Package org.jboss.errai.tools.monitoring

Source Code of org.jboss.errai.tools.monitoring.ObjectExplorer$PrimitiveMarker

/*
* Copyright 2010 JBoss, a divison Red Hat, Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*    http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.jboss.errai.tools.monitoring;

import org.mvel2.util.ParseTools;
import org.mvel2.util.StringAppender;

import javax.swing.*;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeExpansionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.MutableTreeNode;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import static javax.swing.SwingUtilities.invokeLater;
import static org.jboss.errai.tools.monitoring.UiHelper.createIconEntry;
import static org.mvel2.util.ParseTools.boxPrimitive;

public class ObjectExplorer extends JTree {
    private DefaultMutableTreeNode rootNode;
    private Object root;

    private Map<Object, Runnable> deferred = new ConcurrentHashMap<Object, Runnable>();

    private static Map<Class, ValRenderer> renderers = new HashMap<Class, ValRenderer>();

    public ObjectExplorer() {
        setCellRenderer(new MonitorTreeCellRenderer());
        buildTree();

        addTreeExpansionListener(new TreeExpansionListener() {
            public void treeExpanded(TreeExpansionEvent event) {
                Runnable r = deferred.get(event.getPath().getLastPathComponent());
                if (r != null) r.run();
            }

            public void treeCollapsed(TreeExpansionEvent event) {
            }
        });
    }

    public void setRoot(Object root) {
        this.root = root;
    }

    public void buildTree() {
        DefaultTreeModel model = (DefaultTreeModel) getModel();
        rootNode = null;
        if (root != null) {
            model.setRoot(nestObject(this, null, "<Root>", root));

        } else {
            model.setRoot(createIconEntry("database.png", ""));
        }
        model.reload();
    }

    public static DefaultMutableTreeNode nestObject(final ObjectExplorer explorer, DefaultMutableTreeNode node, String field, Object v) {
        if (v == null) return null;

        Class cls = v != null ? v.getClass() : Object.class;

        DefaultMutableTreeNode nNode = createClassNode(field, v);

        if (node == null) {
            DefaultMutableTreeNode temp = new DefaultMutableTreeNode();
            if (renderFieldByType(explorer, temp, field, cls, v)) {
                pullNodesUp(nNode, temp);
            } else {
                DefaultMutableTreeNode n = (DefaultMutableTreeNode) temp.getChildAt(0);
                ((JLabel) n.getUserObject()).setIcon(UiHelper.getSwIcon("class.png"));
                return n;
            }

        } else {
            renderFields(explorer, nNode, v != null ? v.getClass() : Object.class, v);
            node.add(nNode);
        }

        return nNode;
    }

    public static DefaultMutableTreeNode createClassNode(String field, Object v) {
        return createIconEntry("class.png", field + " {" + (v == null ? "null" : v.getClass().getName()) + "} = " + v);
    }

    private static void pullNodesUp(DefaultMutableTreeNode newNode, DefaultMutableTreeNode oldNode) {
        while (oldNode.getChildCount() != 0) {
            newNode.add((MutableTreeNode) oldNode.getChildAt(0));
        }
    }

    public static void renderFields(final ObjectExplorer explorer, final DefaultMutableTreeNode node, final Class clazz, final Object v) {
        if (clazz == null) return;

        if (clazz.isPrimitive()) {
            renderFieldByType(explorer, node, "val", PrimitiveMarker.class, v);
            return;
        }

        final DefaultMutableTreeNode placeholder = new DefaultMutableTreeNode("<...>");
        node.add(placeholder);

        Runnable r = new Runnable() {
            public void run() {
                if (!node.isNodeChild(placeholder)) {
                    return;
                }

                node.remove(placeholder);

                if (clazz.getSuperclass() != Object.class) {
                    renderFields(explorer, node, clazz.getSuperclass(), v);
                }

                for (Field fld : clazz.getDeclaredFields()) {
                    if ((fld.getModifiers() & Modifier.STATIC) != 0) continue;
                    fld.setAccessible(true);
                    renderField(explorer, node, fld, v);
                }

                invokeLater(new Runnable() {
                    public void run() {
                        ((DefaultTreeModel) explorer.getModel()).reload(node);
                    }
                });

                explorer.deferred.remove(node);
            }
        };

        if (explorer.rootNode == null) {
            explorer.rootNode = node;
            r.run();
        } else {
            explorer.deferred.put(node, r);
        }
    }

    public static void renderField(ObjectExplorer explorer, DefaultMutableTreeNode node, Field fld, Object v) {
        Object val;
        try {
            val = fld.get(v);
        }
        catch (Throwable t) {
            return;
        }

        DefaultMutableTreeNode tempNode = new DefaultMutableTreeNode();

        if (renderFieldByType(explorer, tempNode, fld.getName(), fld.getType(), val)) {
            DefaultMutableTreeNode newNode = createClassNode(fld.getName(), val);
            pullNodesUp(newNode, tempNode);
            node.add(newNode);
        } else {
            pullNodesUp(node, tempNode);
        }
    }

    public static boolean renderFieldByType(ObjectExplorer explorer, DefaultMutableTreeNode node, String field, Class clazz, Object v) {
        if (clazz.isArray()) {
            clazz = ArrayMarker.class;
        }

        if (!renderers.containsKey(clazz)) {
            if (!_scanClassHeirarchy(clazz, clazz)) {
                clazz = Object.class;
            }
        }

        return renderers.get(clazz).render(explorer, node, field, v);
    }

    public static boolean _scanClassHeirarchy(Class clazz, Class root) {
        if (clazz.isPrimitive()) {
            renderers.put(clazz, renderers.get(PrimitiveMarker.class));
            return true;
        }

        do {
            if (renderers.containsKey(root)) {
                renderers.put(boxPrimitive(clazz), renderers.get(root));
                return true;
            }

            for (Class iface : root.getInterfaces()) {
                if (_scanClassHeirarchy(clazz, iface)) return true;
            }
        } while ((root = root.getSuperclass()) != null);
        return false;
    }

    static {
        renderers.put(CharSequence.class, new ValRenderer() {
            public boolean render(ObjectExplorer explorer, DefaultMutableTreeNode node, String name, Object val) {
                node.add(createIconEntry("field.png", fieldLabel(name, val)));
                return false;
            }
        });

        renderers.put(ArrayMarker.class, new ValRenderer() {
            public boolean render(ObjectExplorer explorer, DefaultMutableTreeNode node, String name, Object val) {
                if (val == null) {
                    node.add(createIconEntry("field.png", fieldLabel(name, "null")));
                    return false;
                }

                int length = Array.getLength(val);
                Object o;
                for (int i = 0; i < length; i++) {
                    o = Array.get(val, i);
                    nestObject(explorer, node, String.valueOf(i), o);
                }

                return true;
            }
        });

        renderers.put(Collection.class, new ValRenderer() {
            public boolean render(ObjectExplorer explorer, DefaultMutableTreeNode node, String name, Object val) {
                if (val == null) {
                    node.add(createIconEntry("field.png", fieldLabel(name, "null")));
                    return false;
                }

                int i = 0;
                for (Object o : (Collection) val) {
                    nestObject(explorer, node, String.valueOf(i++), o);
                }

                return true;
            }
        });

        renderers.put(Map.class, new ValRenderer() {
            public boolean render(ObjectExplorer explorer, DefaultMutableTreeNode node, String name, Object val) {
                if (val == null) {
                    node.add(createIconEntry("field.png", fieldLabel(name, "null")));
                    return false;
                } else {
                    for (Map.Entry<Object, Object> entry : ((Map<Object, Object>) val).entrySet()) {
                        nestObject(explorer, node, String.valueOf(entry.getKey()), entry);
                    }
                    return true;
                }

            }
        });

        renderers.put(Object.class, new ValRenderer() {
            public boolean render(ObjectExplorer explorer, DefaultMutableTreeNode node, String name, Object val) {
                nestObject(explorer, node, name, val);
                return false;
            }
        });

        ValRenderer boxedPrimRenderer = new ValRenderer() {
            public boolean render(ObjectExplorer explorer, DefaultMutableTreeNode node, String name, Object val) {
                node.add(createIconEntry("field.png", fieldLabel(name, val)));
                return false;
            }
        };

        renderers.put(Integer.class, boxedPrimRenderer);
        renderers.put(Long.class, boxedPrimRenderer);
        renderers.put(Character.class, boxedPrimRenderer);
        renderers.put(Byte.class, boxedPrimRenderer);
        renderers.put(Short.class, boxedPrimRenderer);
        renderers.put(Double.class, boxedPrimRenderer);
        renderers.put(Boolean.class, boxedPrimRenderer);
        renderers.put(Float.class, boxedPrimRenderer);

        renderers.put(PrimitiveMarker.class, new ValRenderer() {
            public boolean render(ObjectExplorer explorer, DefaultMutableTreeNode node, String name, Object val) {
                node.add(createIconEntry("field.png", fieldLabelPrimitive(name, val)));
                return false;
            }
        });
    }

    static String fieldLabel(String name, Object v) {
        if (v == null) {
            return name + " = null";
        }
        return name + " {" + friendlyClassName(v) + "@" + v.hashCode() + "} = " + friendlyValue(v);
    }

    static String fieldLabelPrimitive(String name, Object v) {
        if (v == null) {
            return name + " = null";
        }

        Class c = v.getClass();

        return name + " {" + friendlyClassName(ParseTools.unboxPrimitive(c), v) + "} = " + friendlyValue(v);
    }

    static String friendlyClassName(Object v) {
        if (v == null) return "null";

        return friendlyClassName(v.getClass(), v);
    }

    static String friendlyClassName(Class cls, Object v) {
        if (cls.isPrimitive()) {
            if (cls == char[].class) return "char[" + Array.getLength(v) + "]";
            else if (cls == int[].class) return "int[" + Array.getLength(v) + "]";
            else if (cls == long[].class) return "long[" + Array.getLength(v) + "]";
            else if (cls == double[].class) return "double[" + Array.getLength(v) + "]";
            else if (cls == short[].class) return "short[" + Array.getLength(v) + "]";
            else if (cls == float[].class) return "float[" + Array.getLength(v) + "]";
            else if (cls == boolean[].class) return "boolean[" + Array.getLength(v) + "]";
            else if (cls == byte[].class) return "byte[" + Array.getLength(v) + "]";
        } else if (cls.isArray()) {
            return cls.getComponentType().getName() + "[" + Array.getLength(v) + "]";
        } else if (Collection.class.isAssignableFrom(cls)) {
            return cls.getName() + " [" + ((Collection) v).size() + "]";
        }
        return cls.getName();
    }

    static String friendlyValue(Object v) {
        if (v == null) return "null";

        Class cls = v.getClass();

        if (cls.isArray()) {
            Class comp = cls.getComponentType();

            if (comp == char.class) {
                return "\"" + (Array.getLength(v) < 50 ? new String((char[]) v) : new String((char[]) v, 0, 50) + "...") + "\"";
            } else {
                StringAppender appender = new StringAppender();

                int len = Array.getLength(v);
                appender.append("[");
                for (int i = 0; i < len && i < 25;) {
                    appender.append(String.valueOf(Array.get(v, i)));
                    if (++i < len && i < 25) appender.append(", ");
                }
                return appender.append("]").toString();
            }
        } else if (cls == Character.class) {
            return "'" + String.valueOf(v) + "'";
        }

        return "\"" + String.valueOf(v) + "\"";
    }

    static class ArrayMarker {
    }

    static class PrimitiveMarker {
    }

}
TOP

Related Classes of org.jboss.errai.tools.monitoring.ObjectExplorer$PrimitiveMarker

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.