docs: @Override
      //TODO: invoke parent overlay notifyEntryChange for the entry representing this overlay in parent, if this overlay is a nested overlay.
      public void notifyEntryChange(ArtifactNotification added, ArtifactNotification removed, ArtifactNotification modified, String filter) {
          //the overlay will call us via this method as the mask set is manipulated.
          //if we have no listeners, we have no need to do anything.
          if (listeners.isEmpty())
              return;
  
          //added/removed/modified will all have the same container set for any invocation, so we can just test 'added'
          if (added.getContainer() == overlayContainer) {
              //remove any paths from the notification that were already present in the original container.
              //eg.
              //  if added to overlay and already present in base, convert to modified.
              //  if removed from overlay and already present in base, convert to modified.
              //  if modified in overlay, leave as modified.
              Set<String> filteredAdd = filterExistingPaths(added.getPaths());
              Set<String> filteredRemoved = filterExistingPaths(removed.getPaths());
  
              //remove the converted from the set..
              Set<String> newAdd = new HashSet(filterMaskedPaths(added.getPaths()));
              newAdd.removeAll(filteredAdd);
  
              Set<String> newRemoved = new HashSet(filterMaskedPaths(removed.getPaths()));
              newRemoved.removeAll(filteredRemoved);
  
              Set<String> newModified = new HashSet<String>(modified.getPaths().size());
              //filter out masked from the modified set..
              newModified.addAll(filterMaskedPaths(modified.getPaths()));
              //add in the add/deletes that are being converted..
              newModified.addAll(filteredAdd);
              newModified.addAll(filteredRemoved);
  
              //now iterate the registered listeners, and invoke them with the subsets that they cared about..
              notifyAllListeners(newAdd, newRemoved, newModified, filter);
          }
          if (added.getContainer() == overlaidContainer) {
              //remove any paths from the notification that are overlaid.
              Set<String> filteredAdd = filterOverlaidPaths(added.getPaths());
              Set<String> filteredRemoved = filterOverlaidPaths(removed.getPaths());
              Set<String> filteredModified = filterOverlaidPaths(modified.getPaths());
  
              //now iterate the registered listeners, and invoke them with the subsets that they cared about..
              notifyAllListeners(filteredAdd, filteredRemoved, filteredModified, filter);
          }
          if (added.getContainer() == root) {
              //this is a special invocation coming in from the mask unmask logic..
              //there is no need to prefilter the paths here.
              notifyAllListeners(added.getPaths(), removed.getPaths(), modified.getPaths(), filter);
          }
  
      }