package com.revolsys.record.io.format.directory; 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.geometry.model.GeometryFactory; import com.revolsys.io.AbstractRecordWriter; import com.revolsys.io.IoConstants; import com.revolsys.io.PathUtil; import com.revolsys.io.Writer; import com.revolsys.logging.Logs; import com.revolsys.record.Record; import com.revolsys.record.io.RecordWriter; 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 DirectoryRecordWriter extends AbstractRecordWriter { private File directory; private String fileExtension = ""; private String nameSuffix = ""; private Map<String, RecordDefinition> recordDefinitionMap = new HashMap<>(); private LabelCountMap labelCountMap; private boolean useNamespaceAsSubDirectory; private Map<String, Writer<Record>> writers = new HashMap<>(); public DirectoryRecordWriter() { } public DirectoryRecordWriter(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) { Logs.error(this, "Error closing " + writer, e); } } 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) { Logs.error(this, "Error flusing " + writer, e); } } } 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; } public String getFileExtension() { return this.fileExtension; } 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 record) { final RecordDefinition recordDefinition = record.getRecordDefinition(); final String path = recordDefinition.getPath(); Writer<Record> writer = this.writers.get(path); if (writer == null) { final File directory = getDirectory(recordDefinition); directory.mkdirs(); final String fileName = getFileName(recordDefinition); final File file = new File(directory, fileName + this.nameSuffix + "." + this.fileExtension); final FileSystemResource resource = new FileSystemResource(file); writer = RecordWriter.newRecordWriter(recordDefinition, resource); if (writer == null) { throw new IllegalArgumentException("Unable to create writer for " + resource); } else { final Map<String, Object> properties = getProperties(); writer.setProperties(properties); final Geometry geometry = record.getGeometry(); if (geometry != null) { final GeometryFactory geometryFactory = geometry.getGeometryFactory(); setProperty(IoConstants.GEOMETRY_FACTORY, geometryFactory); } this.writers.put(path, writer); RecordDefinition writerRecordDefinition = recordDefinition; if (writer instanceof AbstractRecordWriter) { final AbstractRecordWriter recordWriter = (AbstractRecordWriter)writer; writerRecordDefinition = recordWriter.getRecordDefinition(); if (writerRecordDefinition == null) { writerRecordDefinition = recordDefinition; } } this.recordDefinitionMap.put(path, writerRecordDefinition); } } return writer; } public boolean isUseNamespaceAsSubDirectory() { return this.useNamespaceAsSubDirectory; } public void setDirectory(final File baseDirectory) { this.directory = baseDirectory; baseDirectory.mkdirs(); this.labelCountMap = new LabelCountMap("Write " + baseDirectory.getAbsolutePath()); this.labelCountMap.connect(); } public void setFileExtension(final String fileExtension) { this.fileExtension = fileExtension; } 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; } @Override public String toString() { return this.directory.getAbsolutePath(); } @Override public void write(final Record record) { if (record != null) { final Writer<Record> writer = getWriter(record); writer.write(record); this.labelCountMap.addCount(record); } } }