private static <T extends WorkspaceEntity, R> R processEntityChanges(@NotNull VersionedStorageChange event,
                                                                       Class<T> entityClass,
                                                                       Predicate<T> filter,
                                                                       BiFunction<T, T, Boolean> equalsBy,
                                                                       ChangeProcessor<T, R> proc) {
    for (EntityChange<T> change : event.getChanges(entityClass)) {
      final T before = change.getOldEntity();
      final T after = change.getNewEntity();
      boolean shouldContinue = true;
      if (after != null) {
        if (before != null) {
          if ((filter.test(before) || filter.test(after)) && !equalsBy.apply(before, after)) {
            shouldContinue = proc.changed(before, after);
          }
        }
        else if (filter.test(after)) {
          shouldContinue = proc.added(after);
        }
      }
      else if (before != null && filter.test(before)) {
        shouldContinue = proc.removed(before);
      }
      if (!shouldContinue) {
        return proc.getResult();
      }
    }
    return proc.getResult();
  }
private static <T extends WorkspaceEntity, R> R processEntityChanges(@NotNull VersionedStorageChange event,
                                                                       Class<T> entityClass,
                                                                       Predicate<T> filter,
                                                                       BiFunction<T, T, Boolean> equalsBy,
                                                                       ChangeProcessor<T, R> proc)