package org.opentripplanner.analyst;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
public class DiskBackedPointSetCache extends PointSetCache {
private static final Logger LOG = LoggerFactory.getLogger(DiskBackedPointSetCache.class);
protected File pointSetPath;
protected class PointSetLoader extends CacheLoader<String, PointSet> {
@Override
public PointSet load(String pointSetId) throws Exception {
if (pointSetPath != null && ! (pointSetPath.isDirectory() && pointSetPath.canRead())) {
LOG.error("'{}' is not a readable directory.", pointSetPath);
return null;
}
for (File file : pointSetPath.listFiles()) {
if(file.getName().toLowerCase().startsWith(pointSetId.toLowerCase())) {
LOG.info("Attempting to load pointset from '{}'.", file);
PointSet pointSet = this.loadFromFile(file);
if(pointSet == null) {
LOG.error("Pointset loading function returned null.");
return null;
} else {
return pointSet;
}
}
}
LOG.error("No file was found with the given pointset name.");
return null;
}
public PointSet loadFromFile(File pointSetData) {
String name = pointSetData.getName();
if (name.endsWith(".csv")) {
String baseName = name.substring(0, name.length() - 4);
LOG.info("loading '{}' with ID '{}'", pointSetData, baseName);
try {
PointSet pset = PointSet.fromCsv(pointSetData);
if (pset == null) {
LOG.warn("Failure, skipping this pointset.");
}
return pset;
} catch (IOException ioex) {
LOG.warn("Exception while loading pointset.", ioex);
}
} else if (name.endsWith(".json")) {
String baseName = name.substring(0, name.length() - 5);
LOG.info("loading '{}' with ID '{}'", pointSetData, baseName);
PointSet pset = PointSet.fromGeoJson(pointSetData);
if (pset == null) {
LOG.warn("Failure, skipping this pointset.");
}
return pset;
}
return null;
}
}
public DiskBackedPointSetCache(Integer maxCacheSize, File pointSetPath) {
super();
this.pointSetPath = pointSetPath;
// TODO could convert to a weight-based eviction strategy based on pointset size
this.pointSets = CacheBuilder.newBuilder()
.maximumSize(maxCacheSize)
.build(new PointSetLoader());
}
@Override
public ArrayList<String> getPointSetIds() {
ArrayList<String> ids = new ArrayList<String>();
for(File f : pointSetPath.listFiles()) {
String name = f.getName();
if (name.endsWith(".csv")) {
String baseName = name.substring(0, name.length() - 4);
ids.add(baseName);
}
else if (name.endsWith(".json")) {
String baseName = name.substring(0, name.length() - 5);
ids.add(baseName);
}
}
return ids;
}
}