// **********************************************************************
// <copyright>
// BBN Technologies
// 10 Moulton Street
// Cambridge, MA 02138
// (617) 873-8000
//
// Copyright (C) BBNT Solutions LLC. All rights reserved.
// </copyright>
// **********************************************************************
// $Source: /cvs/distapps/openmap/src/vpfservlet/WEB-INF/src/com/bbn/openmap/vpfservlet/TileHolder.java,v $
// $Revision: 1.4 $ $Date: 2005/08/11 20:39:15 $ $Author: dietrick $
// **********************************************************************
package com.bbn.openmap.vpfservlet;
import java.io.File;
import java.util.List;
import java.util.Vector;
import com.bbn.openmap.io.FormatException;
import com.bbn.openmap.layer.vpf.DcwCrossTileID;
import com.bbn.openmap.layer.vpf.DcwRecordFile;
import com.bbn.openmap.layer.vpf.TilingAdapter;
import com.bbn.openmap.layer.vpf.VPFUtil;
/**
* This class provides easy access to tiled data.
*/
public class TileHolder {
/** the name of the primitive file */
private final String fileName;
/** the current open tile */
private DcwRecordFile currentTileFile;
/** the index (into tileStuff) of the current open tile */
private int curTile;
/** an array of tile paths */
private String tileStuff[];
/** the directory which has tile subdirectories */
private final File basepath;
/**
* Construct a TileHolder. close() should be called when you are
* done with the object.
*
* @param basepath the directory which has tile subdirectories
* @param fileName the name of the primitive file
* @param isTiled if the coverage is tiled or not. If it is,
* tiling information is assumed to be located in
* $basepath/../tileref
* @throws FormatException something went wrong
*/
public TileHolder(File basepath, String fileName, boolean isTiled)
throws FormatException {
this.fileName = fileName;
this.basepath = basepath;
curTile = -1;
if (isTiled) {
tileStuff = doTileRefStuff(basepath);
} else {
currentTileFile = new DcwRecordFile(basepath + File.separator
+ fileName);
}
}
/**
* Gets a row from a primitive file in a coverage.
*
* @param tileColumn the column index used to get the tile id
* @param rowColumn the column index used to get the row id
* @param tileRow the row to retrieve the tile and row IDs from
* @param retrow the row gotten from the file
* @return true if the row was fetched, false otherwise
* @throws FormatException
*/
public boolean getRow(int tileColumn, int rowColumn, List tileRow,
List retrow) throws FormatException {
int tileId = (tileColumn == -1) ? -1
: VPFUtil.objectToInt(tileRow.get(tileColumn));
int rowId = VPFUtil.objectToInt(tileRow.get(rowColumn));
return getRow(tileId, rowId, retrow);
}
public boolean getRow(TilingAdapter ta, List tileRow, List retrow)
throws FormatException {
return getRow(ta.getTileId(tileRow), ta.getTilePrimId(tileRow), retrow);
}
public boolean getRow(DcwCrossTileID prim, List retrow)
throws FormatException {
return getRow(prim.nextTileID, prim.nextTileKey, retrow);
}
/**
* Gets a row from a primitive file in a coverage.
*
* @param tileId the tile identifier
* @param rowId the row identifier
* @param retrow the row gotten from the file
* @return true if the row was fetched, false otherwise
* @throws FormatException
*/
public boolean getRow(int tileId, int rowId, List retrow)
throws FormatException {
if (rowId <= 0) {
return false;
}
if (tileId != curTile) {
File joinfile = new File(basepath + File.separator
+ tileStuff[tileId]);
close();
currentTileFile = new DcwRecordFile(joinfile + File.separator
+ fileName);
curTile = tileId;
}
return currentTileFile.getRow(retrow, rowId);
}
/**
* Closes any related tables.
*/
public void close() {
if (currentTileFile != null) {
currentTileFile.close();
}
currentTileFile = null;
}
/**
* Loads tiling information for the coverage.
*
* @param path the path to the coverage. tiling info is in
* ../tileref
* @return an array of tile paths
*/
private static String[] doTileRefStuff(File path) throws FormatException {
File pathname = new File(path.getParentFile(), "tileref");
String faceIDColumnName = null;
// read fcs to figure out what column in tileref.aft we need
// to use to
// read the fbr (face bounding rectangle) table
File fcsFile = new File(pathname, "fcs");
if (!fcsFile.canRead()) {
fcsFile = new File(pathname, "fcs.");
}
DcwRecordFile fcs = new DcwRecordFile(fcsFile.toString());
Vector fcsv = new Vector(fcs.getColumnCount());
while (fcs.parseRow(fcsv)) {
String fclass = ((String) fcsv.elementAt(1)).toLowerCase();
String table1 = ((String) fcsv.elementAt(2)).toLowerCase();
if ((fclass.equals("tileref")) && (table1.equals("tileref.aft"))) {
faceIDColumnName = (String) fcsv.elementAt(3);
break;
}
}
fcs.close();
if (faceIDColumnName == null) {
throw new FormatException("no faceIDColumn");
// won't be able to read the tiling info. abort
}
// Okay, we've got info on what column we use from tileref.aft
// to index
// into the fbr.
DcwRecordFile aft = new DcwRecordFile(pathname + File.separator
+ "tileref.aft");
int faceIDColumn = aft.whatColumn(faceIDColumnName.toLowerCase());
int tileNameColumn = aft.whatColumn("tile_name");
if ((faceIDColumn == -1) || (tileNameColumn == -1)) {
aft.close();
throw new FormatException("no faceIDColumn");
}
Vector aftv = new Vector(aft.getColumnCount());
// set the array size to record count + 1, to be able to
// use the tileID as the index into the array
String containedTiles[] = new String[aft.getRecordCount() + 1];
int tileid = 1;
while (aft.parseRow(aftv)) {
//int fac_num = ((Number) aftv.elementAt(faceIDColumn)).intValue();
String tilename = (String) aftv.elementAt(tileNameColumn);
char chs[] = tilename.toCharArray();
boolean goodTile = false;
for (int i = 0; i < chs.length; i++) {
if ((chs[i] != '\\') && (chs[i] != ' ')) {
goodTile = true;
chs[i] = Character.toLowerCase(chs[i]);
}
if (chs[i] == '\\') {
chs[i] = File.separatorChar;
}
}
containedTiles[tileid++] = (goodTile) ? new String(chs) : null;
}
aft.close();
return containedTiles;
}
}