docs: @Override
      public boolean registerForNotifications(Notification targets, NotificationListener callbackObject) throws IllegalArgumentException {
          // Convert the targets to the right root, only need to do this if we have a fake root
          final Notification rootNotification;
          if (this.isNotifierForFakeRoot) {
              // Have a fake root so convert the paths, need to also move ! to the front of the path to indicate a non-recursive listener
              Collection<String> newTargetPaths = new HashSet<String>();
              for (String oldPath : targets.getPaths()) {
                  final StringBuilder newPath = new StringBuilder();
                  if (oldPath.startsWith("!")) {
                      newPath.append("!");
                      oldPath = oldPath.substring(1);
                  }
                  newPath.append(pathInRealRoot);
                  // Notification paths don't end in "/", except for root.
                  // "/x.jar" + "/" should result in "/x.jar", not "/x.jar/".
                  if (!oldPath.equals("/")) {
                      newPath.append(oldPath);
                  }
                  newTargetPaths.add(newPath.toString());
              }
              rootNotification = new DefaultNotification(targets.getContainer(), newTargetPaths);
          } else {
              /*
               * We aren't a fake root so we can use the original set of targets, even if the targets live within a child fake root that is ok as the targets in the artifact API
               * will be the same, we'll sort out converting the child fake root when we get a notification back
               */
              rootNotification = targets;
          }
  
          /*
           * Instead of registering the callbackObject directly, wrap it in a CorrectInterpretedPath listener that will handle converting paths given by the artifact layer to the
           * correct state as seen by the interpreted layer
           */
          CorrectInterpretedPathListener interpretedListener = new CorrectInterpretedPathListener(callbackObject);
  
          // Now register against our delegate, this will also validate the targets
          boolean isRegistered = this.delegateNotifier.registerForNotifications(rootNotification, interpretedListener);
          if (isRegistered) {
              // We could register with the delegate so keep track of the listener (in case we need to unregister it later)
              this.listeners.put(callbackObject, interpretedListener);
          }
          return isRegistered;
      }