public void addCategoryMonitor(MeemPath meemPath, CategoryMonitor categoryMonitor) {

    LinkedList<String> paths = new LinkedList<String>();

    String space = meemPath.getSpace().getType();

    String location = meemPath.getLocation();
    StringTokenizer tok = new StringTokenizer(location, "/");
    while (tok.hasMoreTokens()) {
      paths.add(tok.nextToken());
    }

    // start with the space
    CategoryMonitorMapPair spaceMonitorMapPair = null;
    synchronized (monitoredSpaces) {
      spaceMonitorMapPair = (CategoryMonitorMapPair) monitoredSpaces.get(space);

      if (spaceMonitorMapPair == null) {
        // The only time this is ok is if the paths list is empty
        if (paths.size() == 0) {
          spaceMonitorMapPair = new CategoryMonitorMapPair(categoryMonitor);
          monitoredSpaces.put(space, spaceMonitorMapPair);
          // we are done
          return;
        } else {
          throw new RuntimeException("Tried to add a MeemPath with a previously unseen space type");
        }
      }
    }

    Map<String, CategoryMonitorMapPair> children = spaceMonitorMapPair.getChildren();
    CategoryMonitorMapPair pair = spaceMonitorMapPair;

    for (int i = 0; i < paths.size() - 1; i++) {
      String pathName = (String) paths.get(i);

      pair = children.get(pathName);

      if (pair != null) {
        children = pair.getChildren();
      } else {
        throw new RuntimeException(
            "Tried to add a MeemPath whose parents are not being watched: " + meemPath);
      }
    }

    // we should now have the new category watchers parent pair
    String pathName = (String) paths.get(paths.size() - 1);

    pair.addChild(pathName, categoryMonitor);
  }
  public CategoryMonitorMapPair getCategoryMonitorMapPair(MeemPath meemPath) {

    List<String> paths = new LinkedList<String>();

    String space = meemPath.getSpace().getType();

    String location = meemPath.getLocation();
    StringTokenizer tok = new StringTokenizer(location, "/");
    while (tok.hasMoreTokens()) {
      paths.add(tok.nextToken());
    }

    CategoryMonitorMapPair spaceMonitorMapPair =
        (CategoryMonitorMapPair) monitoredSpaces.get(space);

    if (spaceMonitorMapPair == null) {
      // not watching this space type. return straight away
      return null;
    }

    if (paths.size() == 0) {
      // if this is the case, we are just looking at the space
      return spaceMonitorMapPair;
    }

    Map<String, CategoryMonitorMapPair> children = spaceMonitorMapPair.getChildren();
    for (int i = 0; i < paths.size() - 1; i++) {
      String pathName = (String) paths.get(i);

      CategoryMonitorMapPair pair = (CategoryMonitorMapPair) children.get(pathName);

      if (pair != null) {
        children = pair.getChildren();
      } else {
        return null;
      }
    }

    String pathName = (String) paths.get(paths.size() - 1);

    return (CategoryMonitorMapPair) children.get(pathName);
  }
  public void removeMeemPath(MeemPath meemPath) {
    List<String> paths = new LinkedList<String>();

    String space = meemPath.getSpace().getType();

    String location = meemPath.getLocation();
    StringTokenizer tok = new StringTokenizer(location, "/");
    while (tok.hasMoreTokens()) {
      paths.add(tok.nextToken());
    }

    // go thru all the category watchers in the meempath and remove this meempath from their list of
    // paths to watch

    if (paths.size() > 0) {

      CategoryMonitorMapPair spaceMonitorMapPair =
          (CategoryMonitorMapPair) monitoredSpaces.get(space);

      spaceMonitorMapPair
          .getCategoryMonitor()
          .removeWatchedMeemPath((String) paths.get(0), meemPath);

      Map<String, CategoryMonitorMapPair> children = spaceMonitorMapPair.getChildren();
      for (int i = 0; i < paths.size() - 1; i++) {
        String pathName = (String) paths.get(i);
        String nextPathName = (String) paths.get(i + 1);

        CategoryMonitorMapPair pair = (CategoryMonitorMapPair) children.get(pathName);

        if (pair != null) {
          pair.getCategoryMonitor().removeWatchedMeemPath(nextPathName, meemPath);
          children = pair.getChildren();
        }
      }
    }
  }