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