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}