/*
* Copyright 2013, 2014 Deutsche Nationalbibliothek
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.culturegraph.mf.metamorph.maps;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UncheckedIOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.regex.Pattern;
import org.culturegraph.mf.metamorph.api.MorphExecutionException;
import org.culturegraph.mf.metamorph.api.helpers.AbstractReadOnlyMap;
/**
* Provides a {@link Map} based on a file. The file is supposed to be UTF-8
* encoded. The separator is by default \t. <strong>Important:</strong> Lines
* that are not split in two parts by the separator are ignored!
*
* @author "Markus Michael Geipel"
*
*/
public final class FileMap extends AbstractReadOnlyMap<String, String> {
private final Map<String, String> map = new HashMap<String, String>();
private Pattern split = Pattern.compile("\t", Pattern.LITERAL);
public void setFiles(final String files) {
final String[] parts = files.split("\\s*,\\s*");
for (final String part : parts) {
setFile(part);
}
}
public void setFile(final String file) {
try (
final InputStream stream = openStream(file);
final BufferedReader reader = new BufferedReader(
new InputStreamReader(stream, StandardCharsets.UTF_8))
) {
String line;
while ((line = reader.readLine()) != null) {
if (line.isEmpty()) {
continue;
}
final String[] parts = split.split(line);
if (parts.length == 2) {
map.put(parts[0], parts[1]);
}
}
} catch (final IOException | UncheckedIOException e) {
throw new MorphExecutionException("filemap: cannot read map file", e);
}
}
private InputStream openStream(String file) {
return openAsFile(file)
.orElseGet(() -> openAsResource(file)
.orElseGet(() -> openAsUrl(file)
.orElseThrow(() -> new MorphExecutionException(
"File not found: " + file))));
}
private Optional<InputStream> openAsFile(String file) {
try {
return Optional.of(new FileInputStream(file));
} catch (FileNotFoundException e) {
return Optional.empty();
}
}
private Optional<InputStream> openAsResource(String file) {
return Optional.ofNullable(Thread.currentThread()
.getContextClassLoader().getResourceAsStream(file));
}
private Optional<InputStream> openAsUrl(String file) {
final URL url;
try {
url = new URL(file);
} catch (MalformedURLException e) {
return Optional.empty();
}
try {
return Optional.of(url.openStream());
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
public void setSeparator(final String delimiter) {
split = Pattern.compile(delimiter, Pattern.LITERAL);
}
@Override
public String get(final Object key) {
return map.get(key);
}
}