/**
   * Constructs a <code>VariabilityRecordTable</code> with a list of variability records.
   *
   * @param record_list the list of variability records.
   * @param desktop the parent desktop.
   */
  public VariabilityRecordTable(Vector record_list, net.aerith.misao.gui.Desktop desktop) {
    this.record_list = record_list;
    this.desktop = desktop;

    index = new ArrayIndex(record_list.size());

    model = new DefaultTableModel(column_names, 0);
    Object[] objects = new Object[column_names.length];
    objects[0] = new Boolean(true);
    for (int i = 1; i < column_names.length; i++) objects[i] = "";
    for (int i = 0; i < record_list.size(); i++) model.addRow(objects);
    setModel(model);

    column_model = (DefaultTableColumnModel) getColumnModel();
    for (int i = 1; i < column_names.length; i++)
      column_model
          .getColumn(i)
          .setCellRenderer(
              new StringRenderer(column_names[i], LabelTableCellRenderer.MODE_MULTIPLE_SELECTION));

    initializeCheckColumn();

    setTableHeader(new TableHeader(column_model));

    setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
    initializeColumnWidth();

    pane = this;

    initPopupMenu();
  }
  /**
   * Gets the list of selected records.
   *
   * @return the list of selected records.
   */
  public Variability[] getSelectedRecords() {
    ArrayList list = new ArrayList();

    int check_column = getCheckColumn();
    for (int i = 0; i < model.getRowCount(); i++) {
      if (((Boolean) getValueAt(i, check_column)).booleanValue()) {
        Variability record = (Variability) record_list.elementAt(index.get(i));
        list.add(record);
      }
    }

    Variability[] records = new Variability[list.size()];
    return (Variability[]) list.toArray(records);
  }
  /**
   * Gets the sortable array of the specified column.
   *
   * @param header_value the header value of the column to sort.
   */
  protected SortableArray getSortableArray(String header_value) {
    if (header_value.length() == 0) return null;

    SortableArray array = null;
    if (header_value.equals("R.A.") || header_value.equals("Decl.") || header_value.equals("ID"))
      array = new StringArray(record_list.size());
    else array = new Array(record_list.size());

    for (int i = 0; i < record_list.size(); i++) {
      String value = getCellString(header_value, i);

      if (header_value.equals("R.A.")
          || header_value.equals("Decl.")
          || header_value.equals("ID")) {
        ((StringArray) array).set(i, value);
      } else if (header_value.equals("Max Mag") || header_value.equals("Min Mag")) {
        double mag_value = 0.0;
        if ('0' <= value.charAt(0) && value.charAt(0) <= '9'
            || value.charAt(0) == '-'
            || value.charAt(0) == '+') {
          mag_value = Format.doubleValueOf(value);
        } else {
          mag_value = 100 + Format.doubleValueOf(value.substring(1));
        }
        ((Array) array).set(i, mag_value);
      } else if (header_value.equals("First Date") || header_value.equals("Last Date")) {
        double jd = 0.0;
        if (value.length() > 0) jd = JulianDay.create(value).getJD();
        ((Array) array).set(i, jd);
      } else {
        ((Array) array).set(i, Double.parseDouble(value));
      }
    }

    return array;
  }
  /**
   * Gets the output string of the cell.
   *
   * @param header_value the header value of the column.
   * @param row the index of row in original order.
   * @return the output string of the cell.
   */
  protected String getCellString(String header_value, int row) {
    Variability record = (Variability) record_list.elementAt(row);

    if (header_value.equals("R.A.")) {
      String coor = record.getStar().getCoor().getOutputString();
      int p = coor.indexOf(' ');
      return coor.substring(0, p);
    }
    if (header_value.equals("Decl.")) {
      String coor = record.getStar().getCoor().getOutputString();
      int p = coor.indexOf(' ');
      return coor.substring(p + 1);
    }
    if (header_value.equals("ID")) {
      if (record.getIdentifiedStar() != null) return record.getIdentifiedStar().getName();
    }
    if (header_value.equals("Max Mag")) {
      return ((XmlMag) record.getBrightestMagnitude().getMag()).getOutputString();
    }
    if (header_value.equals("Min Mag")) {
      return ((XmlMag) record.getFaintestMagnitude().getMag()).getOutputString();
    }
    if (header_value.equals("Mag Range")) {
      return Format.formatDouble(record.getMagnitudeRange(), 5, 2);
    }
    if (header_value.equals("Observations")) {
      return String.valueOf(record.getObservations());
    }
    if (header_value.equals("Positive Observations")) {
      return String.valueOf(record.getPositiveObservations());
    }
    if (header_value.equals("Arc")) {
      return String.valueOf(record.getArcInDays());
    }
    if (header_value.equals("First Date")) {
      String s = record.getFirstDate();
      if (s != null) return s;
    }
    if (header_value.equals("Last Date")) {
      String s = record.getLastDate();
      if (s != null) return s;
    }
    return "";
  }
    /** Runs this thread. */
    public void run() {
      CommonFileChooser file_chooser = new CommonFileChooser();
      file_chooser.setDialogTitle("Choose a directory.");
      file_chooser.setMultiSelectionEnabled(false);
      file_chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);

      if (file_chooser.showSaveDialog(pane) == JFileChooser.APPROVE_OPTION) {
        try {
          File directory = file_chooser.getSelectedFile();
          directory.mkdirs();

          // Outputs the variability XML file.

          String path = FileManager.unitePath(directory.getAbsolutePath(), "package.xml");
          File file = new File(path);
          if (file.exists()) {
            String message = "Overwrite to " + file.getPath() + " ?";
            if (0
                != JOptionPane.showConfirmDialog(
                    pane, message, "Confirmation", JOptionPane.YES_NO_OPTION)) {
              return;
            }
          }

          XmlVariabilityHolder holder = new XmlVariabilityHolder();

          Variability[] records = getSelectedRecords();
          for (int i = 0; i < records.length; i++) {
            XmlVariability variability = new XmlVariability(records[i]);
            holder.addVariability(variability);
          }

          holder.write(file);

          // Copies the report XML document files.

          Hashtable hash_xml = new Hashtable();

          for (int i = 0; i < records.length; i++) {
            XmlMagRecord[] mag_records = records[i].getMagnitudeRecords();
            for (int j = 0; j < mag_records.length; j++)
              hash_xml.put(mag_records[j].getImageXmlPath(), this);
          }

          Vector failed_list = new Vector();

          Enumeration keys = hash_xml.keys();
          while (keys.hasMoreElements()) {
            String xml_path = (String) keys.nextElement();
            try {
              File src_file = desktop.getFileManager().newFile(xml_path);
              File dst_file =
                  new File(FileManager.unitePath(directory.getAbsolutePath(), xml_path));
              if (dst_file.exists() == false) FileManager.copy(src_file, dst_file);
            } catch (Exception exception) {
              failed_list.addElement(xml_path);
            }
          }

          if (failed_list.size() > 0) {
            String header = "Failed to copy the following XML files:";
            MessagesDialog dialog = new MessagesDialog(header, failed_list);
            dialog.show(pane, "Error", JOptionPane.ERROR_MESSAGE);
          }

          // Copies the image files.

          failed_list = new Vector();

          keys = hash_xml.keys();
          while (keys.hasMoreElements()) {
            path = (String) keys.nextElement();
            try {
              XmlInformation info =
                  XmlReport.readInformation(desktop.getFileManager().newFile(path));
              path = info.getImage().getContent();

              File src_file = desktop.getFileManager().newFile(path);
              File dst_file = new File(FileManager.unitePath(directory.getAbsolutePath(), path));
              if (dst_file.exists() == false) FileManager.copy(src_file, dst_file);
            } catch (Exception exception) {
              failed_list.addElement(path);
            }
          }

          if (failed_list.size() > 0) {
            String header = "Failed to copy the following image files:";
            MessagesDialog dialog = new MessagesDialog(header, failed_list);
            dialog.show(pane, "Error", JOptionPane.ERROR_MESSAGE);
          }

          // Creates the sub catalog database.

          try {
            DiskFileSystem file_system =
                new DiskFileSystem(
                    new File(
                        directory.getAbsolutePath(),
                        net.aerith.misao.pixy.Properties.getDatabaseDirectoryName()));
            CatalogDBManager new_manager = new GlobalDBManager(file_system).getCatalogDBManager();

            Hashtable hash_stars = new Hashtable();
            for (int i = 0; i < records.length; i++) {
              CatalogStar star = records[i].getStar();

              CatalogDBReader reader =
                  new CatalogDBReader(desktop.getDBManager().getCatalogDBManager());
              StarList list = reader.read(star.getCoor(), 0.5);
              for (int j = 0; j < list.size(); j++) {
                CatalogStar s = (CatalogStar) list.elementAt(j);
                hash_stars.put(s.getOutputString(), s);
              }
            }

            keys = hash_stars.keys();
            while (keys.hasMoreElements()) {
              String string = (String) keys.nextElement();
              CatalogStar star = (CatalogStar) hash_stars.get(string);
              new_manager.addElement(star);
            }
          } catch (Exception exception) {
            String message = "Failed to create sub catalog database.";
            JOptionPane.showMessageDialog(pane, message, "Error", JOptionPane.ERROR_MESSAGE);
          }

          String message = "Completed.";
          JOptionPane.showMessageDialog(pane, message);
        } catch (IOException exception) {
          String message = "Failed.";
          JOptionPane.showMessageDialog(pane, message, "Error", JOptionPane.ERROR_MESSAGE);
        }
      }
    }