package com.revolsys.record.io.format.shp;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.PreDestroy;
import com.revolsys.geometry.model.Geometry;
import com.revolsys.io.AbstractRecordWriter;
import com.revolsys.io.IoConstants;
import com.revolsys.io.PathUtil;
import com.revolsys.io.Writer;
import com.revolsys.record.Record;
import com.revolsys.record.io.RecordWriter;
import com.revolsys.record.io.format.xbase.XbaseRecordWriter;
import com.revolsys.record.schema.RecordDefinition;
import com.revolsys.spring.resource.FileSystemResource;
import com.revolsys.util.Property;
import com.revolsys.util.count.LabelCountMap;
public class ShapefileDirectoryWriter extends AbstractRecordWriter {
private File directory;
private String nameSuffix = "";
private Map<String, RecordDefinition> recordDefinitionMap = new HashMap<>();
private LabelCountMap labelCountMap;
private boolean useNamespaceAsSubDirectory;
private boolean useZeroForNull = true;
private Map<String, Writer<Record>> writers = new HashMap<>();
public ShapefileDirectoryWriter() {
}
public ShapefileDirectoryWriter(final File baseDirectory) {
setDirectory(baseDirectory);
}
@Override
@PreDestroy
public void close() {
if (this.writers != null) {
for (final Writer<Record> writer : this.writers.values()) {
try {
writer.close();
} catch (final RuntimeException e) {
e.printStackTrace();
}
}
this.writers = null;
this.recordDefinitionMap = null;
}
if (this.labelCountMap != null) {
this.labelCountMap.disconnect();
this.labelCountMap = null;
}
}
@Override
public void flush() {
for (final Writer<Record> writer : this.writers.values()) {
try {
writer.flush();
} catch (final RuntimeException e) {
e.printStackTrace();
}
}
}
public File getDirectory() {
return this.directory;
}
private File getDirectory(final RecordDefinition recordDefinition) {
if (this.useNamespaceAsSubDirectory) {
final String typePath = recordDefinition.getPath();
final String schemaName = PathUtil.getPath(typePath);
if (Property.hasValue(schemaName)) {
final File childDirectory = new File(this.directory, schemaName);
if (!childDirectory.mkdirs()) {
if (!childDirectory.isDirectory()) {
throw new IllegalArgumentException("Unable to create directory " + childDirectory);
}
}
return childDirectory;
}
}
return this.directory;
}
private String getFileName(final RecordDefinition recordDefinition) {
return recordDefinition.getName();
}
public String getNameSuffix() {
return this.nameSuffix;
}
public RecordDefinition getRecordDefinition(final String path) {
return this.recordDefinitionMap.get(path);
}
public LabelCountMap getStatistics() {
return this.labelCountMap;
}
private Writer<Record> getWriter(final Record object) {
final RecordDefinition recordDefinition = object.getRecordDefinition();
final String path = recordDefinition.getPath();
Writer<Record> writer = this.writers.get(path);
if (writer == null) {
final File directory = getDirectory(recordDefinition);
directory.mkdirs();
final File file = new File(directory,
getFileName(recordDefinition) + this.nameSuffix + ".shp");
writer = RecordWriter.newRecordWriter(recordDefinition, new FileSystemResource(file));
((XbaseRecordWriter)writer).setUseZeroForNull(this.useZeroForNull);
final Geometry geometry = object.getGeometry();
if (geometry != null) {
setProperty(IoConstants.GEOMETRY_FACTORY, geometry.getGeometryFactory());
}
this.writers.put(path, writer);
this.recordDefinitionMap.put(path, ((ShapefileRecordWriter)writer).getRecordDefinition());
}
return writer;
}
public boolean isUseNamespaceAsSubDirectory() {
return this.useNamespaceAsSubDirectory;
}
public boolean isUseZeroForNull() {
return this.useZeroForNull;
}
public void setDirectory(final File baseDirectory) {
this.directory = baseDirectory;
baseDirectory.mkdirs();
this.labelCountMap = new LabelCountMap("Write Shape " + baseDirectory.getAbsolutePath());
this.labelCountMap.connect();
}
public void setLogCounts(final boolean logCounts) {
this.labelCountMap.setLogCounts(false);
}
public void setNameSuffix(final String nameSuffix) {
this.nameSuffix = nameSuffix;
}
public void setStatistics(final LabelCountMap labelCountMap) {
if (this.labelCountMap != labelCountMap) {
this.labelCountMap = labelCountMap;
labelCountMap.connect();
}
}
public void setUseNamespaceAsSubDirectory(final boolean useNamespaceAsSubDirectory) {
this.useNamespaceAsSubDirectory = useNamespaceAsSubDirectory;
}
public void setUseZeroForNull(final boolean useZeroForNull) {
this.useZeroForNull = useZeroForNull;
}
@Override
public String toString() {
return this.directory.getAbsolutePath();
}
@Override
public void write(final Record object) {
final Writer<Record> writer = getWriter(object);
writer.write(object);
this.labelCountMap.addCount(object);
}
}