/* XXL: The eXtensible and fleXible Library for data processing Copyright (C) 2000-2011 Prof. Dr. Bernhard Seeger Head of the Database Research Group Department of Mathematics and Computer Science University of Marburg Germany This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; If not, see <http://www.gnu.org/licenses/>. http://code.google.com/p/xxl/ */ package xxl.core.io.fat; import java.util.Iterator; import java.util.NoSuchElementException; /** * This class iterates over a list of clusters. The object returned by the next method * is a byte array representation of the actual cluster. */ public class ClusterChainIterator implements Iterator { /** * Object of FATDevice. */ protected FATDevice device; /** * Actual number of cluster. */ protected long clusterNumber; /** * Indicates if the clusterNumber belongs to the root directory. */ protected boolean isRoot; /** * Indicates if there is a next cluster. */ protected boolean hasNext; /** * Actual cluster. */ protected byte[] cluster; /** * Creates an instance of this object. If the given clusterNumber belongs to * the root directory in case of FAT12 or FAT16 the isRoot flag has to be true * and the clusterNumber has to be direct. Otherwise the given clusterNumber has * to be indirect. * @param device object of FATDevice. * @param clusterNumber number of cluster where the iteration should start. * @param isRoot indicates if the clusterNumber belongs to the root directory. */ public ClusterChainIterator(FATDevice device, long clusterNumber, boolean isRoot) { this.device = device; this.clusterNumber = clusterNumber; this.isRoot = isRoot; hasNext = true; if (isRoot && device.getFatType() != FAT.FAT32) { cluster = new byte[512]; if (!device.readSector(cluster, clusterNumber)) //read only sector because the root directory is only accessible by sectors cluster = null; } else { cluster = device.readCluster(device.getFirstSectorNumberOfCluster(clusterNumber)); } } //end constructor /** * Returns true if the iteration has more elements. (In other words, * returns true if next would return an element rather than * throwing an exception.) * @return true if the iterator has more elements. */ public boolean hasNext() { if (hasNext) return hasNext; if (isRoot && device.getFatType() != FAT.FAT32) { if ((++clusterNumber) < device.getNumRootDirSectors() + device.getFirstRootDirSector()) { cluster = new byte[512]; if (!device.readSector(cluster,clusterNumber)) //read only sector because the root directory is only accessible by sectors cluster = null; hasNext = true; return true; } } else { clusterNumber = device.getFatContent(clusterNumber); if (!device.isLastCluster(clusterNumber)) { cluster = device.readCluster(device.getFirstSectorNumberOfCluster(clusterNumber)); hasNext = true; return true; } } return false; } //end next /** * Returns the next element in the iteration. * @return the cluster as byte[] * about the actual directory entry. * @throws NoSuchElementException in case iteration has no more elements * @see xxl.core.io.fat.DirectoryEntryInformation */ public Object next() throws NoSuchElementException { if (hasNext) { hasNext = false; return cluster; } else { if (!hasNext()) throw new NoSuchElementException(); else { hasNext = false; return cluster; } } } //end next /** * Not implemented yet. * @throws UnsupportedOperationException */ public void remove() { throw new UnsupportedOperationException(); } //end remove() /** * Return the clusterNumber. * @return the clusterNumber. */ public long getClusterNumber() { return clusterNumber; } /** * Return the flag that indicates if the actual cluster belongs to the root directory. * @return true if the actual cluster belongs to the root directory; false otherwise. */ public boolean isRoot() { return isRoot; } } //end class ClusterChainIterator