org.shaman.rpg.editor.dbviewer.TreeTableModelFactory.java Source code

Java tutorial

Introduction

Here is the source code for org.shaman.rpg.editor.dbviewer.TreeTableModelFactory.java

Source

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package org.shaman.rpg.editor.dbviewer;

import java.awt.Dimension;
import java.beans.*;
import java.io.File;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import org.apache.commons.lang.ArrayUtils;
import org.jdesktop.swingx.treetable.AbstractTreeTableModel;
import org.jdesktop.swingx.treetable.TreeTableModel;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.openide.filesystems.FileUtil;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle;
import org.shaman.database.*;
import org.shaman.database.io.IOFactory;
import org.shaman.database.io.Input;
import org.shaman.rpg.editor.utilities.dataobject.DatabaseDataObject;

/**
 * This class loads a database data object and creates a {@link TreeTableModel}
 * from that.
 * @author Sebastian Weiss
 */
public class TreeTableModelFactory {
    private static final Logger LOG = Logger.getLogger(TreeTableModelFactory.class.getName());

    private TreeTableModelFactory() {
    }

    /**
     * Columns are:
     * Tree, Name, Class, Value.
     */
    public static final int COLUMN_COUNT = 4;
    public static final String[] COLUMN_NAMES = {
            NbBundle.getMessage(TreeTableModelFactory.class, "DatabaseTable.Header.Tree"),
            NbBundle.getMessage(TreeTableModelFactory.class, "DatabaseTable.Header.Name"),
            NbBundle.getMessage(TreeTableModelFactory.class, "DatabaseTable.Header.Class"),
            NbBundle.getMessage(TreeTableModelFactory.class, "DatabaseTable.Header.Value") };

    /**
     * Loads the database and creates a tree table model that displays the contents.
     * This method might take a while, so call this method in a worker thread.
     * @param obj the database to load
     * @return the tree table model
     */
    public static <T extends Record> TreeTableModel createModel(DatabaseDataObject<T> obj) {
        //load database
        Database<T> db;
        File file = FileUtil.toFile(obj.getPrimaryFile());
        try (Input in = IOFactory.createFileInput(file)) {
            ErrorCollector collector = new ErrorCollector();
            db = new Database<>(in, collector);
            if (!collector.entries.isEmpty()) {
                //contains errors
                showErrors(collector);
            }
        } catch (Exception e) {
            Exceptions.printStackTrace(e);
            return new ErrorModel(e);
        }
        return new DatabaseTableModel(db.getRoot());
    }

    private static void showErrors(ErrorCollector collector) {
        JTextArea area = new JTextArea();
        for (Map.Entry<String, Integer> e : collector.entries.entrySet()) {
            area.append(e.getValue().toString());
            area.append("x: ");
            area.append(e.getKey());
            area.append("\n");
        }
        JScrollPane pane = new JScrollPane(area);
        pane.setMinimumSize(new Dimension(200, 50));
        DialogDisplayer.getDefault()
                .notifyLater(new NotifyDescriptor.Message(pane, NotifyDescriptor.ERROR_MESSAGE));
    }

    private static class ErrorModel extends AbstractTreeTableModel {
        private final Exception e;

        private ErrorModel(Exception e) {
            super("unable to load database");
            this.e = e;
        }

        @Override
        public int getColumnCount() {
            return 1;
        }

        @Override
        public Object getValueAt(Object o, int i) {
            return "unable to load database: " + e.getLocalizedMessage();
        }

        @Override
        public Object getChild(Object parent, int index) {
            return null;
        }

        @Override
        public int getChildCount(Object parent) {
            return 0;
        }

        @Override
        public int getIndexOfChild(Object parent, Object child) {
            return -1;
        }

        @Override
        public String getColumnName(int column) {
            return "Error";
        }

    }

    private static class Parameter {
        private final Record record;
        private final RecordTemplate.Attribute attribute;

        private Parameter(Record record, RecordTemplate.Attribute attribute) {
            this.record = record;
            this.attribute = attribute;
        }

    }

    private static class NullItem {
        private final String name;
        private final String id;

        private NullItem(String name, String id) {
            this.name = name;
            this.id = id;
        }

    }

    private static class DatabaseTableModel extends AbstractTreeTableModel {

        private DatabaseTableModel(Record root) {
            super(root);
        }

        @Override
        public int getColumnCount() {
            return COLUMN_COUNT;
        }

        @Override
        public Object getValueAt(Object o, int i) {
            if (o instanceof Record) {
                Record rec = (Record) o;
                //it is a record
                switch (i) {
                case 0:
                    return o.getClass().getSimpleName();
                case 1:
                    return DatabaseSystem.intToName(DatabaseSystem.getRecordTemplate(rec.getClass()).getRecordID());
                case 2:
                    return rec.getClass().getName();
                case 3:
                    return o.toString();
                }
            } else if (o instanceof Parameter) {
                //it is a parameter
                Parameter p = (Parameter) o;
                switch (i) {
                case 0:
                    Method getter = p.attribute.getGetter();
                    return getFieldName(getter);
                case 1:
                    return DatabaseSystem.intToName(p.attribute.getID());
                case 2:
                    return p.attribute.getGetter().getReturnType().getName();
                case 3:
                    return getParameterValue(p.attribute.getValue(p.record));
                }
            } else if (o instanceof NullItem) {
                NullItem ei = (NullItem) o;
                switch (i) {
                case 0:
                    return ei.name;
                case 1:
                    return ei.id;
                case 2:
                    return "";
                case 3:
                    return "";
                }
            }
            throw new IllegalArgumentException("illegal column index " + i + " for node " + o);
        }

        private String getParameterValue(Object value) {
            if (value == null) {
                return "null";
            } else if (value.getClass().isArray()) {
                return ArrayUtils.toString(value);
            } else if (value instanceof ByteBuffer) {
                ByteBuffer buf = (ByteBuffer) value;
                StringBuilder str = new StringBuilder(buf.capacity());
                buf.rewind();
                boolean b = false;
                while (buf.hasRemaining()) {
                    if (b)
                        str.append(",");
                    b = true;
                    str.append(String.format("%02x", buf.get()));
                }
                return str.toString();
            } else {
                return String.valueOf(value);
            }
        }

        @Override
        public boolean isLeaf(Object node) {
            return (node instanceof Parameter);
        }

        @Override
        public Object getChild(Object parent, int index) {
            if (parent instanceof Parameter) {
                throw new IllegalArgumentException("there are no children for a leaf node");
            }
            Record rec = (Record) parent;
            RecordTemplate template = DatabaseSystem.getRecordTemplate(rec.getClass());
            List<? extends RecordTemplate.Attribute> attributes = template.getAttributes();
            if (index < attributes.size()) {
                return new Parameter(rec, attributes.get(index));
            } else {
                Group g = (Group) rec;
                Record sg = g.getSubgroup(index - attributes.size());
                if (sg == null) {
                    return new NullItem("null group", "index: " + (index - attributes.size()));
                } else {
                    return sg;
                }
            }
        }

        @Override
        public int getChildCount(Object parent) {
            if (parent instanceof Parameter) {
                return 0;
            }
            Record rec = (Record) parent;
            RecordTemplate template = DatabaseSystem.getRecordTemplate(rec.getClass());
            int count = template.getAttributes().size();
            if (rec instanceof Group) {
                count += ((Group) rec).getSubgroupCount();
            }
            return count;
        }

        @Override
        public int getIndexOfChild(Object parent, Object child) {
            if (parent == null || child == null || !(parent instanceof Record)) {
                return -1;
            }
            Record rec = (Record) parent;
            RecordTemplate template = DatabaseSystem.getRecordTemplate(rec.getClass());
            List<? extends RecordTemplate.Attribute> attributes = template.getAttributes();
            int index = attributes.indexOf(child);
            if (index >= 0) {
                return index;
            } else {
                if (rec instanceof Group) {
                    Group g = (Group) rec;
                    Record[] subgroups = g.getAllSubgroups();
                    index = ArrayUtils.indexOf(subgroups, child);
                    return index;
                } else {
                    return -1;
                }
            }
        }

        @Override
        public boolean isCellEditable(Object node, int column) {
            return false;
        }

        @Override
        public Class<?> getColumnClass(int column) {
            return String.class;
        }

        @Override
        public String getColumnName(int column) {
            return COLUMN_NAMES[column];
        }

    }

    private static String getFieldName(Method method) {
        try {
            Class<?> clazz = method.getDeclaringClass();
            BeanInfo info = Introspector.getBeanInfo(clazz);
            PropertyDescriptor[] props = info.getPropertyDescriptors();
            for (PropertyDescriptor pd : props) {
                if (method.equals(pd.getWriteMethod()) || method.equals(pd.getReadMethod())) {
                    //               System.out.println(pd.getDisplayName());
                    return pd.getName();
                }
            }
        } catch (Exception e) {
            LOG.log(Level.FINE, "unable to get field name for method " + method, e);
        }

        return method.getName();
    }
}