package tim.prune.function.cache;
import java.io.File;
import java.util.ArrayList;
import tim.prune.gui.map.MapSource;
import tim.prune.gui.map.MapSourceLibrary;
/**
* Class to obtain and hold information about the current
* tile cache including its subdirectories
*/
public class TileCacheModel
{
/** Cache directory */
private File _cacheDir = null;
/** Array of tilesets */
private ArrayList<TileSet> _tileSets = null;
/** Summary information */
private RowInfo _summaryRow = null;
/** Cancelled flag */
private boolean _cancelled = false;
/**
* Constructor
* @param inDir start directory
*/
public TileCacheModel(File inDir)
{
if (inDir != null && inDir.exists() && inDir.isDirectory() && inDir.canRead()) {
_cacheDir = inDir;
}
_cancelled = false;
}
/**
* Build the tilesets by searching recursively
*/
public void buildTileSets()
{
if (_cacheDir == null) return;
_tileSets = new ArrayList<TileSet>();
// go through subdirectories, if any
File[] subdirs = _cacheDir.listFiles();
for (File subdir : subdirs)
{
if (subdir != null && subdir.isDirectory() && subdir.exists() && subdir.canRead()
&& !_cancelled)
{
getTileSets(subdir, null, _tileSets);
}
}
// Loop over found tile sets and create summary rowinfo
_summaryRow = new RowInfo();
for (TileSet ts : _tileSets)
{
_summaryRow.addRow(ts.getRowInfo());
}
}
/**
* Get all the tilesets from the given directory
* @param inDir directory to search
* @return array of TileSet objects
*/
private static void getTileSets(File inDir, String inParentPath, ArrayList<TileSet> inTsList)
{
final String wholePath = (inParentPath == null ? "" : inParentPath)
+ inDir.getName() + File.separator;
// See if any configured backgrounds use this directory
// or if the directories match OSM structure
String usedByDesc = matchConfig(wholePath);
boolean tsFound = false;
if (usedByDesc != null || looksLikeCacheDir(inDir))
{
TileSet ts = new TileSet(inDir, wholePath, usedByDesc);
if (usedByDesc != null || ts.getRowInfo().getNumTiles() > 0)
{
tsFound = true;
inTsList.add(ts);
}
}
// If a tileset wasn't found, look through subdirectories
if (!tsFound)
{
// Go through subdirectories and look at each of them too
File[] subdirs = inDir.listFiles();
if (subdirs != null) {
for (File subdir : subdirs)
{
if (subdir != null && subdir.exists() && subdir.isDirectory()
&& subdir.canRead())
{
getTileSets(subdir, wholePath, inTsList);
}
}
}
}
}
/**
* Match the given directory name to find the configs which use it
* @param inName name of directory to match
* @return null if not used, otherwise comma-separated list of background names
*/
private static String matchConfig(String inName)
{
if (inName == null || inName.equals(""))
return null;
String usedBy = null;
for (int i=0; i<MapSourceLibrary.getNumSources(); i++)
{
MapSource ms = MapSourceLibrary.getSource(i);
for (int l=0; l<2; l++)
{
String msdir = ms.getSiteName(l);
if (msdir != null && msdir.equals(inName))
{
if (usedBy == null)
usedBy = ms.getName();
else
usedBy = usedBy + ", " + ms.getName();
}
}
}
return usedBy;
}
/**
* @param inDir directory to test
* @return true if the subdirectories meet the normal osm layout
*/
private static boolean looksLikeCacheDir(File inDir)
{
// look for at least one numeric directory, nothing else
boolean numFound = false;
if (inDir != null && inDir.exists() && inDir.isDirectory() && inDir.canRead())
{
for (File subdir : inDir.listFiles())
{
// Only consider readable things which exist
if (subdir != null && subdir.exists() && subdir.canRead())
{
// subdirectories should have numeric names (for the zoom levels)
if (subdir.isDirectory() && TileSet.isNumeric(subdir.getName())
&& subdir.getName().length() < 3)
{
numFound = true;
}
else return false; // either a file or non-numeric directory
}
}
}
return numFound;
}
/**
* @return cache directory
*/
public File getCacheDir() {
return _cacheDir;
}
/**
* @return number of tile sets
*/
public int getNumTileSets()
{
if (_tileSets == null) return 0;
return _tileSets.size();
}
/**
* @return the total number of tile images found
*/
public int getTotalTiles()
{
return _summaryRow.getNumTiles();
}
/**
* @return the total number of bytes taken up with tile images
*/
public long getTotalBytes()
{
return _summaryRow.getTotalSize();
}
/**
* @param inIndex index of tileset
* @return requested tileset
*/
public TileSet getTileSet(int inIndex)
{
if (inIndex >= 0 && inIndex < getNumTileSets()) {
return _tileSets.get(inIndex);
}
return null;
}
/**
* Cancel the search
*/
public void cancel() {
_cancelled = true;
}
/**
* @return true if search was cancelled
*/
public boolean isAborted() {
return _cancelled;
}
}