/** pre-condition: mergeTo and beMerged are isostructural */
 private static void mergeFiles0(@Nonnull File mergeTo, @Nonnull File beMerged) {
   if (mergeTo.getClass() == DirectoryFile.class) {
     mergeDirectoryFiles((DirectoryFile) mergeTo, (DirectoryFile) beMerged);
   } else if (mergeTo.getClass() == RegularFile.class) {
     mergeRegularFiles((RegularFile) mergeTo, (RegularFile) beMerged);
   } else {
     throw new UnsupportedOperationException("Unsupported File Type:" + mergeTo.getClass());
   }
 }
 private boolean isostructuralEquals(File o1, File o2) {
   return o1 == o2
       || ( // ignore UselessParentheses. have it more clear
       o1.getClass() == o2.getClass() // NOPMD
           && isostructuralEquals(o1.getParent(), o2.getParent())
           && Objects.equals(o1.getPath(), o2.getPath()));
 }
 /**
  * @param file {@link RegularFile} or {@link DirectoryFile}
  * @param algorithmsContainer the result which is used Algorithms in file
  * @return if algorithmsContainer.containsAll(ALL_ALGORITHMS)
  */
 private static boolean getUsedAlgorithms0(File file, Set<Hash.Algorithm> algorithmsContainer) {
   if (file instanceof RegularFile) {
     algorithmsContainer.addAll(getUsedAlgorithms1((RegularFile) file));
     return algorithmsContainer.size() == ALL_ALGORITHMS_LENGTH;
   } else if (file instanceof DirectoryFile) {
     for (File child : file.getChildren()) {
       if (getUsedAlgorithms0(child, algorithmsContainer)) {
         return true;
       }
     }
     return false;
   } else {
     throw new RuntimeException("Shouldn't goto here");
   }
 }