package com.limegroup.gnutella.library; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.limewire.collection.IntSet; import org.limewire.util.FileUtils; import org.limewire.util.Objects; import com.limegroup.gnutella.URN; abstract class AbstractFileView implements FileView { private final IntSet indexes = new IntSet(); protected final LibraryImpl library; public AbstractFileView(LibraryImpl library) { this.library = library; } /** * Returns the {@link IntSet} that is internally used to store * the index of {@link FileDesc}s contained in this view. * * Subclasses can use this to perform operations in bulk. * The read lock should be held while using this, or if a subclass * modifies it it should consistently hold a write lock * while mutating it. */ protected IntSet getInternalIndexes() { return indexes; } @Override public boolean contains(File file) { return getFileDesc(file) != null; } @Override public boolean contains(FileDesc fileDesc) { getReadLock().lock(); try { return indexes.contains(fileDesc.getIndex()); } finally { getReadLock().unlock(); } } @Override public FileDesc getFileDesc(URN urn) { List<FileDesc> descs = getFileDescsMatching(urn); if(descs.isEmpty()) { return null; } else { return descs.get(0); } } @Override public FileDesc getFileDesc(File f) { FileDesc fd = library.getFileDesc(f); if(fd != null && contains(fd)) { return fd; } else { return null; } } @Override public FileDesc getFileDescForIndex(int index) { FileDesc fd = library.getFileDescForIndex(index); if(fd != null && contains(fd)) { return fd; } else { return null; } } @Override public List<FileDesc> getFileDescsMatching(URN urn) { List<FileDesc> fds = null; List<FileDesc> matching = library.getFileDescsMatching(urn); // Optimal case. if(matching.size() == 1 && contains(matching.get(0))) { return matching; } else { for(FileDesc fd : matching) { if(contains(fd)) { if(fds == null) { fds = new ArrayList<FileDesc>(matching.size()); } fds.add(fd); } } if(fds == null) { return Collections.emptyList(); } else { return fds; } } } @Override public int size() { getReadLock().lock(); try { return indexes.size(); } finally { getReadLock().unlock(); } } @Override public List<FileDesc> getFilesInDirectory(File directory) { // Remove case, trailing separators, etc. try { directory = FileUtils.getCanonicalFile(Objects.nonNull(directory, "directory")); } catch (IOException e) { // invalid directory ? return Collections.emptyList(); } List<FileDesc> list = new ArrayList<FileDesc>(); getReadLock().lock(); try { for(FileDesc fd : this) { if(directory.equals(fd.getFile().getParentFile())) { list.add(fd); } } } finally { getReadLock().unlock(); } return list; } }