<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def MultiDelete(self, urns, token=None):
 """Drop all the information about given objects. DANGEROUS! This recursively deletes all objects contained within the specified URN. Args: urns: Urns of objects to remove. token: The Security Token to use for opening this item. Raises: ValueError: If one of the urns is too short. This is a safety check to ensure the root is not removed. """

    urns = [rdfvalue.RDFURN(urn) for urn in urns]

    if token is None:
      token = data_store.default_token

    for urn in urns:
      if urn.Path() == "/":
        raise ValueError("Can't delete root URN. Please enter a valid URN")

    deletion_pool = DeletionPool(token=token)
    deletion_pool.MultiMarkForDeletion(urns)

    marked_root_urns = deletion_pool.root_urns_for_deletion
    marked_urns = deletion_pool.urns_for_deletion

    logging.debug(u"Found %d objects to remove when removing %s",
                  len(marked_urns), urns)

    logging.debug(u"Removing %d root objects when removing %s: %s",
                  len(marked_root_urns), urns, marked_root_urns)

    pool = data_store.DB.GetMutationPool()
    for root in marked_root_urns:
      # Only the index of the parent object should be updated. Everything
      # below the target object (along with indexes) is going to be
      # deleted.
      self._DeleteChildFromIndex(root, mutation_pool=pool)

    for urn_to_delete in marked_urns:
      try:
        self.intermediate_cache.ExpireObject(urn_to_delete.Path())
      except KeyError:
        pass

    pool.DeleteSubjects(marked_urns)
    pool.Flush()

    # Ensure this is removed from the cache as well.
    self.Flush()

    logging.debug("Removed %d objects", len(marked_urns))