/* * Jajuk * Copyright (C) The Jajuk Team * http://jajuk.info * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ package org.jajuk.base; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Locale; import org.jajuk.util.Const; import org.jajuk.util.MD5Processor; import org.jajuk.util.ReadOnlyIterator; import org.jajuk.util.UtilSystem; /** * Convenient class to manage directories. */ public final class DirectoryManager extends ItemManager { /** Self instance. */ private static DirectoryManager singleton = new DirectoryManager(); /** * Return hashcode for this item. * * @param sName directory name * @param device device * @param dParent parent directory * * @return ItemManager ID */ protected static String createID(final String sName, final Device device, final Directory dParent) { final StringBuilder sbAbs = new StringBuilder(device.getName()); // Under windows, all files/directories with different cases should get // the same ID if (UtilSystem.isUnderWindows()) { if (dParent != null) { sbAbs.append(dParent.getRelativePath().toLowerCase(Locale.getDefault())); } sbAbs.append(sName.toLowerCase(Locale.getDefault())); } else { if (dParent != null) { sbAbs.append(dParent.getRelativePath()); } sbAbs.append(sName); } return MD5Processor.hash(sbAbs.toString()); } /** * Gets the instance. * * @return singleton */ public static DirectoryManager getInstance() { return DirectoryManager.singleton; } /** * No constructor available, only static access. */ private DirectoryManager() { super(); // ---register properties--- // ID registerProperty(new PropertyMetaInformation(Const.XML_ID, false, true, false, false, false, String.class, null)); // Name test with (getParentDirectory() != null); //name editable only // for standard // directories, not root registerProperty(new PropertyMetaInformation(Const.XML_NAME, false, true, true, false, false, String.class, null)); // @TODO edition // Parent registerProperty(new PropertyMetaInformation(Const.XML_DIRECTORY_PARENT, false, true, true, false, false, String.class, null)); // Device registerProperty(new PropertyMetaInformation(Const.XML_DEVICE, false, true, true, false, false, String.class, null)); // Expand registerProperty(new PropertyMetaInformation(Const.XML_EXPANDED, false, false, false, false, true, Boolean.class, false)); // Synchronized directory registerProperty(new PropertyMetaInformation(Const.XML_DIRECTORY_SYNCHRONIZED, false, false, true, false, false, Boolean.class, true)); } /** * Clean all references for the given device. * * @param sId : * Device id */ public void cleanDevice(final String sId) { lock.writeLock().lock(); try { for (Directory directory : getDirectories()) { if (directory.getDevice().getID().equals(sId)) { removeItem(directory); } } } finally { lock.writeLock().unlock(); } } /** * Gets a defensive copy of all directories. * * @return ordered directories list */ @SuppressWarnings("unchecked") public List<Directory> getDirectories() { return (List<Directory>) getItems(); } /** * Gets the directories iterator. * * @return directories iterator */ @SuppressWarnings("unchecked") public ReadOnlyIterator<Directory> getDirectoriesIterator() { return new ReadOnlyIterator<Directory>((Iterator<Directory>) getItemsIterator()); } /** * Gets the directory by id. * * @param sID Item ID * * @return Directory matching the id */ Directory getDirectoryByID(final String sID) { return (Directory) getItemByID(sID); } /** * Gets the directory for io. * * @param fio * @param device Associated device * @return Directory matching the io file */ public Directory getDirectoryForIO(final java.io.File fio, Device device) { for (Directory dir : getDirectories()) { // we have to test the device because of cdroms : all CD have the same IO if (dir.getFio().equals(fio) && dir.getDevice().equals(device)) { return dir; } } return null; } /* * (non-Javadoc) * * @see org.jajuk.base.ItemManager#getIdentifier() */ @Override public String getXMLTag() { return Const.XML_DIRECTORIES; } /** * Register a root device directory. * * @param device * * @return the directory */ public Directory registerDirectory(final Device device) { return registerDirectory(device.getID(), "", null, device); } /** * Register a directory. * * @param sName * @param dParent * @param device * * @return the directory */ public Directory registerDirectory(final String sName, final Directory dParent, final Device device) { return registerDirectory(DirectoryManager.createID(sName, device, dParent), sName, dParent, device); } /** * Register a directory with a known id. * * @param sId * @param sName * @param dParent * @param device * @return the directory */ Directory registerDirectory(final String sId, final String sName, final Directory dParent, final Device device) { Directory directory = getDirectoryByID(sId); if (directory != null) { return directory; } directory = new Directory(sId, sName, dParent, device); registerItem(directory); return directory; } /** * Remove a directory and all subdirectories from main directory repository. * Remove reference from parent directories as well. * * @param sId */ public void removeDirectory(final String sId) { lock.writeLock().lock(); try { final Directory dir = getDirectoryByID(sId); if (dir == null) {// check the directory has not already been // removed return; } // remove all files // need to use a defensive copy to avoid concurrent exceptions final List<File> alFiles = new ArrayList<File>(dir.getFiles()); for (final File file : alFiles) { FileManager.getInstance().removeFile(file); } // remove all playlists for (final Playlist plf : dir.getPlaylistFiles()) { PlaylistManager.getInstance().removeItem(plf); } // remove all sub dirs final Iterator<Directory> it = dir.getDirectories().iterator(); while (it.hasNext()) { final Directory dSub = it.next(); removeDirectory(dSub.getID()); // self call // remove it it.remove(); } // remove this dir from collection removeItem(dir); } finally { lock.writeLock().unlock(); } } }