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