code: public <T extends EventObject> void call(final CrawlEvent event, final T eventObject) {
          if (!customCallbacks.containsKey(event)) {
              ((Consumer<T>) defaultCallbacks.get(event)).accept(eventObject);
              return;
          }
  
          String requestUrl = eventObject.getCrawlCandidate().getRequestUrl().toString();
          List<PatternMatchingCallback> applicableCallbacks = customCallbacks.get(event)
                  .stream()
                  .filter(callback -> callback.getUrlPattern().matcher(requestUrl).matches())
                  .collect(Collectors.toList());
  
          if (applicableCallbacks.isEmpty()) {
              ((Consumer<T>) defaultCallbacks.get(event)).accept(eventObject);
              return;
          }
  
          applicableCallbacks.stream()
                  .map(PatternMatchingCallback::getCallback)
                  .forEach(op -> op.accept(eventObject));
      }
docs: Invokes the default callback for the specific event, if no custom callbacks are registered
  for it. Otherwise, it calls all the associated callbacks whose pattern matches the URL of the
  request.
  
  @param <T>         the type of the input to the operation
  @param event       the event for which the callback should be invoked
  @param eventObject the input parameter for the callback