private void appendFileSecs(DigitalObject obj, PrintWriter writer)
      throws ObjectIntegrityException, StreamIOException {
    Iterator<String> iter = obj.datastreamIdIterator();
    boolean didFileSec = false;
    while (iter.hasNext()) {
      Datastream ds =
          DOTranslationUtility.setDatastreamDefaults(
              obj.datastreams(iter.next()).iterator().next());
      if (!ds.DSControlGrp.equals("X")) {
        if (!didFileSec) {
          didFileSec = true;
          writer.print("<");
          writer.print(METS.prefix);
          writer.print(":fileSec>\n");
          writer.print("<");
          writer.print(METS.prefix);
          writer.print(":fileGrp ID=\"DATASTREAMS\">\n");
        }
        writer.print("<");
        writer.print(METS.prefix);
        writer.print(":fileGrp ID=\"");
        writer.print(ds.DatastreamID);
        writer.print("\" STATUS=\"");
        writer.print(ds.DSState);
        writer.print("\" VERSIONABLE=\"");
        writer.print(ds.DSVersionable);
        writer.print("\">\n");
        Iterator<Datastream> contentIter = obj.datastreams(ds.DatastreamID).iterator();
        while (contentIter.hasNext()) {
          Datastream dsc = DOTranslationUtility.setDatastreamDefaults(contentIter.next());

          writer.print("<");
          writer.print(METS.prefix);
          writer.print(":file ID=\"");
          writer.print(dsc.DSVersionID);
          writer.print("\"");
          if (dsc.DSCreateDT != null) {
            writer.print(" CREATED=\"");
            writer.print(DateUtility.convertDateToString(dsc.DSCreateDT));
            writer.print("\"");
          }
          writer.print(" MIMETYPE=\"");
          writer.print(StreamUtility.enc(dsc.DSMIME));
          writer.print("\"");
          if (dsc.DSSize != 0) {
            writer.print(" SIZE=\"" + dsc.DSSize + "\"");
          }
          if (dsc.DSFormatURI != null && !dsc.DSFormatURI.equals("")) {
            writer.print(" FORMAT_URI=\"");
            writer.print(StreamUtility.enc(dsc.DSFormatURI));
            writer.print("\"");
          }
          String altIds = DOTranslationUtility.oneString(dsc.DatastreamAltIDs);
          if (altIds != null && !altIds.equals("")) {
            writer.print(" ALT_IDS=\"");
            writer.print(StreamUtility.enc(altIds));
            writer.print("\"");
          }
          String csType = ds.DSChecksumType;
          if (csType != null
              && csType.length() > 0
              && !csType.equals(Datastream.CHECKSUMTYPE_DISABLED)) {
            writer.print(" CHECKSUM=\"");
            writer.print(StreamUtility.enc(ds.DSChecksum));
            writer.print("\"");
            writer.print(" CHECKSUMTYPE=\"");
            writer.print(StreamUtility.enc(csType));
            writer.print("\"");
          }
          writer.print(" OWNERID=\"");
          writer.print(dsc.DSControlGrp);
          writer.print("\">\n");
          if (m_transContext == DOTranslationUtility.SERIALIZE_EXPORT_ARCHIVE
              && dsc.DSControlGrp.equalsIgnoreCase("M")) {
            serializeDatastreamContent(dsc, writer);
          } else {
            writer.print("<");
            writer.print(METS.prefix);
            writer.print(":FLocat");
            if (dsc.DSLabel != null && !dsc.DSLabel.equals("")) {
              writer.print(" ");
              writer.print(XLINK.prefix);
              writer.print(":title=\"");
              writer.print(StreamUtility.enc(dsc.DSLabel));
              writer.print("\"");
            }
            writer.print(" LOCTYPE=\"URL\" ");
            writer.print(XLINK.prefix);
            writer.print(":href=\"");
            writer.print(
                StreamUtility.enc(
                    DOTranslationUtility.normalizeDSLocationURLs(obj.getPid(), dsc, m_transContext)
                        .DSLocation));
            writer.print("\"/>\n");
          }
          writer.print("</");
          writer.print(METS.prefix);
          writer.print(":file>\n");
        }
        writer.print("</");
        writer.print(METS.prefix);
        writer.print(":fileGrp>\n");
      }
    }
    if (didFileSec) {
      writer.print("</");
      writer.print(METS.prefix);
      writer.print(":fileGrp>\n");
      writer.print("</");
      writer.print(METS.prefix);
      writer.print(":fileSec>\n");
    }
  }
  private void appendMDSec(
      DigitalObject obj,
      String outerName,
      String innerName,
      Iterable<Datastream> XMLMetadata,
      PrintWriter writer,
      String encoding)
      throws ObjectIntegrityException, UnsupportedEncodingException, StreamIOException {
    DatastreamXMLMetadata first =
        (DatastreamXMLMetadata)
            DOTranslationUtility.setDatastreamDefaults(XMLMetadata.iterator().next());
    writer.print("<");
    writer.print(METS.prefix);
    writer.print(":");
    writer.print(outerName);
    writer.print(" ID=\"");
    writer.print(first.DatastreamID);
    writer.print("\" STATUS=\"");
    writer.print(first.DSState);
    writer.print("\" VERSIONABLE=\"");
    writer.print(first.DSVersionable);
    writer.print("\">\n");
    for (Datastream d : XMLMetadata) {
      DatastreamXMLMetadata ds =
          (DatastreamXMLMetadata) DOTranslationUtility.setDatastreamDefaults(d);

      writer.print("<");
      writer.print(METS.prefix);
      writer.print(":");
      writer.print(innerName);
      writer.print(" ID=\"");
      writer.print(ds.DSVersionID);
      writer.print("\"");
      if (ds.DSCreateDT != null) {
        writer.print(" CREATED=\"");
        writer.print(DateUtility.convertDateToString(ds.DSCreateDT));
        writer.print("\"");
      }
      writer.print(">\n");

      writer.print("<");
      writer.print(METS.prefix);
      writer.print(":mdWrap MIMETYPE=\"");
      writer.print(StreamUtility.enc(ds.DSMIME));
      writer.print("\" MDTYPE=\"");
      String mdType = ds.DSInfoType;
      if (!mdType.equals("MARC")
          && !mdType.equals("EAD")
          && !mdType.equals("DC")
          && !mdType.equals("NISOIMG")
          && !mdType.equals("LC-AV")
          && !mdType.equals("VRA")
          && !mdType.equals("TEIHDR")
          && !mdType.equals("DDI")
          && !mdType.equals("FGDC")) {
        writer.print("OTHER\" OTHERMDTYPE=\"");
        writer.print(StreamUtility.enc(mdType));
      } else {
        writer.print(mdType);
      }
      writer.print("\" ");

      if (ds.DSLabel != null && !ds.DSLabel.equals("")) {
        writer.print(" LABEL=\"");
        writer.print(StreamUtility.enc(ds.DSLabel));
        writer.print("\"");
      }

      if (ds.DSFormatURI != null && !ds.DSFormatURI.equals("")) {
        writer.print(" FORMAT_URI=\"");
        writer.print(StreamUtility.enc(ds.DSFormatURI));
        writer.print("\"");
      }

      String altIds = DOTranslationUtility.oneString(ds.DatastreamAltIDs);
      if (altIds != null && !altIds.equals("")) {
        writer.print(" ALT_IDS=\"");
        writer.print(StreamUtility.enc(altIds));
        writer.print("\"");
      }

      // CHECKSUM and CHECKSUMTYPE are also optional
      String csType = ds.DSChecksumType;
      if (csType != null
          && csType.length() > 0
          && !csType.equals(Datastream.CHECKSUMTYPE_DISABLED)) {
        writer.print(" CHECKSUM=\"");
        writer.print(StreamUtility.enc(ds.DSChecksum));
        writer.print("\" CHECKSUMTYPE=\"");
        writer.print(StreamUtility.enc(csType));
        writer.print("\"");
      }

      writer.print(">\n");
      writer.print("<");
      writer.print(METS.prefix);
      writer.print(":xmlData>\n");

      // If WSDL or SERVICE-PROFILE datastream (in SDep)
      // make sure that any embedded URLs are encoded
      // appropriately for either EXPORT or STORE.
      if (obj.hasContentModel(SERVICE_DEPLOYMENT_3_0) && ds.DatastreamID.equals("SERVICE-PROFILE")
          || ds.DatastreamID.equals("WSDL")) {
        writer.print(
            DOTranslationUtility.normalizeInlineXML(
                new String(ds.xmlContent, "UTF-8").trim(), m_transContext));
      } else {
        DOTranslationUtility.appendXMLStream(ds.getContentStream(), writer, encoding);
      }
      writer.print("\n</");
      writer.print(METS.prefix);
      writer.print(":xmlData>");
      writer.print("</");
      writer.print(METS.prefix);
      writer.print(":mdWrap>\n");
      writer.print("</");
      writer.print(METS.prefix);
      writer.print(":");
      writer.print(innerName);
      writer.print(">\n");
    }
    writer.print("</");
    writer.print(METS.prefix);
    writer.print(":");
    writer.print(outerName);
    writer.print(">\n");
  }