code: static String resolveZipEntryName(File zipDirectory, File file) {
  
      return Optional.ofNullable(zipDirectory)
        .filter(File::isDirectory)
        .map(File::getName)
        .filter(StringUtils::hasText)
        .map(zipDirectoryName -> {
  
          String filePath = file.getAbsolutePath();
  
          int index = filePath.indexOf(zipDirectoryName);
  
          return index > -1 ? filePath.substring(index) : null;
        })
        .orElseGet(file::getName);
    }
docs: Tries to resolve the {@link String} of the {@link ZipEntry} given the {@link File directory} being zipped
  and the {@link File} from when the {@link ZipEntry} is being constructed.
  
  The resolved {@link ZipEntry} {@link String name} will be the relative path of the given {@link File}
  if the {@link File} is relative to the given {@link File directory}, otherwise the {@link ZipEntry}
  {@link String name} will be the {@link String name} of the given {@link File}.
  
  If {@link File diretory} is {@literal null}, or is not a valid {@link File directory},
  or the {@link File directory} refers to the root of the file system (i.e. the {@link File#getName() name}
  of the {@link File directory} is {@link String empty}), then the resolved {@link ZipEntry} {@link String name}
  will be the {@link String name} of the given {@link File}.
  
  @param zipDirectory {@link File directory} being zipped.
  @param file {@link File} used to construct the {@link ZipEntry}; must not be {@literal null}.
  @return the resolved {@link String name} of the {@link ZipEntry}.
  @see java.io.File