package com.revolsys.gdal.record;
import java.io.File;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Pattern;
import org.gdal.ogr.ogr;
import com.revolsys.collection.map.Maps;
import com.revolsys.gdal.Gdal;
import com.revolsys.io.FileUtil;
import com.revolsys.record.io.FileRecordStoreFactory;
import com.revolsys.record.schema.RecordStore;
public class OgrRecordStoreFactory implements FileRecordStoreFactory {
private static final Map<String, AtomicInteger> COUNTS = new HashMap<>();
private static final Map<String, OgrRecordStore> DATA_STORES = new HashMap<>();
private static OgrRecordStore newRecordStore(final String driverName, File file) {
if (file == null) {
return null;
} else {
synchronized (COUNTS) {
final String fileName = FileUtil.getCanonicalPath(file);
file = new File(fileName);
final AtomicInteger count = Maps.get(COUNTS, fileName, new AtomicInteger());
count.incrementAndGet();
OgrRecordStore recordStore = DATA_STORES.get(fileName);
if (recordStore == null) {
recordStore = new OgrRecordStore(driverName, file);
// recordStore.setCreateMissingRecordStore(false);
DATA_STORES.put(fileName, recordStore);
}
return recordStore;
}
}
}
static boolean release(final File file) {
if (file == null) {
return false;
} else {
synchronized (COUNTS) {
final String fileName = FileUtil.getCanonicalPath(file);
final AtomicInteger countHolder = Maps.get(COUNTS, fileName, new AtomicInteger());
final int count = countHolder.decrementAndGet();
if (count <= 0) {
COUNTS.remove(fileName);
final OgrRecordStore recordStore = DATA_STORES.remove(fileName);
if (recordStore == null) {
return false;
} else {
recordStore.closeDo();
}
COUNTS.remove(fileName);
return true;
} else {
return true;
}
}
}
}
private boolean available;
private final String driverName;
private final List<String> fileNameExtensions;
private final String name;
private final List<Pattern> urlPatterns = new ArrayList<>();
public OgrRecordStoreFactory(final String name, final String driverName, final String mediaType,
final List<String> fileNameExtensions) {
this.name = name;
this.driverName = driverName;
this.fileNameExtensions = fileNameExtensions;
try {
if (Gdal.isAvailable()) {
this.available = ogr.GetDriverByName(driverName) != null;
if (this.available) {
// final RecordStoreRecordAndGeometryWriterFactory writerFactory = new
// RecordStoreRecordAndGeometryWriterFactory(
// name, mediaType, true, true, fileNameExtensions);
// IoFactoryRegistry.getInstance().addFactory(writerFactory);
for (final String extension : fileNameExtensions) {
this.urlPatterns.add(Pattern.compile("file:/(//)?.*." + extension + "/?"));
this.urlPatterns.add(Pattern.compile("folderconnection:/(//)?.*." + extension + "/?"));
}
}
} else {
this.available = false;
}
} catch (final UnsatisfiedLinkError e) {
this.available = false;
}
}
public OgrRecordStoreFactory(final String name, final String driverName, final String mediaType,
final String... fileNameExtensions) {
this(name, driverName, mediaType, Arrays.asList(fileNameExtensions));
}
@Override
public boolean canOpenPath(final Path path) {
if (FileRecordStoreFactory.super.canOpenPath(path)) {
try {
// FGDB must be a file not inside a zip file
path.toFile();
} catch (final UnsupportedOperationException e) {
return false;
}
return true;
}
return false;
}
@Override
public String getName() {
return this.name;
}
@Override
public List<String> getRecordStoreFileExtensions() {
return this.fileNameExtensions;
}
@Override
public Class<? extends RecordStore> getRecordStoreInterfaceClass(
final Map<String, ? extends Object> connectionProperties) {
return RecordStore.class;
}
@Override
public List<Pattern> getUrlPatterns() {
return this.urlPatterns;
}
@Override
public boolean isAvailable() {
return this.available;
}
@Override
public OgrRecordStore newRecordStore(final Map<String, ? extends Object> connectionProperties) {
final Map<String, Object> properties = new LinkedHashMap<>(connectionProperties);
final String url = (String)properties.remove("url");
final File file = FileUtil.getUrlFile(url);
final OgrRecordStore recordStore = newRecordStore(this.driverName, file);
RecordStore.setConnectionProperties(recordStore, properties);
return recordStore;
}
}