Skip to content

Commit

Permalink
refactor!: Split file reader/writer registries and resource factory
Browse files Browse the repository at this point in the history
  • Loading branch information
jruaux committed Nov 25, 2024
1 parent 15e7613 commit 26f264f
Show file tree
Hide file tree
Showing 10 changed files with 222 additions and 212 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,58 +1,31 @@
package com.redis.riot.file;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.GZIPInputStream;

import org.springframework.core.io.Resource;
import org.springframework.util.MimeType;

public class FileReaderRegistry extends AbstractRegistry {
public class FileReaderRegistry {

private final Map<MimeType, ReaderFactory> factories = new HashMap<>();

public void register(MimeType type, ReaderFactory factory) {
factories.put(type, factory);
}

public FileReaderResult find(String location, ReadOptions options) {
Resource resource = resource(location, options);
MimeType type = type(resource, options);
FileReaderResult reader = new FileReaderResult();
reader.setResource(resource);
reader.setType(type);
ReaderFactory factory = factories.get(type);
if (factory != null) {
reader.setReader(factory.create(resource, options));
}
return reader;
}

@Override
protected Resource resource(String location, FileOptions options) {
Resource resource = super.resource(location, options);
if (options.isGzip() || FileUtils.isGzip(resource.getFilename())) {
GZIPInputStream gzipInputStream;
try {
gzipInputStream = new GZIPInputStream(resource.getInputStream());
} catch (IOException e) {
throw new RuntimeIOException("Could not create GZip input stream", e);
}
return new NamedInputStreamResource(gzipInputStream, resource.getFilename(), resource.getDescription());
}
return resource;
public ReaderFactory getReaderFactory(MimeType type) {
return factories.get(type);
}

public static FileReaderRegistry defaultReaderRegistry() {
FileReaderRegistry registry = new FileReaderRegistry();
registry.register(FileUtils.JSON, new JsonReaderFactory());
registry.register(FileUtils.JSON_LINES, new JsonLinesReaderFactory());
registry.register(FileUtils.XML, new XmlReaderFactory());
registry.register(FileUtils.CSV, new DelimitedReaderFactory(FileOptions.DELIMITER_COMMA));
registry.register(FileUtils.PSV, new DelimitedReaderFactory(FileOptions.DELIMITER_PIPE));
registry.register(FileUtils.TSV, new DelimitedReaderFactory(FileOptions.DELIMITER_TAB));
registry.register(FileUtils.TEXT, new FixedWidthReaderFactory());
registry.register(ResourceFactory.JSON, new JsonReaderFactory());
registry.register(ResourceFactory.JSON_LINES, new JsonLinesReaderFactory());
registry.register(ResourceFactory.XML, new XmlReaderFactory());
registry.register(ResourceFactory.CSV, new DelimitedReaderFactory(FileOptions.DELIMITER_COMMA));
registry.register(ResourceFactory.PSV, new DelimitedReaderFactory(FileOptions.DELIMITER_PIPE));
registry.register(ResourceFactory.TSV, new DelimitedReaderFactory(FileOptions.DELIMITER_TAB));
registry.register(ResourceFactory.TEXT, new FixedWidthReaderFactory());
return registry;
}

Expand Down
32 changes: 0 additions & 32 deletions core/riot-file/src/main/java/com/redis/riot/file/FileUtils.java

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,71 +1,31 @@
package com.redis.riot.file;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.GZIPOutputStream;

import org.springframework.core.io.Resource;
import org.springframework.core.io.WritableResource;
import org.springframework.util.Assert;
import org.springframework.util.MimeType;

public class FileWriterRegistry extends AbstractRegistry {
public class FileWriterRegistry {

private final Map<MimeType, WriterFactory> factories = new HashMap<>();
private ResourceMap resourceMap = new RiotResourceMap();

public ResourceMap getResourceMap() {
return resourceMap;
}

public void setResourceMap(ResourceMap resourceMap) {
this.resourceMap = resourceMap;
}

public void register(MimeType type, WriterFactory factory) {
factories.put(type, factory);
}

public FileWriterResult find(String location, WriteOptions options) {
WritableResource resource = resource(location, options);
MimeType type = type(resource, options);
FileWriterResult result = new FileWriterResult();
result.setResource(resource);
result.setType(type);
WriterFactory factory = factories.get(type);
if (factory != null) {
result.setWriter(factory.create(resource, options));
}
return result;
}

@Override
protected WritableResource resource(String location, FileOptions options) {
Resource resource = super.resource(location, options);
Assert.isInstanceOf(WritableResource.class, resource, "Resource is not writable");
WritableResource writableResource = (WritableResource) resource;
if (options.isGzip() || FileUtils.isGzip(resource.getFilename())) {
GZIPOutputStream gzipOutputStream;
try {
gzipOutputStream = new GZIPOutputStream(writableResource.getOutputStream());
} catch (IOException e) {
throw new RuntimeIOException("Could not create GZip output stream", e);
}
return new OutputStreamResource(gzipOutputStream, resource.getFilename(), resource.getDescription());
}
return writableResource;
public WriterFactory getWriterFactory(MimeType type) {
return factories.get(type);
}

public static FileWriterRegistry defaultWriterRegistry() {
FileWriterRegistry registry = new FileWriterRegistry();
registry.register(FileUtils.JSON, new JsonWriterFactory());
registry.register(FileUtils.JSON_LINES, new JsonLinesWriterFactory());
registry.register(FileUtils.XML, new XmlWriterFactory());
registry.register(FileUtils.CSV, new DelimitedWriterFactory(FileOptions.DELIMITER_COMMA));
registry.register(FileUtils.PSV, new DelimitedWriterFactory(FileOptions.DELIMITER_PIPE));
registry.register(FileUtils.TSV, new DelimitedWriterFactory(FileOptions.DELIMITER_TAB));
registry.register(FileUtils.TEXT, new FormattedWriterFactory());
registry.register(ResourceFactory.JSON, new JsonWriterFactory());
registry.register(ResourceFactory.JSON_LINES, new JsonLinesWriterFactory());
registry.register(ResourceFactory.XML, new XmlWriterFactory());
registry.register(ResourceFactory.CSV, new DelimitedWriterFactory(FileOptions.DELIMITER_COMMA));
registry.register(ResourceFactory.PSV, new DelimitedWriterFactory(FileOptions.DELIMITER_PIPE));
registry.register(ResourceFactory.TSV, new DelimitedWriterFactory(FileOptions.DELIMITER_TAB));
registry.register(ResourceFactory.TEXT, new FormattedWriterFactory());
return registry;
}

Expand Down
121 changes: 121 additions & 0 deletions core/riot-file/src/main/java/com/redis/riot/file/ResourceFactory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package com.redis.riot.file;

import java.io.IOException;
import java.net.FileNameMap;
import java.util.HashSet;
import java.util.Set;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

import org.springframework.core.io.ProtocolResolver;
import org.springframework.core.io.Resource;
import org.springframework.core.io.WritableResource;
import org.springframework.util.Assert;
import org.springframework.util.MimeType;
import org.springframework.util.MimeTypeUtils;

public class ResourceFactory {

public static final String GZ_SUFFIX = ".gz";

public static final MimeType CSV = new MimeType("text", "csv");
public static final MimeType PSV = new MimeType("text", "psv");
public static final MimeType TSV = new MimeType("text", "tsv");
public static final MimeType TEXT = new MimeType("text", "plain");
public static final MimeType JSON = MimeTypeUtils.APPLICATION_JSON;
public static final MimeType JSON_LINES = new MimeType("application", "jsonlines");
public static final MimeType XML = MimeTypeUtils.APPLICATION_XML;

private ResourceMap resourceMap = defaultResourceMap();
private Set<ProtocolResolver> protocolResolvers = new HashSet<>();

public MimeType type(Resource resource) {
return MimeType.valueOf(resourceMap.getContentTypeFor(resource));
}

public MimeType type(Resource resource, FileOptions options) {
if (options.getContentType() == null) {
return MimeType.valueOf(resourceMap.getContentTypeFor(resource));
}
return options.getContentType();
}

private static class JsonLinesFileNameMap implements FileNameMap {

public static final String JSONL_SUFFIX = ".jsonl";

@Override
public String getContentTypeFor(String fileName) {
if (fileName == null) {
return null;
}
if (fileName.endsWith(JSONL_SUFFIX)) {
return JSON_LINES.toString();
}
return null;
}

}

public static ResourceMap defaultResourceMap() {
RiotResourceMap resourceMap = new RiotResourceMap();
resourceMap.addFileNameMap(new JsonLinesFileNameMap());
return resourceMap;
}

public void addProtocolResolver(ProtocolResolver protocolResolver) {
protocolResolvers.add(protocolResolver);
}

public Resource resource(String location, FileOptions options) throws IOException {
Resource resource = createResource(location, options);
if (isGzip(resource, options)) {
GZIPInputStream gzipInputStream = new GZIPInputStream(resource.getInputStream());
return new NamedInputStreamResource(gzipInputStream, resource.getFilename(), resource.getDescription());
}
return resource;
}

private boolean isGzip(Resource resource, FileOptions options) {
return options.isGzip() || isGzip(resource.getFilename());
}

public WritableResource writableResource(String location, FileOptions options) throws IOException {
Resource resource = createResource(location, options);
Assert.isInstanceOf(WritableResource.class, resource);
if (options.isGzip() || isGzip(resource.getFilename())) {
GZIPOutputStream gzipOutputStream = new GZIPOutputStream(((WritableResource) resource).getOutputStream());
return new OutputStreamResource(gzipOutputStream, resource.getFilename(), resource.getDescription());
}
return (WritableResource) resource;
}

private Resource createResource(String location, FileOptions options) {
RiotResourceLoader resourceLoader = new RiotResourceLoader();
protocolResolvers.forEach(resourceLoader::addProtocolResolver);
resourceLoader.getS3ProtocolResolver().setClientSupplier(options.getS3Options()::client);
resourceLoader.getGoogleStorageProtocolResolver()
.setStorageSupplier(options.getGoogleStorageOptions()::storage);
return resourceLoader.getResource(location);
}

public static boolean isGzip(String filename) {
return filename.endsWith(GZ_SUFFIX);
}

public static String stripGzipSuffix(String filename) {
if (isGzip(filename)) {
return filename.substring(0, filename.length() - GZ_SUFFIX.length());
}
return filename;
}

public ResourceMap getResourceMap() {
return resourceMap;
}

public void setResourceMap(ResourceMap resourceMap) {
this.resourceMap = resourceMap;
}

}
Loading

0 comments on commit 26f264f

Please sign in to comment.