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