Esempio n. 1
0
    public ConeQueryRowSequence createQuerySequence(StarTable table) throws IOException {
      assert rowMap_ == null || rowMap_.length == table.getRowCount();
      final RowSequence rseq = table.getRowSequence();
      return new ConeQueryRowSequence() {
        long irow_ = -1;

        public boolean next() throws IOException {
          if (matchWorker_ != null && matchWorker_.cancelled_) {
            throw new IOException("Cancelled");
          }
          boolean retval = rseq.next();
          if (matchWorker_ != null && matchWorker_.cancelled_) {
            throw new IOException("Cancelled");
          }
          if (retval) {
            irow_++;
            if (matchWorker_ != null) {
              matchWorker_.setInputRow((int) irow_);
            }
          }
          return retval;
        }

        public Object getCell(int icol) throws IOException {
          return rseq.getCell(icol);
        }

        public Object[] getRow() throws IOException {
          return rseq.getRow();
        }

        public void close() throws IOException {
          rseq.close();
        }

        public double getRa() throws IOException {
          return Math.toDegrees(getDoubleValue(raData_));
        }

        public double getDec() throws IOException {
          return Math.toDegrees(getDoubleValue(decData_));
        }

        public double getRadius() throws IOException {
          return Math.toDegrees(getDoubleValue(srData_));
        }

        private double getDoubleValue(ColumnData cdata) throws IOException {
          if (cdata != null) {
            long jrow = rowMap_ == null ? irow_ : rowMap_[(int) irow_];
            Object value = cdata.readValue(jrow);
            return value instanceof Number ? ((Number) value).doubleValue() : Double.NaN;
          } else {
            return Double.NaN;
          }
        }
      };
    }
  public void writeData(DataOutput strm) throws IOException {

    /* Work out the length of each row in bytes. */
    int rowBytes = 0;
    int ncol = table.getColumnCount();
    for (int icol = 0; icol < ncol; icol++) {
      ColumnWriter writer = colWriters[icol];
      if (writer != null) {
        rowBytes += writer.getLength();
      }
    }

    /* Write the data cells, delegating the item in each column to
     * the writer that knows how to handle it. */
    long nWritten = 0L;
    RowSequence rseq = table.getRowSequence();
    try {
      while (rseq.next()) {
        Object[] row = rseq.getRow();
        for (int icol = 0; icol < ncol; icol++) {
          ColumnWriter writer = colWriters[icol];
          if (writer != null) {
            writer.writeValue(strm, row[icol]);
          }
        }
        nWritten += rowBytes;
      }
    } finally {
      rseq.close();
    }

    /* Write padding. */
    int extra = (int) (nWritten % (long) 2880);
    if (extra > 0) {
      strm.write(new byte[2880 - extra]);
    }
  }
  /**
   * Configures this serializer for use with a given table and column writer factory. Should be
   * called before this object is ready for use; in a constructor would be a good place. Calls
   * {@link #createColumnWriter}.
   *
   * @param table table to be written
   */
  final void init(StarTable table) throws IOException {
    if (this.table != null) {
      throw new IllegalStateException("Table already initialised");
    }
    this.table = table;

    /* Get table dimensions (though we may need to calculate the row
     * count directly later. */
    int ncol = table.getColumnCount();
    long nrow = table.getRowCount();

    /* Store column infos. */
    colInfos = Tables.getColumnInfos(table);

    /* Work out column shapes, and check if any are unknown (variable
     * last dimension). */
    boolean hasVarShapes = false;
    boolean checkForNullableInts = false;
    int[][] shapes = new int[ncol][];
    int[] maxChars = new int[ncol];
    int[] maxElements = new int[ncol];
    long[] totalElements = new long[ncol];
    boolean[] useCols = new boolean[ncol];
    boolean[] varShapes = new boolean[ncol];
    boolean[] varChars = new boolean[ncol];
    boolean[] varElementChars = new boolean[ncol];
    boolean[] mayHaveNullableInts = new boolean[ncol];
    Arrays.fill(useCols, true);
    boolean[] hasNulls = new boolean[ncol];
    for (int icol = 0; icol < ncol; icol++) {
      ColumnInfo colinfo = colInfos[icol];
      Class clazz = colinfo.getContentClass();
      if (clazz.isArray()) {
        shapes[icol] = (int[]) colinfo.getShape().clone();
        int[] shape = shapes[icol];
        if (shape[shape.length - 1] < 0) {
          varShapes[icol] = true;
          hasVarShapes = true;
        } else {
          int nel = shape.length > 0 ? 1 : 0;
          for (int id = 0; id < shape.length; id++) {
            nel *= shape[id];
          }
          assert nel >= 0;
          maxElements[icol] = nel;
        }
        if (clazz.getComponentType().equals(String.class)) {
          maxChars[icol] = colinfo.getElementSize();
          if (maxChars[icol] <= 0) {
            varElementChars[icol] = true;
            hasVarShapes = true;
          }
        }
      } else if (clazz.equals(String.class)) {
        maxChars[icol] = colinfo.getElementSize();
        if (maxChars[icol] <= 0) {
          varChars[icol] = true;
          hasVarShapes = true;
        }
      } else if (colinfo.isNullable()
          && (clazz == Byte.class
              || clazz == Short.class
              || clazz == Integer.class
              || clazz == Long.class)) {
        mayHaveNullableInts[icol] = true;

        /* Only set the flag which forces a first pass if we need
         * to work out whether nulls actually exist.  If the
         * aux datum giving a null value exists we will use it in
         * any case, so finding out whether there are in fact null
         * values by scanning the data is not necessary. */
        if (colinfo.getAuxDatumValue(Tables.NULL_VALUE_INFO, Number.class) != null) {
          hasNulls[icol] = true;
        } else {
          checkForNullableInts = true;
        }
      }
    }

    /* If necessary, make a first pass through the table data to
     * find out the maximum size of variable length fields and the length
     * of the table. */
    if (hasVarShapes || checkForNullableInts || nrow < 0) {
      StringBuffer sbuf = new StringBuffer("First pass needed: ");
      if (hasVarShapes) {
        sbuf.append("(variable array shapes) ");
      }
      if (checkForNullableInts) {
        sbuf.append("(nullable ints) ");
      }
      if (nrow < 0) {
        sbuf.append("(unknown row count) ");
      }
      logger.config(sbuf.toString());
      nrow = 0L;

      /* Get the maximum dimensions. */
      RowSequence rseq = table.getRowSequence();
      try {
        while (rseq.next()) {
          nrow++;
          for (int icol = 0; icol < ncol; icol++) {
            if (useCols[icol]
                && (varShapes[icol]
                    || varChars[icol]
                    || varElementChars[icol]
                    || (mayHaveNullableInts[icol] && !hasNulls[icol]))) {
              Object cell = rseq.getCell(icol);
              if (cell == null) {
                if (mayHaveNullableInts[icol]) {
                  hasNulls[icol] = true;
                }
              } else {
                if (varChars[icol]) {
                  int leng = ((String) cell).length();
                  maxChars[icol] = Math.max(maxChars[icol], leng);
                } else if (varElementChars[icol]) {
                  String[] svals = (String[]) cell;
                  for (int i = 0; i < svals.length; i++) {
                    maxChars[icol] = Math.max(maxChars[icol], svals[i].length());
                  }
                }
                if (varShapes[icol]) {
                  int nel = Array.getLength(cell);
                  maxElements[icol] = Math.max(maxElements[icol], nel);
                  totalElements[icol] += nel;
                }
              }
            }
          }
        }
      } finally {
        rseq.close();
      }

      /* In the case of variable string lengths and no non-null data
       * in any of the cells, maxChars could still be set negative.
       * Fix that here. */
      for (int icol = 0; icol < ncol; icol++) {
        if (maxChars[icol] < 0) {
          maxChars[icol] = 0;
        }
      }

      /* Furthermore, zero length strings are probably a bad idea
       * for FITS output.  Make sure that all output strings have
       * a length of at least 1. */
      for (int icol = 0; icol < ncol; icol++) {
        if (maxChars[icol] == 0) {
          maxChars[icol] = 1;
        }
      }

      /* Work out the actual shapes for columns which have variable ones,
       * based on the shapes that we encountered in the rows. */
      if (hasVarShapes) {
        for (int icol = 0; icol < ncol; icol++) {
          if (useCols[icol]) {
            if (varShapes[icol]) {
              int[] shape = shapes[icol];
              int ndim = shape.length;
              assert shape[ndim - 1] <= 0;
              int nel = 1;
              for (int i = 0; i < ndim - 1; i++) {
                nel *= shape[i];
              }
              shape[ndim - 1] = Math.max(1, (maxElements[icol] + nel - 1) / nel);
            }
          }
        }
      }
    }

    /* Store the row count, which we must have got by now. */
    assert nrow >= 0;
    rowCount = nrow;

    /* We now have all the information we need about the table.
     * Construct and store a custom writer for each column which
     * knows about the characteristics of the column and how to
     * write values to the stream.  For columns which can't be
     * written in FITS format store a null in the writers array
     * and log a message. */
    colWriters = new ColumnWriter[ncol];
    int rbytes = 0;
    for (int icol = 0; icol < ncol; icol++) {
      if (useCols[icol]) {
        ColumnInfo cinfo = colInfos[icol];
        ColumnWriter writer =
            createColumnWriter(
                cinfo,
                shapes[icol],
                varShapes[icol],
                maxChars[icol],
                maxElements[icol],
                totalElements[icol],
                mayHaveNullableInts[icol] && hasNulls[icol]);
        if (writer == null) {
          logger.warning(
              "Ignoring column " + cinfo.getName() + " - don't know how to write to FITS");
        }
        colWriters[icol] = writer;
      }
    }
  }