/*
 * 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.morph.maps;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;

import org.culturegraph.mf.morph.api.MorphException;
import org.culturegraph.mf.morph.api.helpers.AbstractReadOnlyMap;
import org.culturegraph.mf.util.ResourceUtil;

/**
 * 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 (InputStream stream = ResourceUtil.getStream(file);
				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 FileNotFoundException e) {
			throw new MorphException("resource '" + file + "' not found", e);
		} catch (final IOException e) {
			throw new MorphException(e);
		}
	}

	public void setSeparator(final String delimiter) {
		split = Pattern.compile(delimiter, Pattern.LITERAL);
	}

	@Override
	public String get(final Object key) {
		return map.get(key);
	}

}

/*
 * 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.morph.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.morph.api.MorphException;
import org.culturegraph.mf.morph.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 MorphException(e);
		}
	}

	private InputStream openStream(String file) {
		return openAsFile(file)
				.orElseGet(() -> openAsResource(file)
						.orElseGet(() -> openAsUrl(file)
								.orElseThrow(() -> new MorphException(
										"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);
	}

}

Rewrite open file logic in FileMap