/*
 * Copyright (c) 2004, 2008, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code 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.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package sun.tools.jconsole.inspector;


import java.awt.Component;
import java.awt.EventQueue;
import java.awt.Dimension;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;

import java.lang.reflect.Array;

import java.util.EventObject;
import java.util.HashMap;
import java.util.WeakHashMap;

import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.management.JMException;
import javax.management.MBeanInfo;
import javax.management.MBeanAttributeInfo;
import javax.management.AttributeList;
import javax.management.Attribute;
import javax.management.openmbean.CompositeData;
import javax.management.openmbean.TabularData;

import javax.swing.JComponent;
import javax.swing.JOptionPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SwingWorker;
import javax.swing.event.ChangeEvent;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableModel;

import sun.tools.jconsole.Resources;
import sun.tools.jconsole.MBeansTab;
import sun.tools.jconsole.JConsole;
import sun.tools.jconsole.ProxyClient.SnapshotMBeanServerConnection;

/*IMPORTANT :
  There is a deadlock issue there if we don't synchronize well loadAttributes,
  refresh attributes and empty table methods since a UI thread can call
  loadAttributes and at the same time a JMX notification can raise an
  emptyTable. Since there are synchronization in the JMX world it's
  COMPULSORY to not call the JMX world in synchronized blocks */
@SuppressWarnings("serial")
public class XMBeanAttributes extends XTable {

    final Logger LOGGER =
            Logger.getLogger(XMBeanAttributes.class.getPackage().getName());

    private final static String[] columnNames =
    {Resources.getText("Name"),
     Resources.getText("Value")};

    private XMBean mbean;
    private MBeanInfo mbeanInfo;
    private MBeanAttributeInfo[] attributesInfo;
    private HashMap<String, Object> attributes;
    private HashMap<String, Object> unavailableAttributes;
    private HashMap<String, Object> viewableAttributes;
    private WeakHashMap<XMBean, HashMap<String, ZoomedCell>> viewersCache =
            new WeakHashMap<XMBean, HashMap<String, ZoomedCell>>();
    private final TableModelListener attributesListener;
    private MBeansTab mbeansTab;
    private TableCellEditor valueCellEditor = new ValueCellEditor();
    private int rowMinHeight = -1;
    private AttributesMouseListener mouseListener = new AttributesMouseListener();

    private static TableCellEditor editor =
            new Utils.ReadOnlyTableCellEditor(new JTextField());

    public XMBeanAttributes(MBeansTab mbeansTab) {
        super();
        this.mbeansTab = mbeansTab;
        ((DefaultTableModel)getModel()).setColumnIdentifiers(columnNames);
        attributesListener = new AttributesListener(this);
        getModel().addTableModelListener(attributesListener);
        getColumnModel().getColumn(NAME_COLUMN).setPreferredWidth(40);

        addMouseListener(mouseListener);
        getTableHeader().setReorderingAllowed(false);
        setColumnEditors();
        addKeyListener(new Utils.CopyKeyAdapter());
    }

    @Override
    public synchronized Component prepareRenderer(TableCellRenderer renderer,
                                                  int row, int column) {
        //In case we have a repaint thread that is in the process of
        //repainting an obsolete table, just ignore the call.
        //It can happen when MBean selection is switched at a very quick rate
        if(row >= getRowCount())
            return null;
        else
            return super.prepareRenderer(renderer, row, column);
    }

    void updateRowHeight(Object obj, int row) {
        ZoomedCell cell = null;
        if(obj instanceof ZoomedCell) {
            cell = (ZoomedCell) obj;
            if(cell.isInited())
                setRowHeight(row, cell.getHeight());
            else
                if(rowMinHeight != - 1)
                    setRowHeight(row, rowMinHeight);
        } else
            if(rowMinHeight != - 1)
                setRowHeight(row, rowMinHeight);
    }

    @Override
    public synchronized TableCellRenderer getCellRenderer(int row,
            int column) {
        //In case we have a repaint thread that is in the process of
        //repainting an obsolete table, just ignore the call.
        //It can happen when MBean selection is switched at a very quick rate
        if (row >= getRowCount()) {
            return null;
        } else {
            if (column == VALUE_COLUMN) {
                Object obj = getModel().getValueAt(row, column);
                if (obj instanceof ZoomedCell) {
                    ZoomedCell cell = (ZoomedCell) obj;
                    if (cell.isInited()) {
                        DefaultTableCellRenderer renderer =
                                (DefaultTableCellRenderer) cell.getRenderer();
                        renderer.setToolTipText(getToolTip(row,column));
                        return renderer;
                    }
                }
            }
            DefaultTableCellRenderer renderer = (DefaultTableCellRenderer)
                super.getCellRenderer(row, column);
            if (!isCellError(row, column)) {
                if (!(isColumnEditable(column) && isWritable(row) &&
                      Utils.isEditableType(getClassName(row)))) {
                    renderer.setForeground(getDefaultColor());
                }
            }
            return renderer;
        }
    }

    private void setColumnEditors() {
        TableColumnModel tcm = getColumnModel();
        for (int i = 0; i < columnNames.length; i++) {
            TableColumn tc = tcm.getColumn(i);
            if (isColumnEditable(i)) {
                tc.setCellEditor(valueCellEditor);
            } else {
                tc.setCellEditor(editor);
            }
        }
    }

    public void cancelCellEditing() {
        if (LOGGER.isLoggable(Level.FINER)) {
            LOGGER.finer("Cancel Editing Row: "+getEditingRow());
        }
        final TableCellEditor tableCellEditor = getCellEditor();
        if (tableCellEditor != null) {
            tableCellEditor.cancelCellEditing();
        }
    }

    public void stopCellEditing() {
        if (LOGGER.isLoggable(Level.FINER)) {
            LOGGER.finer("Stop Editing Row: "+getEditingRow());
        }
        final TableCellEditor tableCellEditor = getCellEditor();
        if (tableCellEditor != null) {
            tableCellEditor.stopCellEditing();
        }
    }

    @Override
    public final boolean editCellAt(final int row, final int column, EventObject e) {
        if (LOGGER.isLoggable(Level.FINER)) {
            LOGGER.finer("editCellAt(row="+row+", col="+column+
                    ", e="+e+")");
        }
        if (JConsole.isDebug()) {
            System.err.println("edit: "+getValueName(row)+"="+getValue(row));
        }
        boolean retVal = super.editCellAt(row, column, e);
        if (retVal) {
            final TableCellEditor tableCellEditor =
                    getColumnModel().getColumn(column).getCellEditor();
            if (tableCellEditor == valueCellEditor) {
                ((JComponent) tableCellEditor).requestFocus();
            }
        }
        return retVal;
    }

    @Override
    public boolean isCellEditable(int row, int col) {
        // All the cells in non-editable columns are editable
        if (!isColumnEditable(col)) {
            return true;
        }
        // Maximized zoomed cells are editable
        Object obj = getModel().getValueAt(row, col);
        if (obj instanceof ZoomedCell) {
            ZoomedCell cell = (ZoomedCell) obj;
            return cell.isMaximized();
        }
        return true;
    }

    @Override
    public void setValueAt(Object value, int row, int column) {
        if (!isCellError(row, column) && isColumnEditable(column) &&
            isWritable(row) && Utils.isEditableType(getClassName(row))) {
            if (JConsole.isDebug()) {
                System.err.println("validating [row="+row+", column="+column+
                        "]: "+getValueName(row)+"="+value);
            }
            super.setValueAt(value, row, column);
        }
    }

    //Table methods

    public boolean isTableEditable() {
        return true;
    }

    public void setTableValue(Object value, int row) {
    }

    public boolean isColumnEditable(int column) {
        if (column < getColumnCount()) {
            return getColumnName(column).equals(Resources.getText("Value"));
        }
        else {
            return false;
        }
    }

    public String getClassName(int row) {
        int index = convertRowToIndex(row);
        if (index != -1) {
            return attributesInfo[index].getType();
        }
        else {
            return null;
        }
    }


    public String getValueName(int row) {
        int index = convertRowToIndex(row);
        if (index != -1) {
            return attributesInfo[index].getName();
        }
        else {
            return null;
        }
    }

    public Object getValue(int row) {
        final Object val = ((DefaultTableModel) getModel())
                .getValueAt(row, VALUE_COLUMN);
        return val;
    }

    //tool tip only for editable column
    @Override
    public String getToolTip(int row, int column) {
        if (isCellError(row, column)) {
            return (String) unavailableAttributes.get(getValueName(row));
        }
        if (isColumnEditable(column)) {
            Object value = getValue(row);
            String tip = null;
            if (value != null) {
                tip = value.toString();
                if(isAttributeViewable(row, VALUE_COLUMN))
                    tip = Resources.getText("Double click to expand/collapse")+
                        ". " + tip;
            }

            return tip;
        }

        if(column == NAME_COLUMN) {
            int index = convertRowToIndex(row);
            if (index != -1) {
                return attributesInfo[index].getDescription();
            }
        }
        return null;
    }

    public synchronized boolean isWritable(int row) {
        int index = convertRowToIndex(row);
        if (index != -1) {
            return (attributesInfo[index].isWritable());
        }
        else {
            return false;
        }
    }

    /**
     * Override JTable method in order to make any call to this method
     * atomic with TableModel elements.
     */
    @Override
    public synchronized int getRowCount() {
        return super.getRowCount();
    }

    public synchronized boolean isReadable(int row) {
        int index = convertRowToIndex(row);
        if (index != -1) {
            return (attributesInfo[index].isReadable());
        }
        else {
            return false;
        }
    }

    public synchronized boolean isCellError(int row, int col) {
        return (isColumnEditable(col) &&
                (unavailableAttributes.containsKey(getValueName(row))));
    }

    public synchronized boolean isAttributeViewable(int row, int col) {
        boolean isViewable = false;
        if(col == VALUE_COLUMN) {
            Object obj = getModel().getValueAt(row, col);
            if(obj instanceof ZoomedCell)
                isViewable = true;
        }

        return isViewable;
    }

    // Call this in EDT
    public void loadAttributes(final XMBean mbean, final MBeanInfo mbeanInfo) {

        final SwingWorker<Runnable,Void> load =
                new SwingWorker<Runnable,Void>() {
            @Override
            protected Runnable doInBackground() throws Exception {
                return doLoadAttributes(mbean,mbeanInfo);
            }

            @Override
            protected void done() {
                try {
                    final Runnable updateUI = get();
                    if (updateUI != null) updateUI.run();
                } catch (RuntimeException x) {
                    throw x;
                } catch (ExecutionException x) {
                    if(JConsole.isDebug()) {
                       System.err.println(
                               "Exception raised while loading attributes: "
                               +x.getCause());
                       x.printStackTrace();
                    }
                } catch (InterruptedException x) {
                    if(JConsole.isDebug()) {
                       System.err.println(
                            "Interrupted while loading attributes: "+x);
                       x.printStackTrace();
                    }
                }
            }

        };
        mbeansTab.workerAdd(load);
    }

    // Don't call this in EDT, but execute returned Runnable inside
    // EDT - typically in the done() method of a SwingWorker
    // This method can return null.
    private Runnable doLoadAttributes(final XMBean mbean, MBeanInfo infoOrNull)
        throws JMException, IOException {
        // To avoid deadlock with events coming from the JMX side,
        // we retrieve all JMX stuff in a non synchronized block.

        if(mbean == null) return null;
        final MBeanInfo curMBeanInfo =
                (infoOrNull==null)?mbean.getMBeanInfo():infoOrNull;

        final MBeanAttributeInfo[] attrsInfo = curMBeanInfo.getAttributes();
        final HashMap<String, Object> attrs =
            new HashMap<String, Object>(attrsInfo.length);
        final HashMap<String, Object> unavailableAttrs =
            new HashMap<String, Object>(attrsInfo.length);
        final HashMap<String, Object> viewableAttrs =
            new HashMap<String, Object>(attrsInfo.length);
        AttributeList list = null;

        try {
            list = mbean.getAttributes(attrsInfo);
        }catch(Exception e) {
            if (JConsole.isDebug()) {
                System.err.println("Error calling getAttributes() on MBean \"" +
                                   mbean.getObjectName() + "\". JConsole will " +
                                   "try to get them individually calling " +
                                   "getAttribute() instead. Exception:");
                e.printStackTrace(System.err);
            }
            list = new AttributeList();
            //Can't load all attributes, do it one after each other.
            for(int i = 0; i < attrsInfo.length; i++) {
                String name = null;
                try {
                    name = attrsInfo[i].getName();
                    Object value =
                        mbean.getMBeanServerConnection().
                        getAttribute(mbean.getObjectName(), name);
                    list.add(new Attribute(name, value));
                }catch(Exception ex) {
                    if(attrsInfo[i].isReadable()) {
                        unavailableAttrs.put(name,
                                Utils.getActualException(ex).toString());
                    }
                }
            }
        }
        try {
            int att_length = list.size();
            for (int i=0;i<att_length;i++) {
                Attribute attribute = (Attribute) list.get(i);
                if(isViewable(attribute)) {
                    viewableAttrs.put(attribute.getName(),
                                           attribute.getValue());
                }
                else
                    attrs.put(attribute.getName(),attribute.getValue());

            }
            // if not all attributes are accessible,
            // check them one after the other.
            if (att_length < attrsInfo.length) {
                for (int i=0;i<attrsInfo.length;i++) {
                    MBeanAttributeInfo attributeInfo = attrsInfo[i];
                    if (!attrs.containsKey(attributeInfo.getName()) &&
                        !viewableAttrs.containsKey(attributeInfo.
                                                        getName()) &&
                        !unavailableAttrs.containsKey(attributeInfo.
                                                           getName())) {
                        if (attributeInfo.isReadable()) {
                            // getAttributes didn't help resolving the
                            // exception.
                            // We must call it again to understand what
                            // went wrong.
                            try {
                                Object v =
                                    mbean.getMBeanServerConnection().getAttribute(
                                    mbean.getObjectName(), attributeInfo.getName());
                                //What happens if now it is ok?
                                // Be pragmatic, add it to readable...
                                attrs.put(attributeInfo.getName(),
                                               v);
                            }catch(Exception e) {
                                //Put the exception that will be displayed
                                // in tooltip
                                unavailableAttrs.put(attributeInfo.getName(),
                                        Utils.getActualException(e).toString());
                            }
                        }
                    }
                }
            }
        }
        catch(Exception e) {
            //sets all attributes unavailable except the writable ones
            for (int i=0;i<attrsInfo.length;i++) {
                MBeanAttributeInfo attributeInfo = attrsInfo[i];
                if (attributeInfo.isReadable()) {
                    unavailableAttrs.put(attributeInfo.getName(),
                                              Utils.getActualException(e).
                                              toString());
                }
            }
        }
        //end of retrieval

        //one update at a time
        return new Runnable() {
            public void run() {
                synchronized (XMBeanAttributes.this) {
                    XMBeanAttributes.this.mbean = mbean;
                    XMBeanAttributes.this.mbeanInfo = curMBeanInfo;
                    XMBeanAttributes.this.attributesInfo = attrsInfo;
                    XMBeanAttributes.this.attributes = attrs;
                    XMBeanAttributes.this.unavailableAttributes = unavailableAttrs;
                    XMBeanAttributes.this.viewableAttributes = viewableAttrs;

                    DefaultTableModel tableModel =
                            (DefaultTableModel) getModel();

                    // add attribute information
                    emptyTable(tableModel);

                    addTableData(tableModel,
                            mbean,
                            attrsInfo,
                            attrs,
                            unavailableAttrs,
                            viewableAttrs);

                    // update the model with the new data
                    tableModel.newDataAvailable(new TableModelEvent(tableModel));
                    // re-register for change events
                    tableModel.addTableModelListener(attributesListener);
                }
            }
        };
    }

    void collapse(String attributeName, final Component c) {
        final int row = getSelectedRow();
        Object obj = getModel().getValueAt(row, VALUE_COLUMN);
        if(obj instanceof ZoomedCell) {
            cancelCellEditing();
            ZoomedCell cell = (ZoomedCell) obj;
            cell.reset();
            setRowHeight(row,
                         cell.getHeight());
            editCellAt(row,
                       VALUE_COLUMN);
            invalidate();
            repaint();
        }
    }

    ZoomedCell updateZoomedCell(int row,
                                int col) {
        Object obj = getModel().getValueAt(row, VALUE_COLUMN);
        ZoomedCell cell = null;
        if(obj instanceof ZoomedCell) {
            cell = (ZoomedCell) obj;
            if(!cell.isInited()) {
                Object elem = cell.getValue();
                String attributeName =
                    (String) getModel().getValueAt(row,
                                                   NAME_COLUMN);
                Component comp = mbeansTab.getDataViewer().
                        createAttributeViewer(elem, mbean, attributeName, this);
                if(comp != null){
                    if(rowMinHeight == -1)
                        rowMinHeight = getRowHeight(row);

                    cell.init(super.getCellRenderer(row, col),
                              comp,
                              rowMinHeight);

                    mbeansTab.getDataViewer().registerForMouseEvent(
                            comp, mouseListener);
                } else
                    return cell;
            }

            cell.switchState();
            setRowHeight(row,
                         cell.getHeight());

            if(!cell.isMaximized()) {
                cancelCellEditing();
                //Back to simple editor.
                editCellAt(row,
                           VALUE_COLUMN);
            }

            invalidate();
            repaint();
        }
        return cell;
    }

    // This is called by XSheet when the "refresh" button is pressed.
    // In this case we will commit any pending attribute values by
    // calling 'stopCellEditing'.
    //
    public void refreshAttributes() {
         refreshAttributes(true);
    }

    // refreshAttributes(false) is called by tableChanged().
    // in this case we must not call stopCellEditing, because it's already
    // been called - e.g.
    // lostFocus/mousePressed -> stopCellEditing -> setValueAt -> tableChanged
    //                        -> refreshAttributes(false)
    //
    // Can be called in EDT - as long as the implementation of
    // mbeansTab.getCachedMBeanServerConnection() and mbsc.flush() doesn't
    // change
    //
    private void refreshAttributes(final boolean stopCellEditing) {
         SwingWorker<Void,Void> sw = new SwingWorker<Void,Void>() {

            @Override
            protected Void doInBackground() throws Exception {
                SnapshotMBeanServerConnection mbsc =
                mbeansTab.getSnapshotMBeanServerConnection();
                mbsc.flush();
                return null;
            }

            @Override
            protected void done() {
                try {
                    get();
                    if (stopCellEditing) stopCellEditing();
                    loadAttributes(mbean, mbeanInfo);
                } catch (Exception x) {
                    if (JConsole.isDebug()) {
                        x.printStackTrace();
                    }
                }
            }
         };
         mbeansTab.workerAdd(sw);
     }
    // We need to call stop editing here - otherwise edits are lost
    // when resizing the table.
    //
    @Override
    public void columnMarginChanged(ChangeEvent e) {
        if (isEditing()) stopCellEditing();
        super.columnMarginChanged(e);
    }

    // We need to call stop editing here - otherwise the edited value
    // is transferred to the wrong row...
    //
    @Override
    void sortRequested(int column) {
        if (isEditing()) stopCellEditing();
        super.sortRequested(column);
    }


    @Override
    public synchronized void emptyTable() {
         emptyTable((DefaultTableModel)getModel());
     }

    // Call this in synchronized block.
    private void emptyTable(DefaultTableModel model) {
         model.removeTableModelListener(attributesListener);
         super.emptyTable();
    }

    private boolean isViewable(Attribute attribute) {
        Object data = attribute.getValue();
        return XDataViewer.isViewableValue(data);

    }

    synchronized void removeAttributes() {
        if (attributes != null) {
            attributes.clear();
        }
        if (unavailableAttributes != null) {
            unavailableAttributes.clear();
        }
        if (viewableAttributes != null) {
            viewableAttributes.clear();
        }
        mbean = null;
    }

    private ZoomedCell getZoomedCell(XMBean mbean, String attribute, Object value) {
        synchronized (viewersCache) {
            HashMap<String, ZoomedCell> viewers;
            if (viewersCache.containsKey(mbean)) {
                viewers = viewersCache.get(mbean);
            } else {
                viewers = new HashMap<String, ZoomedCell>();
            }
            ZoomedCell cell;
            if (viewers.containsKey(attribute)) {
                cell = viewers.get(attribute);
                cell.setValue(value);
                if (cell.isMaximized() && cell.getType() != XDataViewer.NUMERIC) {
                    // Plotters are the only viewers with auto update capabilities.
                    // Other viewers need to be updated manually.
                    Component comp =
                        mbeansTab.getDataViewer().createAttributeViewer(
                            value, mbean, attribute, XMBeanAttributes.this);
                    cell.init(cell.getMinRenderer(), comp, cell.getMinHeight());
                    mbeansTab.getDataViewer().registerForMouseEvent(comp, mouseListener);
                }
            } else {
                cell = new ZoomedCell(value);
                viewers.put(attribute, cell);
            }
            viewersCache.put(mbean, viewers);
            return cell;
        }
    }

    //will be called in a synchronzed block
    protected void addTableData(DefaultTableModel tableModel,
                                XMBean mbean,
                                MBeanAttributeInfo[] attributesInfo,
                                HashMap<String, Object> attributes,
                                HashMap<String, Object> unavailableAttributes,
                                HashMap<String, Object> viewableAttributes) {

        Object rowData[] = new Object[2];
        int col1Width = 0;
        int col2Width = 0;
        for (int i = 0; i < attributesInfo.length; i++) {
            rowData[0] = (attributesInfo[i].getName());
            if (unavailableAttributes.containsKey(rowData[0])) {
                rowData[1] = Resources.getText("Unavailable");
            } else if (viewableAttributes.containsKey(rowData[0])) {
                rowData[1] = viewableAttributes.get(rowData[0]);
                if (!attributesInfo[i].isWritable() ||
                    !Utils.isEditableType(attributesInfo[i].getType())) {
                    rowData[1] = getZoomedCell(mbean, (String) rowData[0], rowData[1]);
                }
            } else {
                rowData[1] = attributes.get(rowData[0]);
            }

            tableModel.addRow(rowData);

            //Update column width
            //
            String str = null;
            if(rowData[0] != null) {
                str = rowData[0].toString();
                if(str.length() > col1Width)
                    col1Width = str.length();
            }
            if(rowData[1] != null) {
                str = rowData[1].toString();
                if(str.length() > col2Width)
                    col2Width = str.length();
            }
        }
        updateColumnWidth(col1Width, col2Width);
    }

    private void updateColumnWidth(int col1Width, int col2Width) {
        TableColumnModel colModel = getColumnModel();

        //Get the column at index pColumn, and set its preferred width.
        col1Width = col1Width * 7;
        col2Width = col2Width * 7;
        if(col1Width + col2Width <
           (int) getPreferredScrollableViewportSize().getWidth())
            col2Width = (int) getPreferredScrollableViewportSize().getWidth()
                - col1Width;

        colModel.getColumn(NAME_COLUMN).setPreferredWidth(50);
    }

    class AttributesMouseListener extends MouseAdapter {

        @Override
        public void mousePressed(MouseEvent e) {
            if(e.getButton() == MouseEvent.BUTTON1) {
                if(e.getClickCount() >= 2) {

                    int row = XMBeanAttributes.this.getSelectedRow();
                    int col = XMBeanAttributes.this.getSelectedColumn();
                    if(col != VALUE_COLUMN) return;
                    if(col == -1 || row == -1) return;

                    XMBeanAttributes.this.updateZoomedCell(row, col);
                }
            }
        }
    }

    @SuppressWarnings("serial")
    class ValueCellEditor extends XTextFieldEditor {
        // implements javax.swing.table.TableCellEditor
        @Override
        public Component getTableCellEditorComponent(JTable table,
                                                     Object value,
                                                     boolean isSelected,
                                                     int row,
                                                     int column) {
            Object val = value;
            if(column == VALUE_COLUMN) {
                Object obj = getModel().getValueAt(row,
                                                   column);
                if(obj instanceof ZoomedCell) {
                    ZoomedCell cell = (ZoomedCell) obj;
                    if(cell.getRenderer() instanceof MaximizedCellRenderer) {
                        MaximizedCellRenderer zr =
                            (MaximizedCellRenderer) cell.getRenderer();
                        return zr.getComponent();
                    }
                } else {
                    Component comp = super.getTableCellEditorComponent(
                            table, val, isSelected, row, column);
                    if (isCellError(row, column) ||
                        !isWritable(row) ||
                        !Utils.isEditableType(getClassName(row))) {
                        textField.setEditable(false);
                    }
                    return comp;
                }
            }
            return super.getTableCellEditorComponent(table,
                                                     val,
                                                     isSelected,
                                                     row,
                                                     column);
        }
        @Override
        public boolean stopCellEditing() {
            int editingRow = getEditingRow();
            int editingColumn = getEditingColumn();
            if (editingColumn == VALUE_COLUMN) {
                Object obj = getModel().getValueAt(editingRow, editingColumn);
                if (obj instanceof ZoomedCell) {
                    ZoomedCell cell = (ZoomedCell) obj;
                    if (cell.isMaximized()) {
                        this.cancelCellEditing();
                        return true;
                    }
                }
            }
            return super.stopCellEditing();
        }
    }

    @SuppressWarnings("serial")
    class MaximizedCellRenderer extends  DefaultTableCellRenderer {
        Component comp;
        MaximizedCellRenderer(Component comp) {
            this.comp = comp;
            Dimension d = comp.getPreferredSize();
            if (d.getHeight() > 220) {
                comp.setPreferredSize(new Dimension((int) d.getWidth(), 220));
            }
        }
        @Override
        public Component getTableCellRendererComponent(JTable table,
                                                       Object value,
                                                       boolean isSelected,
                                                       boolean hasFocus,
                                                       int row,
                                                       int column) {
            return comp;
        }
        public Component getComponent() {
            return comp;
        }
    }

    class ZoomedCell {
        TableCellRenderer minRenderer;
        MaximizedCellRenderer maxRenderer;
        int minHeight;
        boolean minimized = true;
        boolean init = false;
        int type;
        Object value;
        ZoomedCell(Object value) {
            type = XDataViewer.getViewerType(value);
            this.value = value;
        }

        boolean isInited() {
            return init;
        }

        Object getValue() {
            return value;
        }

        void setValue(Object value) {
            this.value = value;
        }

        void init(TableCellRenderer minRenderer,
                  Component maxComponent,
                  int minHeight) {
            this.minRenderer = minRenderer;
            this.maxRenderer = new MaximizedCellRenderer(maxComponent);

            this.minHeight = minHeight;
            init = true;
        }

        int getType() {
            return type;
        }

        void reset() {
            init = false;
            minimized = true;
        }

        void switchState() {
            minimized = !minimized;
        }
        boolean isMaximized() {
            return !minimized;
        }
        void minimize() {
            minimized = true;
        }

        void maximize() {
            minimized = false;
        }

        int getHeight() {
            if(minimized) return minHeight;
            else
                return (int) maxRenderer.getComponent().
                    getPreferredSize().getHeight() ;
        }

        int getMinHeight() {
            return minHeight;
        }

        @Override
        public String toString() {

            if(value == null) return null;

            if(value.getClass().isArray()) {
                String name =
                    Utils.getArrayClassName(value.getClass().getName());
                int length = Array.getLength(value);
                return name + "[" + length +"]";
            }

            if(value instanceof CompositeData ||
               value instanceof TabularData)
                return value.getClass().getName();

            return value.toString();
        }

        TableCellRenderer getRenderer() {
            if(minimized) return minRenderer;
            else return maxRenderer;
        }

        TableCellRenderer getMinRenderer() {
            return minRenderer;
        }
    }

    class AttributesListener implements  TableModelListener {

        private Component component;

        public AttributesListener(Component component) {
            this.component = component;
        }

        // Call this in EDT
        public void tableChanged(final TableModelEvent e) {
            // only post changes to the draggable column
            if (isColumnEditable(e.getColumn())) {
                final TableModel model = (TableModel)e.getSource();
                Object tableValue = model.getValueAt(e.getFirstRow(),
                                                 e.getColumn());

                if (LOGGER.isLoggable(Level.FINER)) {
                    LOGGER.finer("tableChanged: firstRow="+e.getFirstRow()+
                        ", lastRow="+e.getLastRow()+", column="+e.getColumn()+
                        ", value="+tableValue);
                }
                // if it's a String, try construct new value
                // using the defined type.
                if (tableValue instanceof String) {
                    try {
                        tableValue =
                            Utils.createObjectFromString(getClassName(e.getFirstRow()), // type
                            (String)tableValue);// value
                    } catch (Throwable ex) {
                        popupAndLog(ex,"tableChanged",
                                "Problem setting attribute");
                    }
                }
                final String attributeName = getValueName(e.getFirstRow());
                final Attribute attribute =
                      new Attribute(attributeName,tableValue);
                setAttribute(attribute, "tableChanged");
            }
        }

        // Call this in EDT
        private void setAttribute(final Attribute attribute, final String method) {
            final SwingWorker<Void,Void> setAttribute =
                    new SwingWorker<Void,Void>() {
                @Override
                protected Void doInBackground() throws Exception {
                    try {
                        if (JConsole.isDebug()) {
                            System.err.println("setAttribute("+
                                    attribute.getName()+
                                "="+attribute.getValue()+")");
                        }
                        mbean.setAttribute(attribute);
                    } catch (Throwable ex) {
                        popupAndLog(ex,method,"Problem setting attribute");
                    }
                    return null;
                }
                @Override
                protected void done() {
                    try {
                        get();
                    } catch (Exception x) {
                        if (JConsole.isDebug())
                            x.printStackTrace();
                    }
                    refreshAttributes(false);
                }

            };
            mbeansTab.workerAdd(setAttribute);
        }

        // Call this outside EDT
        private void popupAndLog(Throwable ex, String method, String key) {
            ex = Utils.getActualException(ex);
            if (JConsole.isDebug()) ex.printStackTrace();

            String message = (ex.getMessage() != null) ? ex.getMessage()
                    : ex.toString();
            EventQueue.invokeLater(
                    new ThreadDialog(component, message+"\n",
                                     Resources.getText(key),
                                     JOptionPane.ERROR_MESSAGE));
        }
    }
}
