@Override
  public void process(
      OpusDocument opusDocument, ModsDocument modsDocument, InfoDocument infoDocument)
      throws Exception {
    final Document opus = opusDocument.getOpus().getOpusDocument();
    final ModsDefinition mods = modsDocument.getMods();

    final Boolean hasPublisherName = nodeExists("PublisherName[text()!='']", opus);
    final Boolean hasPublisherPlace = nodeExists("PublisherPlace[text()!='']", opus);
    final Boolean hasServerDatePublished = nodeExists("ServerDatePublished", opus);

    if (hasPublisherName || hasPublisherPlace || hasServerDatePublished) {
      OriginInfoDefinition oid =
          (OriginInfoDefinition) select("mods:originInfo[@eventType='distribution']", mods);

      if (oid == null) {
        oid = mods.addNewOriginInfo();
        oid.setEventType("distribution");
        signalChanges(MODS_CHANGES);
      }

      if (hasPublisherName) mapPublisherName(opus, oid);
      if (hasPublisherPlace) mapPublisherPlace(opus, oid);
      if (hasServerDatePublished) mapServerDatePublished(opus, oid);
    }
  }
  private void mapPublisherName(Document opus, OriginInfoDefinition oid) {
    final String publisherName = opus.getPublisherName();

    XmlString modsPublisher = (XmlString) select("mods:publisher", oid);

    if (modsPublisher == null) {
      modsPublisher = oid.addNewPublisher();
      signalChanges(MODS_CHANGES);
    }

    if (!modsPublisher.getStringValue().equals(publisherName)) {
      modsPublisher.setStringValue(publisherName);
      signalChanges(MODS_CHANGES);
    }
  }
  private void mapPublisherPlace(Document opus, OriginInfoDefinition oid) {
    final String publisherPlace = singleline(opus.getPublisherPlace());

    PlaceDefinition pd = (PlaceDefinition) select("mods:place", oid);

    if (pd == null) {
      pd = oid.addNewPlace();
      signalChanges(MODS_CHANGES);
    }

    PlaceTermDefinition ptd =
        (PlaceTermDefinition)
            select("mods:placeTerm[@type='text' and text()='" + publisherPlace + "']", pd);

    if (ptd == null) {
      ptd = pd.addNewPlaceTerm();
      ptd.setType(TEXT);
      ptd.setStringValue(publisherPlace);
      signalChanges(MODS_CHANGES);
    }
  }
  private void mapServerDatePublished(Document opus, OriginInfoDefinition oid) {
    final String mappedDateEncoding = dateEncoding(opus.getServerDatePublished());

    DateDefinition dateIssued =
        (DateDefinition)
            select(
                String.format(
                    "mods:dateIssued[@encoding='%s' and @keyDate='%s']", "iso8601", "yes"),
                oid);

    if (dateIssued == null) {
      dateIssued = oid.addNewDateIssued();
      dateIssued.setEncoding(ISO_8601);
      dateIssued.setKeyDate(XmlString.Factory.newValue("yes"));
      signalChanges(MODS_CHANGES);
    }

    if (!dateIssued.getStringValue().equals(mappedDateEncoding)) {
      dateIssued.setStringValue(mappedDateEncoding);
      signalChanges(MODS_CHANGES);
    }
  }