code: public List<Resource<L>> removeResources(L query, LocationResolver<L> locationResolver) {
          graphLockWrite.lock();
          try {
              List<Resource<L>> doomedResources = new ArrayList<Resource<L>>();
              GraphIterator<Resource<L>, DefaultEdge> it = new DepthFirstIterator<>(this.resourcesGraph);
              while (it.hasNext()) {
                  Resource<L> resource = it.next();
                  if (locationResolver.matches(query, resource.getLocation())) {
                      getAllDescendants(resource, doomedResources);
                      doomedResources.add(resource);
                  }
              }
  
              // we couldn't do this while iterating (a ConcurrentModificationException would have resulted)
              // but now that we have the doomed resources, we can remove them from the graph now
              for (Resource<L> doomedResource : doomedResources) {
                  this.resourcesGraph.removeVertex(doomedResource);
              }
  
              return Collections.unmodifiableList(doomedResources);
          } finally {
              graphLockWrite.unlock();
          }
      }
docs: Remove the resources from {@link #resourcesGraph} matching the given {@code query} including all direct and
  indirect descendants.
  
  @param query a location eventually containing wildcards
  @param locationResolver the {@link LocationResolver} to perform the matching of graph nodes against the given
  {@code query}
  @return an unmodifiable list of {@link Resources} that were removed by this method