/**
  * Validates the uploaded resource directory
  *
  * @param directory
  * @return True if it is falid
  */
 static boolean validate(File directory, String type) {
   boolean valid = false;
   if (directory != null) {
     // Verify the directory structure:
     // /root
     // __feed.xml
     // __/items
     // ____/item
     // ______item.xml
     // ______/media.xml
     // ________...
     // ____/item
     // ______...
     VFSContainer root = new LocalFolderImpl(directory);
     // try to read podcast
     try {
       Feed feed = FeedManager.getInstance().readFeedFile(root);
       if (feed != null) {
         // The feed is valid, let's check the items
         if (feed.isInternal()) {
           List<String> itemIds = feed.getItemIds();
           VFSContainer itemsContainer = (VFSContainer) root.resolve(FeedManager.ITEMS_DIR);
           if (itemsContainer == null) {
             valid = itemIds.isEmpty(); // empty podcast
           } else {
             int validItemsCount = 0;
             for (String itemId : itemIds) {
               // Try loading each item
               VFSItem itemContainer = itemsContainer.resolve(itemId);
               Item item = FeedManager.getInstance().loadItem(itemContainer);
               if (item != null) {
                 // This item is valid, increase the counter
                 validItemsCount++;
               }
             }
             if (validItemsCount == itemIds.size()) {
               // The feed and all items are valid
               valid = true;
             }
           }
         } else if (feed.isExternal()) {
           // assume the feed url is valid.
           valid = true;
         } else if (feed.isUndefined()) {
           // the feed is empty.
           valid = true;
         }
         // check type
         if (!type.equals(feed.getResourceableTypeName())) {
           valid = false;
         }
       }
     } catch (Exception e) {
       // Reading feed failed, the directory is hence invalid
     }
   }
   return valid;
 }
  public FeedFileResource(File root, File resourceFolder, String type) {
    super.setTypeName(type);
    // After unziping the uploaded folder, I would like to copy it to the
    // appropriate location right away (and not on the next read). So, I put the
    // code here. Note that this constructor is also called on copying a
    // resource. We know that the resource folder is valid.

    // Let's now copy the resource folder to the root folder.
    VFSContainer rootContainer = new LocalFolderImpl(root);
    String folderName = FeedManager.getInstance().getFeedKind(this);
    if (rootContainer.resolve(folderName) == null) {
      // If the podcast directory doesn't exist yet, create it and copy content
      // from uploaded folder
      rootContainer = rootContainer.createChildContainer(folderName);
      VFSContainer resourceContainer = new LocalFolderImpl(resourceFolder);
      for (VFSItem item : resourceContainer.getItems()) {
        rootContainer.copyFrom(item);
        // Delete the item if it is located in the _unzipped_ dir.
        // Remember that the resource folder could be a valid folder of a
        // different resource (when copying the resource).
        if (resourceContainer.getName().equals(FileResourceManager.ZIPDIR)) {
          item.delete();
        }
      }
    }
  }
 /**
  * @see
  *     org.olat.repository.handlers.RepositoryHandler#cleanupOnDelete(org.olat.core.id.OLATResourceable,
  *     org.olat.core.gui.UserRequest, org.olat.core.gui.control.WindowControl)
  */
 @Override
 public boolean cleanupOnDelete(final OLATResourceable res) {
   CoordinatorManager.getInstance()
       .getCoordinator()
       .getEventBus()
       .fireEventToListenersOf(new OLATResourceableJustBeforeDeletedEvent(res), res);
   // For now, notifications are not implemented since a blog feed is meant
   // to be subscriped to anyway.
   // NotificationsManager.getInstance().deletePublishersOf(res);
   FeedManager.getInstance().delete(res);
   return true;
 }
 /**
  * @see
  *     org.olat.repository.handlers.RepositoryHandler#acquireLock(org.olat.core.id.OLATResourceable,
  *     org.olat.core.id.Identity)
  */
 @Override
 public LockResult acquireLock(final OLATResourceable ores, final Identity identity) {
   return FeedManager.getInstance().acquireLock(ores, identity);
 }
 /**
  * @see org.olat.repository.handlers.RepositoryHandler#isLocked(org.olat.core.id.OLATResourceable)
  */
 @Override
 public boolean isLocked(final OLATResourceable ores) {
   return FeedManager.getInstance().isLocked(ores);
 }
 /**
  * @see
  *     org.olat.repository.handlers.RepositoryHandler#releaseLock(org.olat.core.util.coordinate.LockResult)
  */
 @Override
 public void releaseLock(final LockResult lockResult) {
   FeedManager.getInstance().releaseLock(lockResult);
 }
 /**
  * @see
  *     org.olat.repository.handlers.RepositoryHandler#getAsMediaResource(org.olat.core.id.OLATResourceable)
  */
 @Override
 public MediaResource getAsMediaResource(final OLATResourceable res) {
   final FeedManager manager = FeedManager.getInstance();
   return manager.getFeedArchiveMediaResource(res);
 }
 /**
  * @see
  *     org.olat.repository.handlers.RepositoryHandler#createCopy(org.olat.core.id.OLATResourceable,
  *     org.olat.core.gui.UserRequest)
  */
 @Override
 public OLATResourceable createCopy(final OLATResourceable res, final UserRequest ureq) {
   final FeedManager manager = FeedManager.getInstance();
   return manager.copy(res);
 }