code: private static Function<FedoraEvent, Stream<FedoraEvent>> handleMoveEvents(final Session session) {
          return evt -> {
              if (evt.getTypes().contains(RESOURCE_RELOCATION)) {
                  final Map<String, String> movePath = evt.getInfo();
                  final String dest = movePath.get("destAbsPath");
                  final String src = movePath.get("srcAbsPath");
                  final FedoraSession fsession = new FedoraSessionImpl(session);
  
                  try {
                      final FedoraResource resource = new FedoraResourceImpl(session.getNode(evt.getPath()));
                      return concat(of(evt), resource.getChildren(true).map(FedoraResource::getPath)
                          .flatMap(path -> of(
                              new FedoraEventImpl(RESOURCE_RELOCATION, path, evt.getResourceTypes(), evt.getUserID(),
                                  fsession.getUserURI(), evt.getDate(), evt.getInfo()),
                              new FedoraEventImpl(RESOURCE_DELETION, path.replaceFirst(dest, src), evt.getResourceTypes(),
                                  evt.getUserID(), fsession.getUserURI(), evt.getDate(), evt.getInfo()))));
                  } catch (final RepositoryException ex) {
                      throw new RepositoryRuntimeException(ex);
                  }
              }
              return of(evt);
          };
      }
docs: Note: This function maps a FedoraEvent to a Stream of some number of FedoraEvents. This is because a MOVE event
  may lead to an arbitrarily large number of additional events for any child resources. In the event of this not
  being a MOVE event, the same FedoraEvent is returned, wrapped in a Stream. For a MOVEd resource, the resource in
  question will be translated to two FedoraEvents: a MOVED event for the new resource location and a REMOVED event
  corresponding to the old location. The same pair of FedoraEvents will also be generated for each child resource.