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 files COPYING and Copyright.html. *
009 * COPYING can be found at the root of the source code distribution tree.    *
010 * Or, see http://hdfgroup.org/products/hdf-java/doc/Copyright.html.         *
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;
016
017import java.awt.BorderLayout;
018import java.awt.Dialog;
019import java.awt.Dimension;
020import java.awt.GridLayout;
021import java.awt.Point;
022import java.awt.event.ActionEvent;
023import java.awt.event.ActionListener;
024import java.awt.event.ItemEvent;
025import java.awt.event.ItemListener;
026import java.awt.event.KeyEvent;
027import java.math.BigInteger;
028import java.net.URL;
029import java.net.URLClassLoader;
030import java.util.Enumeration;
031import java.util.StringTokenizer;
032
033import javax.swing.BorderFactory;
034import javax.swing.ButtonGroup;
035import javax.swing.JButton;
036import javax.swing.JCheckBox;
037import javax.swing.JComboBox;
038import javax.swing.JDialog;
039import javax.swing.JEditorPane;
040import javax.swing.JLabel;
041import javax.swing.JOptionPane;
042import javax.swing.JPanel;
043import javax.swing.JRadioButton;
044import javax.swing.JScrollPane;
045import javax.swing.JTextField;
046import javax.swing.event.HyperlinkEvent;
047import javax.swing.event.HyperlinkListener;
048import javax.swing.text.html.HTMLDocument;
049import javax.swing.text.html.HTMLFrameHyperlinkEvent;
050import javax.swing.tree.DefaultMutableTreeNode;
051
052import hdf.object.Attribute;
053import hdf.object.Datatype;
054import hdf.object.FileFormat;
055import hdf.object.Group;
056import hdf.object.HObject;
057
058/**
059 * NewAttributeDialog displays components for adding new attribute.
060 *
061 * @author Peter X. Cao
062 * @version 2.4 9/6/2007
063 */
064public class NewAttributeDialog extends JDialog implements ActionListener, ItemListener, HyperlinkListener {
065    private static final long serialVersionUID                = 4883237570834215275L;
066
067    private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(NewAttributeDialog.class);
068
069    /** the default length of a string attribute */
070    public static final int   DEFAULT_STRING_ATTRIBUTE_LENGTH = 256;
071
072    /** the object which the attribute to be attached to */
073    private HObject           hObject;
074
075    private Attribute         newAttribute;
076
077    /** TextField for entering the name of the dataset */
078    private JTextField        nameField;
079
080    /** The Choice of the datatypes */
081    @SuppressWarnings("rawtypes")
082    private JComboBox         classChoice, sizeChoice;
083
084    private JCheckBox         checkUnsigned;
085
086    /** TextField for entering the attribute value. */
087    private JTextField        valueField;
088
089    /** The Choice of the object list */
090    @SuppressWarnings("rawtypes")
091    private JComboBox         objChoice;
092
093    private FileFormat        fileFormat;
094
095    /** TextField for entering the length of the data array or string. */
096    private JTextField        lengthField;
097
098    private JLabel            arrayLengthLabel;
099
100    private final boolean     isH5;
101
102    private JDialog           helpDialog;
103
104    private JRadioButton      h4GrAttrRadioButton;
105
106    /**
107     * Constructs NewAttributeDialog with specified object (dataset, group, or
108     * image) which the new attribute to be attached to.
109     *
110     * @param owner
111     *            the owner of the input
112     * @param obj
113     *            the object which the attribute to be attached to.
114     * @param objList
115     *            the list of objects in the file
116     */
117    @SuppressWarnings({ "rawtypes", "unchecked" })
118    public NewAttributeDialog(Dialog owner, HObject obj, Enumeration<?> objList) {
119        super(owner, "New Attribute...", true);
120
121        hObject = obj;
122        newAttribute = null;
123        isH5 = obj.getFileFormat().isThisType(FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5));
124        helpDialog = null;
125        fileFormat = obj.getFileFormat();
126
127        JPanel typeLabelPanel = new JPanel();
128        typeLabelPanel.setLayout(new GridLayout(1, 4, 15, 3));
129        JPanel typePanel = new JPanel();
130        typePanel.setLayout(new GridLayout(1, 4, 15, 3));
131
132        classChoice = new JComboBox();
133        classChoice.setName("attrclass");
134        sizeChoice = new JComboBox();
135        sizeChoice.setName("attrsize");
136
137        classChoice.addItem("INTEGER");
138        classChoice.addItem("FLOAT");
139        classChoice.addItem("CHAR");
140
141        if (isH5) {
142            classChoice.addItem("STRING");
143            classChoice.addItem("REFERENCE");
144            classChoice.addItem("VLEN_INTEGER");
145            classChoice.addItem("VLEN_FLOAT");
146            classChoice.addItem("VLEN_STRING");
147        }
148        sizeChoice.addItem("8");
149        sizeChoice.addItem("16");
150        sizeChoice.addItem("32");
151        sizeChoice.addItem("64");
152
153        typeLabelPanel.add(new JLabel("Datatype class"));
154        typeLabelPanel.add(new JLabel("Size (bits)"));
155        typeLabelPanel.add(new JLabel(" "));
156
157        typePanel.add(classChoice);
158        typePanel.add(sizeChoice);
159        checkUnsigned = new JCheckBox("Unsigned");
160        checkUnsigned.setName("attrchkunsigned");
161        typePanel.add(checkUnsigned);
162
163        JPanel contentPane = (JPanel) getContentPane();
164        contentPane.setLayout(new BorderLayout(5, 5));
165        contentPane.setBorder(BorderFactory.createEmptyBorder(20, 10, 0, 10));
166        int w = 500 + (ViewProperties.getFontSize() - 12) * 15;
167        int h = 220 + (ViewProperties.getFontSize() - 12) * 12;
168        contentPane.setPreferredSize(new Dimension(w, h));
169
170        JButton okButton = new JButton("   Ok   ");
171        okButton.setName("OK");
172        okButton.setActionCommand("Ok");
173        okButton.setMnemonic(KeyEvent.VK_O);
174
175        JButton cancelButton = new JButton("Cancel");
176        cancelButton.setName("Cancel");
177        cancelButton.setActionCommand("Cancel");
178        cancelButton.setMnemonic(KeyEvent.VK_C);
179
180        JButton helpButton = new JButton(" Help ");
181        helpButton.setName("Help");
182        helpButton.setActionCommand("Show help");
183        helpButton.setMnemonic(KeyEvent.VK_H);
184
185        JPanel p = new JPanel();
186        p.setLayout(new BorderLayout(5, 5));
187        JPanel p2 = new JPanel();
188        p2.setLayout(new GridLayout(6, 1, 3, 3));
189        p2.add(new JLabel("Name: "));
190        p2.add(new JLabel(" "));
191        p2.add(new JLabel("Type: "));
192        p2.add(arrayLengthLabel = new JLabel("Array Size: "));
193        p2.add(new JLabel("Value: "));
194        p2.add(new JLabel("Object List: "));
195        p.add("West", p2);
196
197        JPanel typePane = new JPanel();
198        typePane.setLayout(new BorderLayout());
199        JPanel h4GattrPane = new JPanel();
200        h4GattrPane.setLayout(new GridLayout(1, 2, 3, 3));
201        ButtonGroup bg = new ButtonGroup();
202        JRadioButton grAttr = new JRadioButton("GR");
203        JRadioButton sdAttr = new JRadioButton("SD");
204        bg.add(sdAttr);
205        bg.add(grAttr);
206        sdAttr.setSelected(true);
207        h4GattrPane.add(sdAttr);
208        h4GattrPane.add(grAttr);
209        typePane.add(typePanel, BorderLayout.CENTER);
210        typePane.add(h4GattrPane, BorderLayout.EAST);
211        h4GrAttrRadioButton = grAttr;
212
213        p2 = new JPanel();
214        p2.setLayout(new GridLayout(6, 1, 3, 3));
215        nameField = new JTextField("", 30);
216        nameField.setName("attrname");
217        p2.add(nameField);
218        if (!isH5 && (obj instanceof Group) && ((Group) obj).isRoot()) {
219            p2.add(typePane);
220        }
221        else {
222            p2.add(typeLabelPanel);
223            p2.add(typePanel);
224        }
225        lengthField = new JTextField("1");
226        lengthField.setName("attrlength");
227        p2.add(lengthField);
228        valueField = new JTextField("0");
229        valueField.setName("attrvalue");
230        p2.add(valueField);
231        objChoice = new JComboBox();
232        objChoice.setName("attrobjn");
233        p2.add(objChoice);
234        p.add("Center", p2);
235
236        contentPane.add("Center", p);
237
238        p = new JPanel();
239        p.add(okButton);
240        p.add(cancelButton);
241        p.add(helpButton);
242        contentPane.add("South", p);
243
244        classChoice.addItemListener(this);
245        sizeChoice.addItemListener(this);
246
247        okButton.addActionListener(this);
248        cancelButton.addActionListener(this);
249        helpButton.addActionListener(this);
250        objChoice.addItemListener(this);
251        objChoice.setEnabled(false);
252
253        String str;
254        HObject hobj;
255        DefaultMutableTreeNode theNode;
256        while (objList.hasMoreElements()) {
257            theNode = (DefaultMutableTreeNode) objList.nextElement();
258            hobj = (HObject) theNode.getUserObject();
259            if (hobj instanceof Group) {
260                if (((Group) hobj).isRoot()) continue;
261            }
262            str = hobj.getFullName();
263            objChoice.addItem(str);
264        }
265
266        Point l = owner.getLocation();
267        l.x += 50;
268        l.y += 80;
269        setLocation(l);
270        pack();
271    }
272
273    public void actionPerformed(ActionEvent e) {
274        String cmd = e.getActionCommand();
275
276        if (cmd.equals("Ok")) {
277            if (createAttribute()) {
278                dispose();
279            }
280        }
281        else if (cmd.equals("Cancel")) {
282            newAttribute = null;
283            dispose();
284        }
285        else if (cmd.equals("Show help")) {
286            if (helpDialog == null) {
287                createHelpDialog();
288            }
289            helpDialog.setVisible(true);
290        }
291        else if (cmd.equals("Hide help")) {
292            if (helpDialog != null) {
293                helpDialog.setVisible(false);
294            }
295        }
296    }
297
298    @SuppressWarnings("unchecked")
299    public void itemStateChanged(ItemEvent e) {
300        Object source = e.getSource();
301
302        if (source.equals(classChoice)) {
303            int idx = classChoice.getSelectedIndex();
304            sizeChoice.setSelectedIndex(0);
305            objChoice.setEnabled(false);
306            lengthField.setEnabled(true);
307
308            if ((idx == 0) || (idx == 5)) {
309                sizeChoice.setEnabled(true);
310                checkUnsigned.setEnabled(true);
311                arrayLengthLabel.setText("Array Size: ");
312
313                if (sizeChoice.getItemCount() == 2) {
314                    sizeChoice.removeItem("32");
315                    sizeChoice.removeItem("64");
316                    sizeChoice.addItem("8");
317                    sizeChoice.addItem("16");
318                    sizeChoice.addItem("32");
319                    sizeChoice.addItem("64");
320                }
321            }
322            else if ((idx == 1) || (idx == 6)) {
323                sizeChoice.setEnabled(true);
324                checkUnsigned.setEnabled(false);
325                arrayLengthLabel.setText("Array Size: ");
326
327                if (sizeChoice.getItemCount() == 4) {
328                    sizeChoice.removeItem("16");
329                    sizeChoice.removeItem("8");
330                }
331            }
332            else if (idx == 2) {
333                sizeChoice.setEnabled(false);
334                checkUnsigned.setEnabled(true);
335                arrayLengthLabel.setText("Array Size: ");
336            }
337            else if (idx == 3) {
338                sizeChoice.setEnabled(false);
339                checkUnsigned.setEnabled(false);
340                arrayLengthLabel.setText("String Length: ");
341            }
342            else if (idx == 4) {
343                sizeChoice.setEnabled(false);
344                checkUnsigned.setEnabled(false);
345                lengthField.setText("1");
346                lengthField.setEnabled(false);
347                arrayLengthLabel.setText("Array Size: ");
348                objChoice.setEnabled(true);
349                valueField.setText("");
350            }
351            else if (idx == 7) {
352                sizeChoice.setEnabled(false);
353                checkUnsigned.setEnabled(false);
354                lengthField.setEnabled(false);
355            }
356        }
357        else if (source.equals(sizeChoice)) {
358            if (classChoice.getSelectedIndex() == 0) {
359                checkUnsigned.setEnabled(true);
360            }
361        }
362        else if (source.equals(objChoice)) {
363            String objName = (String) objChoice.getSelectedItem();
364
365            if (e.getStateChange() != ItemEvent.SELECTED) return;
366
367            long ref = -1;
368            try {
369                HObject obj = fileFormat.get(objName);
370                ref = obj.getOID()[0];
371            }
372            catch (Exception ex) {
373                log.debug("object id:", ex);
374            }
375
376            if (ref > 0) {
377                if (valueField.getText().length() > 1) {
378                    valueField.setText(valueField.getText() + "," + ref);
379                    StringTokenizer st = new StringTokenizer(valueField.getText(), ",");
380                    lengthField.setText(String.valueOf(st.countTokens()));
381                }
382                else {
383                    valueField.setText(String.valueOf(ref));
384                    lengthField.setText("1");
385                }
386            }
387        }
388    }
389
390    @SuppressWarnings("unchecked")
391    private boolean createAttribute() {
392        int string_length = 0;
393        int tclass = -1, tsize = -1, torder = -1, tsign = -1;
394        boolean isVLen = false;
395        log.trace("createAttribute start");
396
397        Object value = null;
398        String strValue = valueField.getText();
399
400        String attrName = nameField.getText();
401        if (attrName != null) {
402            attrName = attrName.trim();
403        }
404
405        if ((attrName == null) || (attrName.length() < 1)) {
406            JOptionPane.showMessageDialog(this, "No attribute name.", getTitle(), JOptionPane.ERROR_MESSAGE);
407            return false;
408        }
409
410        String lengthStr = lengthField.getText();
411        log.trace("Name is {} : Length={} and Value={}", attrName, lengthStr, strValue);
412
413        int arraySize = 0;
414        if ((lengthStr == null) || (lengthStr.length() <= 0)) {
415            arraySize = 1;
416        }
417        else {
418            try {
419                arraySize = Integer.parseInt(lengthStr);
420            }
421            catch (Exception e) {
422                arraySize = -1;
423            }
424        }
425
426        if (arraySize <= 0) {
427            JOptionPane.showMessageDialog(this, "Invalid attribute length.", getTitle(), JOptionPane.ERROR_MESSAGE);
428            return false;
429        }
430
431        StringTokenizer st = new StringTokenizer(strValue, ",");
432        int count = Math.min(arraySize, st.countTokens());
433        String theToken;
434        log.trace("Count of Values is {}", count);
435
436        // set datatype class
437        int idx = classChoice.getSelectedIndex();
438        if (idx == 0) {
439            tclass = Datatype.CLASS_INTEGER;
440            if (checkUnsigned.isSelected()) {
441                tsign = Datatype.SIGN_NONE;
442            }
443            torder = Datatype.NATIVE;
444        }
445        else if (idx == 1) {
446            tclass = Datatype.CLASS_FLOAT;
447            torder = Datatype.NATIVE;
448        }
449        else if (idx == 2) {
450            tclass = Datatype.CLASS_CHAR;
451            if (checkUnsigned.isSelected()) {
452                tsign = Datatype.SIGN_NONE;
453            }
454            torder = Datatype.NATIVE;
455        }
456        else if (idx == 3) {
457            tclass = Datatype.CLASS_STRING;
458        }
459        else if (idx == 4) {
460            tclass = Datatype.CLASS_REFERENCE;
461        }
462        else if (idx == 5) {;
463            isVLen = true;
464            tclass = Datatype.CLASS_INTEGER;
465            if (checkUnsigned.isSelected()) {
466                tsign = Datatype.SIGN_NONE;
467            }
468            torder = Datatype.NATIVE;
469            JOptionPane.showMessageDialog(this, "Multi-dimensional Variable Length Integer Attributes will be created without data", getTitle(), JOptionPane.WARNING_MESSAGE);
470        }
471        else if (idx == 6) {;
472            isVLen = true;
473            tclass = Datatype.CLASS_FLOAT;
474            torder = Datatype.NATIVE;
475            JOptionPane.showMessageDialog(this, "Multi-dimensional Variable Length Float Attributes will be created without data", getTitle(), JOptionPane.WARNING_MESSAGE);
476        }
477        else if (idx == 7) {
478            isVLen = true;
479            tclass = Datatype.CLASS_STRING;
480        }
481        log.trace("Attribute: isVLen={} and tclass={} and torder={} and tsign={}", isVLen, tclass, torder, tsign);
482
483        // set datatype size/order
484        idx = sizeChoice.getSelectedIndex();
485        if (isVLen) {
486            tsize = -1;
487            log.trace("Attribute isVLen={} and tsize={}", isVLen, tsize);
488            String[] strArray = { strValue };
489            value = strArray;
490            if (tclass == Datatype.CLASS_INTEGER) {
491                switch(idx) {
492                        case 0:
493                                tsize = 1;
494                                break;
495                        case 1:
496                                tsize = 2;
497                                break;
498                        case 2:
499                                tsize = 4;
500                                break;
501                        case 3:
502                                tsize = 8;
503                                break;
504                }
505                log.trace("Attribute VL-CLASS_INTEGER: tsize={}", tsize);
506            }
507            else if (tclass == Datatype.CLASS_FLOAT) {
508                tsize = (idx + 1) * 4;
509                log.trace("Attribute VL-CLASS_FLOAT: tsize={}", tsize);
510            }
511        }
512        else {
513            if (tclass == Datatype.CLASS_STRING) {
514                int stringLength = 0;
515                try {
516                    stringLength = Integer.parseInt(lengthField.getText());
517                }
518                catch (NumberFormatException ex) {
519                    stringLength = -1;
520                }
521
522                if (stringLength <= 0) {
523                    stringLength = DEFAULT_STRING_ATTRIBUTE_LENGTH;
524                }
525                if (strValue.length() > stringLength) {
526                    strValue = strValue.substring(0, stringLength);
527                }
528
529                tsize = stringLength;
530
531                String[] strArray = { strValue };
532                value = strArray;
533
534                if (isH5) {
535                    arraySize = 1; // support string type
536                }
537                else {
538                    arraySize = stringLength; // array of characters
539                }
540                log.trace("Attribute CLASS_STRING: isVLen={} and tsize={} and arraySize={}", isVLen, tsize, arraySize);
541            }
542            else if (tclass == Datatype.CLASS_REFERENCE) {
543                tsize = 1;
544                arraySize = st.countTokens();
545                long[] ref = new long[arraySize];
546                for (int j = 0; j < arraySize; j++) {
547                    theToken = st.nextToken().trim();
548                    try {
549                        ref[j] = Long.parseLong(theToken);
550                    }
551                    catch (NumberFormatException ex) {
552                        JOptionPane.showMessageDialog(this, ex.getMessage(), getTitle(), JOptionPane.ERROR_MESSAGE);
553                        return false;
554                    }
555                }
556
557                value = ref;
558                torder = Datatype.NATIVE;
559                log.trace("Attribute CLASS_REFERENCE: tsize={} and arraySize={}", tsize, arraySize);
560            }
561            else if (tclass == Datatype.CLASS_INTEGER) {
562                switch(idx) {
563                    case 0:
564                        tsize = 1;
565                        break;
566                    case 1:
567                        tsize = 2;
568                        break;
569                    case 2:
570                        tsize = 4;
571                        break;
572                    case 3:
573                        tsize = 8;
574                        break;
575                }
576                log.trace("Attribute CLASS_INTEGER: tsize={}", tsize);
577            }
578            else if (tclass == Datatype.CLASS_FLOAT) {
579                tsize = (idx + 1) * 4;
580                log.trace("Attribute CLASS_FLOAT: tsize={}", tsize);
581            }
582            else {
583                tsize = 1 << (idx);
584                log.trace("Attribute other: tsize={}", tsize);
585            }
586
587            if ((tsize == 8) && !isH5 && (tclass == Datatype.CLASS_INTEGER)) {
588                JOptionPane.showMessageDialog(this,
589                        "HDF4 does not support 64-bit integer.",
590                        getTitle(),
591                        JOptionPane.ERROR_MESSAGE);
592                return false;
593            }
594
595            if (tclass == Datatype.CLASS_INTEGER) {
596                if (tsign == Datatype.SIGN_NONE) {
597                    if (tsize == 1) {
598                        byte[] b = new byte[arraySize];
599                        short sv = 0;
600                        for (int j = 0; j < count; j++) {
601                            theToken = st.nextToken().trim();
602                            try {
603                                sv = Short.parseShort(theToken);
604                            }
605                            catch (NumberFormatException ex) {
606                                JOptionPane.showMessageDialog(this, ex.getMessage(), getTitle(), JOptionPane.ERROR_MESSAGE);
607                                return false;
608                            }
609                            if (sv < 0) {
610                                sv = 0;
611                            }
612                            else if (sv > 255) {
613                                sv = 255;
614                            }
615                            b[j] = (byte) sv;
616                        }
617                        value = b;
618                    }
619                    else if (tsize == 2) {
620                        short[] s = new short[arraySize];
621                        int iv = 0;
622                        for (int j = 0; j < count; j++) {
623                            theToken = st.nextToken().trim();
624                            try {
625                                iv = Integer.parseInt(theToken);
626                            }
627                            catch (NumberFormatException ex) {
628                                JOptionPane.showMessageDialog(this, ex.getMessage(), getTitle(), JOptionPane.ERROR_MESSAGE);
629                                return false;
630                            }
631                            if (iv < 0) {
632                                iv = 0;
633                            }
634                            else if (iv > 65535) {
635                                iv = 65535;
636                            }
637                            s[j] = (short) iv;
638                        }
639                        value = s;
640                    }
641                    else if (tsize == 4) {
642                        int[] i = new int[arraySize];
643                        long lv = 0;
644                        for (int j = 0; j < count; j++) {
645                            theToken = st.nextToken().trim();
646                            try {
647                                lv = Long.parseLong(theToken);
648                            }
649                            catch (NumberFormatException ex) {
650                                JOptionPane.showMessageDialog(this, ex.getMessage(), getTitle(), JOptionPane.ERROR_MESSAGE);
651                                return false;
652                            }
653                            if (lv < 0) {
654                                lv = 0;
655                            }
656                            if (lv > 4294967295L) {
657                                lv = 4294967295L;
658                            }
659                            i[j] = (int) lv;
660                        }
661                        value = i;
662                    }
663                    else if (tsize == 8) {
664                        long[] i = new long[arraySize];
665                        BigInteger lv = BigInteger.valueOf(0);
666                        for (int j = 0; j < count; j++) {
667                            theToken = st.nextToken().trim();
668                            try {
669                                lv = new BigInteger(theToken);
670                            }
671                            catch (NumberFormatException ex) {
672                                JOptionPane.showMessageDialog(this, ex.getMessage(), getTitle(), JOptionPane.ERROR_MESSAGE);
673                                return false;
674                            }
675                            i[j] = (long) lv.longValue();
676                        }
677                        value = i;
678                    }
679                }
680                else {
681                    if (tsize == 1) {
682                        byte[] b = new byte[arraySize];
683                        for (int j = 0; j < count; j++) {
684                            theToken = st.nextToken().trim();
685                            try {
686                                b[j] = Byte.parseByte(theToken);
687                            }
688                            catch (NumberFormatException ex) {
689                                JOptionPane.showMessageDialog(this, ex.getMessage(), getTitle(), JOptionPane.ERROR_MESSAGE);
690                                return false;
691                            }
692                        }
693                        value = b;
694                    }
695                    else if (tsize == 2) {
696                        short[] s = new short[arraySize];
697
698                        for (int j = 0; j < count; j++) {
699                            theToken = st.nextToken().trim();
700                            try {
701                                s[j] = Short.parseShort(theToken);
702                            }
703                            catch (NumberFormatException ex) {
704                                JOptionPane.showMessageDialog(this, ex.getMessage(), getTitle(), JOptionPane.ERROR_MESSAGE);
705                                return false;
706                            }
707                        }
708                        value = s;
709                    }
710                    else if (tsize == 4) {
711                        int[] i = new int[arraySize];
712
713                        for (int j = 0; j < count; j++) {
714                            theToken = st.nextToken().trim();
715                            try {
716                                i[j] = Integer.parseInt(theToken);
717                            }
718                            catch (NumberFormatException ex) {
719                                JOptionPane.showMessageDialog(this, ex.getMessage(), getTitle(), JOptionPane.ERROR_MESSAGE);
720                                return false;
721                            }
722                        }
723                        value = i;
724                    }
725                    else if (tsize == 8) {
726                        long[] l = new long[arraySize];
727                        for (int j = 0; j < count; j++) {
728                            theToken = st.nextToken().trim();
729                            try {
730                                l[j] = Long.parseLong(theToken);
731                            }
732                            catch (NumberFormatException ex) {
733                                JOptionPane.showMessageDialog(this, ex.getMessage(), getTitle(), JOptionPane.ERROR_MESSAGE);
734                                return false;
735                            }
736                        }
737                        value = l;
738                    }
739                }
740            }
741
742            if (tclass == Datatype.CLASS_FLOAT) {
743                if (tsize == 4) {
744                    float[] f = new float[arraySize];
745                    for (int j = 0; j < count; j++) {
746                        theToken = st.nextToken().trim();
747                        try {
748                            f[j] = Float.parseFloat(theToken);
749                        }
750                        catch (NumberFormatException ex) {
751                            JOptionPane.showMessageDialog(this, ex.getMessage(), getTitle(), JOptionPane.ERROR_MESSAGE);
752                            return false;
753                        }
754                        if (Float.isInfinite(f[j]) || Float.isNaN(f[j])) {
755                            f[j] = 0;
756                        }
757                    }
758                    value = f;
759                }
760                else if (tsize == 8) {
761                    double[] d = new double[arraySize];
762                    for (int j = 0; j < count; j++) {
763                        theToken = st.nextToken().trim();
764                        try {
765                            d[j] = Double.parseDouble(theToken);
766                        }
767                        catch (NumberFormatException ex) {
768                            JOptionPane.showMessageDialog(this, ex.getMessage(), getTitle(), JOptionPane.ERROR_MESSAGE);
769                            return false;
770                        }
771                        if (Double.isInfinite(d[j]) || Double.isNaN(d[j])) {
772                            d[j] = 0;
773                        }
774                    }
775                    value = d;
776                }
777            }
778        }
779
780        Datatype datatype = null;
781        try {
782            Datatype basedatatype = null;
783            if (isVLen) {
784                basedatatype = fileFormat.createDatatype(tclass, tsize, torder, tsign);
785                tclass = Datatype.CLASS_VLEN;
786                log.trace("Attribute CLASS_VLEN");
787            }
788            datatype = fileFormat.createDatatype(tclass, tsize, torder, tsign, basedatatype);
789        }
790        catch (Exception ex) {
791            JOptionPane.showMessageDialog(this, ex.getMessage(), getTitle(), JOptionPane.ERROR_MESSAGE);
792            return false;
793        }
794
795        long[] dims = { arraySize };
796        Attribute attr = new Attribute(attrName, datatype, dims);
797        attr.setValue(value);
798
799        try {
800            if (!isH5 && (hObject instanceof Group) && ((Group) hObject).isRoot() && h4GrAttrRadioButton.isSelected()) {
801                // don't find a good way to write HDF4 global
802                // attribute. Use the isExisted to separate the
803                // global attribute is GR or SD
804                hObject.getFileFormat().writeAttribute(hObject, attr, false);
805                if (hObject.getMetadata() == null) {
806                    hObject.getMetadata().add(attr);
807                }
808            }
809            else {
810                log.trace("writeMetadata()");
811                hObject.writeMetadata(attr);
812            }
813        }
814        catch (Exception ex) {
815            JOptionPane.showMessageDialog(this, ex.getMessage(), getTitle(), JOptionPane.ERROR_MESSAGE);
816            return false;
817        }
818
819        newAttribute = attr;
820
821        log.trace("createAttribute finish");
822        return true;
823    }
824
825    /** Creates a dialog to show the help information. */
826    private void createHelpDialog() {
827        helpDialog = new JDialog(this, "Creation New Attribute");
828
829        JPanel contentPane = (JPanel) helpDialog.getContentPane();
830        contentPane.setLayout(new BorderLayout(5, 5));
831        contentPane.setBorder(BorderFactory.createEmptyBorder(15, 5, 5, 5));
832        int w = 500 + (ViewProperties.getFontSize() - 12) * 15;
833        int h = 400 + (ViewProperties.getFontSize() - 12) * 10;
834        contentPane.setPreferredSize(new Dimension(w, h));
835
836        JButton b = new JButton("  Ok  ");
837        b.addActionListener(this);
838        b.setActionCommand("Hide help");
839        JPanel tmpP = new JPanel();
840        tmpP.add(b);
841        contentPane.add(tmpP, BorderLayout.SOUTH);
842
843        JEditorPane infoPane = new JEditorPane();
844        infoPane.setEditable(false);
845        JScrollPane editorScrollPane = new JScrollPane(infoPane);
846        contentPane.add(editorScrollPane, BorderLayout.CENTER);
847
848        try {
849            URL url = null, url2 = null, url3 = null;
850            String rootPath = ViewProperties.getViewRoot();
851
852            try {
853                url = new URL("file:" + rootPath + "/lib/jhdfview.jar");
854            }
855            catch (java.net.MalformedURLException mfu) {
856                log.debug("help information:", mfu);
857            }
858
859            try {
860                url2 = new URL("file:" + rootPath + "/");
861            }
862            catch (java.net.MalformedURLException mfu) {
863                log.debug("help information:", mfu);
864            }
865
866            try {
867                url3 = new URL("file:" + rootPath + "/src/");
868            }
869            catch (java.net.MalformedURLException mfu) {
870                log.debug("help information:", mfu);
871            }
872
873            URL uu[] = { url, url2, url3 };
874            URLClassLoader cl = new URLClassLoader(uu);
875            URL u = cl.findResource("hdf/view/NewAttrHelp.html");
876
877            if (u == null) {
878                u = ClassLoader.getSystemResource("hdf/view/NewAttrHelp.html");
879            }
880
881            cl.close();
882            infoPane.setPage(u);
883            infoPane.addHyperlinkListener(this);
884        }
885        catch (Exception e) {
886            infoPane.setContentType("text/html");
887            StringBuffer buff = new StringBuffer();
888            buff.append("<html>");
889            buff.append("<body>");
890            buff.append("ERROR: cannot load help information.");
891            buff.append("</body>");
892            buff.append("</html>");
893            infoPane.setText(buff.toString());
894        }
895
896        Point l = helpDialog.getOwner().getLocation();
897        l.x += 50;
898        l.y += 80;
899        helpDialog.setLocation(l);
900        helpDialog.validate();
901        helpDialog.pack();
902    }
903
904    public void hyperlinkUpdate(HyperlinkEvent e) {
905        if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
906            JEditorPane pane = (JEditorPane) e.getSource();
907
908            if (e instanceof HTMLFrameHyperlinkEvent) {
909                HTMLFrameHyperlinkEvent evt = (HTMLFrameHyperlinkEvent) e;
910                HTMLDocument doc = (HTMLDocument) pane.getDocument();
911                doc.processHTMLFrameHyperlinkEvent(evt);
912            }
913            else {
914                try {
915                    pane.setPage(e.getURL());
916                }
917                catch (Throwable t) {
918                    log.debug("JEditorPane hyper link:", t);
919                }
920            }
921        }
922    }
923
924    /**
925     * Returns the new attribute created.
926     * 
927     * @return The new Attribute created
928     */
929    public Attribute getAttribute() {
930        return newAttribute;
931    }
932}