    001/*****************************************************************************
    002 * Copyright by The HDF Group.                                               *
    003 * Copyright by the Board of Trustees of the University of Illinois.         *
    004 * All rights reserved.                                                      *
    005 *                                                                           *
    006 * This file is part of the HDF Java Products distribution.                  *
    007 * The full copyright notice, including terms governing use, modification,   *
    008 * and redistribution, is contained in the COPYING file, which can be found  *
    009 * at the root of the source code distribution tree,                         *
    010 * or in https://www.hdfgroup.org/licenses.                                  *
    011 * If you do not have access to either file, you may request a copy from     *
    012 * help@hdfgroup.org.                                                        *
    013 ****************************************************************************/
    014
    015package hdf.view.MetaDataView;
    016
    017import java.lang.reflect.Array;
    018
    019import org.slf4j.Logger;
    020import org.slf4j.LoggerFactory;
    021
    022import org.eclipse.swt.SWT;
    023import org.eclipse.swt.events.SelectionAdapter;
    024import org.eclipse.swt.events.SelectionEvent;
    025import org.eclipse.swt.layout.FillLayout;
    026import org.eclipse.swt.layout.GridData;
    027import org.eclipse.swt.layout.GridLayout;
    028import org.eclipse.swt.widgets.Button;
    029import org.eclipse.swt.widgets.Composite;
    030import org.eclipse.swt.widgets.Label;
    031import org.eclipse.swt.widgets.Table;
    032import org.eclipse.swt.widgets.TableColumn;
    033import org.eclipse.swt.widgets.TableItem;
    034import org.eclipse.swt.widgets.Text;
    035
    036import hdf.object.CompoundDS;
    037import hdf.object.Dataset;
    038import hdf.object.Datatype;
    039import hdf.object.HObject;
    040import hdf.object.ScalarDS;
    041import hdf.view.Tools;
    042import hdf.view.DataView.DataViewManager;
    043
    044/**
    045 *
    046 * The metadata view interface for displaying dataset metadata information
    047 */
    048public class DefaultDatasetMetaDataView extends DefaultLinkMetaDataView implements MetaDataView {
    049
    050    private static final Logger log = LoggerFactory.getLogger(DefaultDatasetMetaDataView.class);
    051
    052    /**
    053     *The metadata view interface for displaying dataset metadata information
    054     *
    055     * @param parentComposite
    056     *        the parent visual object
    057     * @param viewer
    058     *        the viewer to use
    059     * @param theObj
    060     *        the object to display the metadata info
    061     */
    062    public DefaultDatasetMetaDataView(Composite parentComposite, DataViewManager viewer, HObject theObj) {
    063        super(parentComposite, viewer, theObj);
    064    }
    065
    066    @Override
    067    protected void addObjectSpecificContent() {
    068
    069        super.addObjectSpecificContent();
    070
    071        String labelInfo;
    072        Label label;
    073        Text text;
    074
    075        Dataset d = (Dataset) dataObject;
    076        if (!d.isInited()) {
    077            d.init();
    078        }
    079
    080        org.eclipse.swt.widgets.Group datasetInfoGroup = new org.eclipse.swt.widgets.Group(generalObjectInfoPane, SWT.NONE);
    081        datasetInfoGroup.setFont(curFont);
    082        datasetInfoGroup.setText("Dataset Dataspace and Datatype");
    083        datasetInfoGroup.setLayout(new GridLayout(2, false));
    084        datasetInfoGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 2, 1));
    085
    086        /* Dataset Rank section */
    087        label = new Label(datasetInfoGroup, SWT.LEFT);
    088        label.setFont(curFont);
    089        label.setText("No. of Dimension(s): ");
    090
    091        text = new Text(datasetInfoGroup, SWT.SINGLE | SWT.BORDER);
    092        text.setEditable(false);
    093        text.setFont(curFont);
    094        if (d.isNULL()) {
    095            labelInfo = "NULL";
    096        }
    097        else if (d.isScalar()) {
    098            labelInfo = "Scalar";
    099        }
    100        else {
    101            labelInfo = "" + d.getRank();
    102        }
    103        text.setText(labelInfo);
    104        text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
    105
    106        if (!d.isScalar() && !d.isNULL()) {
    107            /* Dataset dimension size section */
    108            label = new Label(datasetInfoGroup, SWT.LEFT);
    109            label.setFont(curFont);
    110            label.setText("Dimension Size(s): ");
    111
    112            // Set Dimension Size
    113            String dimStr = null;
    114            String maxDimStr = null;
    115            long dims[] = d.getDims();
    116            long maxDims[] = d.getMaxDims();
    117            if (dims != null) {
    118                String[] dimNames = d.getDimNames();
    119                boolean hasDimNames = ((dimNames != null) && (dimNames.length == dims.length));
    120                StringBuilder sb = new StringBuilder();
    121                StringBuilder sb2 = new StringBuilder();
    122
    123                sb.append(dims[0]);
    124                if (hasDimNames) {
    125                    sb.append(" (").append(dimNames[0]).append(")");
    126                }
    127
    128                if (maxDims[0] < 0)
    129                    sb2.append("Unlimited");
    130                else
    131                    sb2.append(maxDims[0]);
    132
    133                for (int i = 1; i < dims.length; i++) {
    134                    sb.append(" x ");
    135                    sb.append(dims[i]);
    136                    if (hasDimNames) {
    137                        sb.append(" (").append(dimNames[i]).append(")");
    138                    }
    139
    140                    sb2.append(" x ");
    141                    if (maxDims[i] < 0)
    142                        sb2.append("Unlimited");
    143                    else
    144                        sb2.append(maxDims[i]);
    145
    146                }
    147                dimStr = sb.toString();
    148                maxDimStr = sb2.toString();
    149            }
    150
    151            text = new Text(datasetInfoGroup, SWT.SINGLE | SWT.BORDER);
    152            text.setEditable(false);
    153            text.setFont(curFont);
    154            text.setText((dimStr == null) ? "null" : dimStr);
    155            text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
    156
    157            label = new Label(datasetInfoGroup, SWT.LEFT);
    158            label.setFont(curFont);
    159            label.setText("Max Dimension Size(s): ");
    160
    161            text = new Text(datasetInfoGroup, SWT.SINGLE | SWT.BORDER);
    162            text.setEditable(false);
    163            text.setFont(curFont);
    164            text.setText((maxDimStr == null) ? "null" : maxDimStr);
    165            text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
    166        }
    167
    168        /* Dataset datatype section */
    169        label = new Label(datasetInfoGroup, SWT.LEFT);
    170        label.setFont(curFont);
    171        label.setText("Data Type: ");
    172
    173        Datatype t = d.getDatatype();
    174        String type = (t == null) ? "null" : t.getDescription();
    175        if (d instanceof CompoundDS) {
    176            if (isH4) {
    177                type = "Vdata";
    178            }
    179            else {
    180                /*
    181                 * For Compounds, Arrays of Compounds, Vlens of Compounds, etc. we want to show
    182                 * the fully-qualified type, minus the compound members, since we already show
    183                 * the Compound datatype's members in a table.
    184                 */
    185                int bracketIndex = type.indexOf('{');
    186                int lastBracketIndex = type.lastIndexOf('}');
    187                if (bracketIndex >= 0 && lastBracketIndex >= 0) {
    188                    type = type.replace(type.substring(bracketIndex, lastBracketIndex + 1), "");
    189                }
    190            }
    191        }
    192
    193        text = new Text(datasetInfoGroup, SWT.SINGLE | SWT.BORDER);
    194        text.setEditable(false);
    195        text.setFont(curFont);
    196        text.setText(type);
    197        text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
    198
    199        /* Add a dummy label to take up some vertical space between sections */
    200        label = new Label(generalObjectInfoPane, SWT.LEFT);
    201        label.setText("");
    202        label.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 2, 1));
    203
    204        /*
    205         * Dataset storage layout, compression, filters, storage type, fill value, etc.
    206         * section
    207         */
    208        org.eclipse.swt.widgets.Group datasetLayoutGroup = new org.eclipse.swt.widgets.Group(generalObjectInfoPane, SWT.NONE);
    209        datasetLayoutGroup.setFont(curFont);
    210        datasetLayoutGroup.setText("Miscellaneous Dataset Information");
    211        datasetLayoutGroup.setLayout(new GridLayout(2, false));
    212        datasetLayoutGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1));
    213
    214        /* Dataset Storage Layout section */
    215        label = new Label(datasetLayoutGroup, SWT.LEFT);
    216        label.setFont(curFont);
    217        label.setText("Storage Layout: ");
    218
    219        label = new Label(datasetLayoutGroup, SWT.RIGHT);
    220        label.setFont(curFont);
    221        labelInfo = d.getStorageLayout();
    222        if (labelInfo == null) labelInfo = "UNKNOWN";
    223        label.setText(labelInfo);
    224
    225        /* Dataset Compression section */
    226        label = new Label(datasetLayoutGroup, SWT.LEFT);
    227        label.setFont(curFont);
    228        label.setText("Compression: ");
    229
    230        label = new Label(datasetLayoutGroup, SWT.RIGHT);
    231        label.setFont(curFont);
    232        labelInfo = d.getCompression();
    233        if (labelInfo == null) labelInfo = "UNKNOWN";
    234        label.setText(labelInfo);
    235
    236        /* Dataset filters section */
    237        label = new Label(datasetLayoutGroup, SWT.LEFT);
    238        label.setFont(curFont);
    239        label.setText("Filters: ");
    240
    241        label = new Label(datasetLayoutGroup, SWT.RIGHT);
    242        label.setFont(curFont);
    243        labelInfo = d.getFilters();
    244        if (labelInfo == null) labelInfo = "UNKNOWN";
    245        label.setText(labelInfo);
    246
    247        /* Dataset extra storage information section */
    248        label = new Label(datasetLayoutGroup, SWT.LEFT);
    249        label.setFont(curFont);
    250        label.setText("Storage: ");
    251
    252        label = new Label(datasetLayoutGroup, SWT.RIGHT);
    253        label.setFont(curFont);
    254        labelInfo = d.getStorage();
    255        if (labelInfo == null) labelInfo = "UNKNOWN";
    256        label.setText(labelInfo);
    257
    258        /* Dataset fill value info section */
    259        label = new Label(datasetLayoutGroup, SWT.LEFT);
    260        label.setFont(curFont);
    261        label.setText("Fill value: ");
    262
    263        Object fillValue = null;
    264        String fillValueInfo = "NONE";
    265        if (d instanceof ScalarDS) fillValue = ((ScalarDS) d).getFillValue();
    266        if (fillValue != null) {
    267            if (fillValue.getClass().isArray()) {
    268                int len = Array.getLength(fillValue);
    269                fillValueInfo = Array.get(fillValue, 0).toString();
    270                for (int i = 1; i < len; i++) {
    271                    fillValueInfo += ", ";
    272                    fillValueInfo += Array.get(fillValue, i).toString();
    273                }
    274            }
    275            else
    276                fillValueInfo = fillValue.toString();
    277        }
    278
    279        label = new Label(datasetLayoutGroup, SWT.RIGHT);
    280        label.setFont(curFont);
    281        label.setText(fillValueInfo);
    282
    283        /* Button to open Data Option dialog */
    284        Button showDataOptionButton = new Button(datasetInfoGroup, SWT.PUSH);
    285        showDataOptionButton.setLayoutData(new GridData(SWT.CENTER, SWT.FILL, true, false, 2, 1));
    286        showDataOptionButton.setText("Show Data with Options");
    287        showDataOptionButton.setEnabled(!d.isNULL());
    288        showDataOptionButton.addSelectionListener(new SelectionAdapter() {
    289            @Override
    290            public void widgetSelected(SelectionEvent e) {
    291                try {
    292                    viewManager.getTreeView().setDefaultDisplayMode(false);
    293                    viewManager.getTreeView().showDataContent(dataObject);
    294                }
    295                catch (Exception ex) {
    296                    display.beep();
    297                    Tools.showError(display.getShells()[0], "Select", ex.getMessage());
    298                }
    299            }
    300        });
    301
    302        /*
    303         * If this is a Compound Dataset, add a table which displays all of the members
    304         * in the Compound Datatype.
    305         */
    306        if (d instanceof CompoundDS) {
    307            log.trace("addObjectSpecificContent(): add member table for Compound Datatype Dataset");
    308
    309            CompoundDS compound = (CompoundDS) d;
    310
    311            int n = compound.getMemberCount();
    312            log.trace("addObjectSpecificContent(): number of compound members={}", n);
    313
    314            // Add a dummy label to take up some vertical space between sections
    315            label = new Label(generalObjectInfoPane, SWT.LEFT);
    316            label.setText("");
    317            label.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 2, 1));
    318
    319            org.eclipse.swt.widgets.Group compoundMembersGroup = new org.eclipse.swt.widgets.Group(generalObjectInfoPane, SWT.NONE);
    320            compoundMembersGroup.setFont(curFont);
    321            compoundMembersGroup.setText("Compound Dataset Members");
    322            compoundMembersGroup.setLayout(new FillLayout(SWT.VERTICAL));
    323            compoundMembersGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1));
    324
    325            Table memberTable = new Table(compoundMembersGroup, SWT.BORDER);
    326            memberTable.setLinesVisible(true);
    327            memberTable.setHeaderVisible(true);
    328            memberTable.setFont(curFont);
    329
    330            String[] columnNames = { "Name", "Type", "Array Size" };
    331
    332            for (int i = 0; i < columnNames.length; i++) {
    333                TableColumn column = new TableColumn(memberTable, SWT.NONE);
    334                column.setText(columnNames[i]);
    335                column.setMoveable(false);
    336            }
    337
    338            if (n > 0) {
    339                String rowData[][] = new String[n][3];
    340                final String names[] = compound.getMemberNames();
    341                Datatype types[] = compound.getMemberTypes();
    342                int orders[] = compound.getMemberOrders();
    343
    344                for (int i = 0; i < n; i++) {
    345                    rowData[i][0] = new String(names[i]);
    346
    347                    if (rowData[i][0].contains(CompoundDS.SEPARATOR)) {
    348                        rowData[i][0] = rowData[i][0].replaceAll(CompoundDS.SEPARATOR, "->");
    349                    }
    350
    351                    int mDims[] = compound.getMemberDims(i);
    352                    if (mDims == null) {
    353                        rowData[i][2] = String.valueOf(orders[i]);
    354
    355                        if (isH4 && types[i].isString()) {
    356                            rowData[i][2] = String.valueOf(types[i].getDatatypeSize());
    357                        }
    358                    }
    359                    else {
    360                        String mStr = String.valueOf(mDims[0]);
    361                        int m = mDims.length;
    362                        for (int j = 1; j < m; j++) {
    363                            mStr += " x " + mDims[j];
    364                        }
    365                        rowData[i][2] = mStr;
    366                    }
    367                    rowData[i][1] = (types[i] == null) ? "null" : types[i].getDescription();
    368                }
    369
    370                for (int i = 0; i < rowData.length; i++) {
    371                    TableItem item = new TableItem(memberTable, SWT.NONE);
    372                    item.setFont(curFont);
    373                    item.setText(0, rowData[i][0]);
    374                    item.setText(1, rowData[i][1]);
    375                    item.setText(2, rowData[i][2]);
    376                }
    377
    378                for (int i = 0; i < columnNames.length; i++) {
    379                    memberTable.getColumn(i).pack();
    380                }
    381
    382                // set cell height for large fonts
    383                // int cellRowHeight = Math.max(16,
    384                // table.getFontMetrics(table.getFont()).getHeight());
    385                // table.setRowHeight(cellRowHeight);
    386            } //  (n > 0)
    387
    388            // Prevent conflict from equal vertical grabbing
    389            datasetLayoutGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 2, 1));
    390        }
    391    }
    392
    393}