private void appendDisseminators(DigitalObject obj, PrintWriter writer)
      throws ObjectIntegrityException {
    Iterator<String> dissIdIter = obj.disseminatorIdIterator();
    while (dissIdIter.hasNext()) {
      String did = dissIdIter.next();
      Disseminator diss =
          DOTranslationUtility.setDisseminatorDefaults(obj.disseminators(did).get(0));
      writer.print("<");
      writer.print(METS.prefix);
      writer.print(":behaviorSec ID=\"");
      writer.print(did);
      writer.print("\" STATUS=\"");
      writer.print(diss.dissState);
      writer.print("\">\n");
      for (int i = 0; i < obj.disseminators(did).size(); i++) {
        diss = DOTranslationUtility.setDisseminatorDefaults(obj.disseminators(did).get(i));
        writer.print("<");
        writer.print(METS.prefix);
        writer.print(":serviceBinding ID=\"");
        writer.print(diss.dissVersionID);
        writer.print("\" STRUCTID=\"");
        writer.print(diss.dsBindMapID);
        writer.print("\" BTYPE=\"");
        writer.print(diss.bDefID);
        writer.print("\" CREATED=\"");
        writer.print(DateUtility.convertDateToString(diss.dissCreateDT));
        writer.print("\"");
        if (diss.dissLabel != null && !diss.dissLabel.equals("")) {
          writer.print(" LABEL=\"");
          writer.print(StreamUtility.enc(diss.dissLabel));
          writer.print("\"");
        }
        writer.print(">\n");
        writer.print("<");
        writer.print(METS.prefix);
        writer.print(":interfaceMD LOCTYPE=\"URN\" ");
        writer.print(XLINK.prefix);
        writer.print(":href=\"");
        writer.print(diss.bDefID);
        writer.print("\"/>\n");
        writer.print("<");
        writer.print(METS.prefix);
        writer.print(":serviceBindMD LOCTYPE=\"URN\" ");
        writer.print(XLINK.prefix);
        writer.print(":href=\"");
        writer.print(diss.sDepID);
        writer.print("\"/>\n");

        writer.print("</");
        writer.print(METS.prefix);
        writer.print(":serviceBinding>\n");
      }
      writer.print("</");
      writer.print(METS.prefix);
      writer.print(":behaviorSec>\n");
    }
  }
  private void appendHdr(DigitalObject obj, PrintWriter writer) throws ObjectIntegrityException {
    writer.print("<");
    writer.print(METS.prefix);
    writer.print(":metsHdr");
    Date cDate = obj.getCreateDate();
    if (cDate != null) {
      writer.print(" CREATEDATE=\"");
      writer.print(DateUtility.convertDateToString(cDate));
      writer.print("\"");
    }
    Date mDate = obj.getLastModDate();
    if (mDate != null) {
      writer.print(" LASTMODDATE=\"");
      writer.print(DateUtility.convertDateToString(mDate));
      writer.print("\"");
    }

    writer.print(" RECORDSTATUS=\"");
    writer.print(DOTranslationUtility.getStateAttribute(obj));
    writer.print("\"");

    writer.print(">\n");
    // use agent to identify the owner of the digital object
    String ownerId = obj.getOwnerId();
    if (ownerId != null && !ownerId.equals("")) {
      writer.print("<");
      writer.print(METS.prefix);
      writer.print(":agent");
      writer.print(" ROLE=\"IPOWNER\">\n");
      writer.print("<");
      writer.print(METS.prefix);
      writer.print(":name>");
      writer.print(ownerId);
      writer.print("</");
      writer.print(METS.prefix);
      writer.print(":name>\n");
      writer.print("</");
      writer.print(METS.prefix);
      writer.print(":agent>\n");
    }
    writer.print("</");
    writer.print(METS.prefix);
    writer.print(":metsHdr>\n");
  }
 private void appendAuditRecordAdminMD(DigitalObject obj, PrintWriter writer)
     throws ObjectIntegrityException {
   if (obj.getAuditRecords().size() > 0) {
     writer.print("<");
     writer.print(METS.prefix);
     writer.print(":amdSec ID=\"AUDIT\" STATUS=\"A\" VERSIONABLE=\"false\">\n");
     writer.print("<");
     writer.print(METS.prefix);
     writer.print(":digiprovMD ID=\"AUDIT.0\" CREATED=\"");
     writer.print(DateUtility.convertDateToString(obj.getCreateDate()));
     writer.print("\">\n");
     writer.print("<");
     writer.print(METS.prefix);
     writer.print(":mdWrap MIMETYPE=\"text/xml\" MDTYPE=\"OTHER\"");
     writer.print(" OTHERMDTYPE=\"FEDORA-AUDIT\"");
     writer.print(" LABEL=\"Audit Trail for this object\"");
     writer.print(" FORMAT_URI=\"");
     writer.print(AUDIT1_0.uri);
     writer.print("\">\n");
     writer.print("<");
     writer.print(METS.prefix);
     writer.print(":xmlData>\n");
     DOTranslationUtility.appendAuditTrail(obj, writer);
     writer.print("</");
     writer.print(METS.prefix);
     writer.print(":xmlData>\n");
     writer.print("</");
     writer.print(METS.prefix);
     writer.print(":mdWrap>\n");
     writer.print("</");
     writer.print(METS.prefix);
     writer.print(":digiprovMD>\n");
     writer.print("</");
     writer.print(METS.prefix);
     writer.print(":amdSec>\n");
   }
 }
 private void appendStructMaps(DigitalObject obj, PrintWriter writer)
     throws ObjectIntegrityException {
   Iterator<String> dissIdIter = obj.disseminatorIdIterator();
   while (dissIdIter.hasNext()) {
     String did = dissIdIter.next();
     Iterator<Disseminator> dissIter = obj.disseminators(did).iterator();
     while (dissIter.hasNext()) {
       Disseminator diss = DOTranslationUtility.setDisseminatorDefaults(dissIter.next());
       writer.print("<");
       writer.print(METS.prefix);
       writer.print(":structMap ID=\"");
       writer.print(diss.dsBindMapID);
       writer.print("\" TYPE=\"fedora:dsBindingMap\">\n");
       writer.print("<");
       writer.print(METS.prefix);
       writer.print(":div TYPE=\"");
       writer.print(diss.sDepID);
       writer.print("\"");
       if (diss.dsBindMap.dsBindMapLabel != null && !diss.dsBindMap.dsBindMapLabel.equals("")) {
         writer.print(" LABEL=\"");
         writer.print(StreamUtility.enc(diss.dsBindMap.dsBindMapLabel));
         writer.print("\"");
       }
       writer.print(">\n");
       DSBinding[] bindings = diss.dsBindMap.dsBindings;
       for (int i = 0; i < bindings.length; i++) {
         if (bindings[i].bindKeyName == null || bindings[i].bindKeyName.equals("")) {
           throw new ObjectIntegrityException(
               "Object's disseminator" + " binding map binding must have a binding key name.");
         }
         writer.print("<");
         writer.print(METS.prefix);
         writer.print(":div TYPE=\"");
         writer.print(bindings[i].bindKeyName);
         if (bindings[i].bindLabel != null && !bindings[i].bindLabel.equals("")) {
           writer.print("\" LABEL=\"");
           writer.print(StreamUtility.enc(bindings[i].bindLabel));
         }
         if (bindings[i].seqNo != null && !bindings[i].seqNo.equals("")) {
           writer.print("\" ORDER=\"");
           writer.print(bindings[i].seqNo);
         }
         if (bindings[i].datastreamID == null || bindings[i].datastreamID.equals("")) {
           throw new ObjectIntegrityException(
               "Object's disseminator" + " binding map binding must point to a datastream.");
         }
         writer.print("\">\n<");
         writer.print(METS.prefix);
         writer.print(":fptr FILEID=\"");
         writer.print(bindings[i].datastreamID);
         writer.print("\"/>\n");
         writer.print("</");
         writer.print(METS.prefix);
         writer.print(":div>\n");
       }
       writer.print("</");
       writer.print(METS.prefix);
       writer.print(":div>\n");
       writer.print("</");
       writer.print(METS.prefix);
       writer.print(":structMap>\n");
     }
   }
 }
  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");
  }
  private void appendRootElementStart(DigitalObject obj, PrintWriter writer)
      throws ObjectIntegrityException {
    writer.print("<");
    writer.print(METS.METS.qName);
    if (m_format.equals(METS_EXT1_1)) {
      writer.print(" ");
      writer.print(METS_EXT.EXT_VERSION.localName);
      writer.print("=\"1.1\"");
    }
    writer.print(" ");
    writer.print(METS.OBJID.localName);
    writer.print("=\"");
    writer.print(obj.getPid());
    writer.print("\"");

    if (m_format.equals(METS_EXT1_0) && DOTranslationUtility.getTypeAttribute(obj) != null) {
      writer.print(" ");
      writer.print(METS.TYPE.localName);
      writer.print("=\"");
      writer.print(DOTranslationUtility.getTypeAttribute(obj).localName);
      writer.print("\"");
    }

    writer.print("\n");
    String label = obj.getLabel();
    if (label != null && label.length() > 0) {
      writer.print(METS.LABEL.localName);
      writer.print("=\"");
      writer.print(StreamUtility.enc(label));
      writer.print("\"\n");
    }
    writer.print("xmlns:");
    writer.print(METS.prefix);
    writer.print("=\"");
    writer.print(METS.uri);
    writer.print("\"\n");
    if (m_format.equals(METS_EXT1_0)) {
      writer.print("xmlns:");
      writer.print(XLINK.prefix);
      writer.print("=\"");
      writer.print(OLD_XLINK.uri);
      writer.print("\"\n");
    } else {
      writer.print("xmlns:");
      writer.print(XLINK.prefix);
      writer.print("=\"");
      writer.print(XLINK.uri);
      writer.print("\"\n");
    }
    writer.print("xmlns:");
    writer.print(XSI.prefix);
    writer.print("=\"");
    writer.print(XSI.uri);
    writer.print("\"\n");
    writer.print(XSI.SCHEMA_LOCATION.qName);
    writer.print("=\"");
    writer.print(METS.uri);
    writer.print(" ");
    writer.print(m_format.xsdLocation);
    writer.print("\">\n");
  }