public void printInfo(boolean printCoordinates) {
    System.out.printf(
        "%d, %s: %d parts, %d points",
        this.getRecordNumber(),
        this.getShapeType(),
        this.getNumberOfParts(),
        this.getNumberOfPoints());
    for (Map.Entry<String, Object> a : this.getAttributes().getEntries()) {
      if (a.getKey() != null) System.out.printf(", %s", a.getKey());
      if (a.getValue() != null) System.out.printf(", %s", a.getValue());
    }
    System.out.println();

    System.out.print("\tAttributes: ");
    for (Map.Entry<String, Object> entry : this.getAttributes().getEntries()) {
      System.out.printf("%s = %s, ", entry.getKey(), entry.getValue());
    }
    System.out.println();

    if (!printCoordinates) return;

    VecBuffer vb = this.getPointBuffer(0);
    for (LatLon ll : vb.getLocations()) {
      System.out.printf("\t%f, %f\n", ll.getLatitude().degrees, ll.getLongitude().degrees);
    }
  }
  /**
   * Sets a subsequence of this buffer with the contents of the specified buffer. The subsequence to
   * set starts with the vector at the specified position, and has size equal to the specified
   * buffer's size. The specified buffer must have the same logical vector size as this buffer
   * (coordsPerVec must be equivalent).
   *
   * @param position the starting vector position to set.
   * @param buffer the input buffer.
   * @throws IllegalArgumentException if the position is out of range, if the buffer is null or
   *     incompatible, or if this buffer has insufficient length to store the sub-buffer at the
   *     specified position.
   */
  public void putSubBuffer(int position, VecBuffer buffer) {
    if (position < 0 || position >= this.getSize()) {
      String message =
          Logging.getMessage("generic.ArgumentOutOfRange", "position < 0 or position >= size");
      Logging.logger().severe(message);
      throw new IllegalArgumentException(message);
    }

    if (buffer == null) {
      String message = Logging.getMessage("nullValue.BufferIsNull");
      Logging.logger().severe(message);
      throw new IllegalArgumentException(message);
    }

    // Buffer is incompatible.
    if (this.coordsPerVec != buffer.coordsPerVec) {
      String message = Logging.getMessage("generic.BufferIncompatible", buffer);
      Logging.logger().severe(message);
      throw new IllegalArgumentException(message);
    }

    // Buffer is too large.
    int sizeNeeded = position + buffer.getSize();
    if (this.getSize() < sizeNeeded) {
      String message = Logging.getMessage("generic.BufferOverflow", this.getSize(), sizeNeeded);
      Logging.logger().severe(message);
      throw new IllegalArgumentException(message);
    }

    int index = this.indexFromVectorPosition(position);
    this.buffer.putSubBuffer(index, buffer.getBufferWrapper());
  }
  public void exportAsXML(XMLStreamWriter xmlWriter) throws IOException, XMLStreamException {
    if (xmlWriter == null) {
      String message = Logging.getMessage("Export.UnsupportedOutputObject");
      Logging.logger().warning(message);
      throw new IllegalArgumentException(message);
    }

    xmlWriter.writeStartElement("Record");

    xmlWriter.writeAttribute("id", Integer.toString(this.getRecordNumber()));
    xmlWriter.writeAttribute(
        "shape", this.getShapeType().substring(this.getShapeType().lastIndexOf("Shape") + 5));
    xmlWriter.writeAttribute("parts", Integer.toString(this.getNumberOfParts()));
    xmlWriter.writeAttribute("points", Integer.toString(this.getNumberOfPoints()));
    xmlWriter.writeCharacters("\n");

    for (Map.Entry<String, Object> a : this.getAttributes().getEntries()) {
      xmlWriter.writeStartElement("Attribute");

      xmlWriter.writeAttribute("name", a.getKey() != null ? a.getKey().toString() : "");
      xmlWriter.writeAttribute("value", a.getValue() != null ? a.getValue().toString() : "");

      xmlWriter.writeEndElement(); // Attribute
      xmlWriter.writeCharacters("\n");
    }

    if (this.getNumberOfParts() > 0) {
      VecBuffer vb = this.getPointBuffer(0);
      for (LatLon ll : vb.getLocations()) {
        xmlWriter.writeStartElement("Point");
        xmlWriter.writeAttribute("x", Double.toString(ll.getLatitude().degrees));
        xmlWriter.writeAttribute("y", Double.toString(ll.getLongitude().degrees));
        xmlWriter.writeEndElement(); // Point
        xmlWriter.writeCharacters("\n");
      }
    }

    // TODO: export record-type specific fields

    xmlWriter.writeEndElement(); // Record
  }