/*
 * Copyright (c) 2007, intarsys consulting GmbH
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * - Redistributions of source code must retain the above copyright notice,
 *   this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 *
 * - Neither the name of intarsys nor the names of its contributors may be used
 *   to endorse or promote products derived from this software without specific
 *   prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
package de.intarsys.tools.string;

import java.io.File;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.StringTokenizer;

import de.intarsys.tools.file.FileTools;

/**
 * Simple string conversion utilities;
 */
public class Converter {

	public static final String ELEMENT_SEPARATOR = ";"; //$NON-NLS-1$

	public static final String KEY_VALUE_SEPARATOR = "="; //$NON-NLS-1$

	public static boolean asBoolean(String booleanString)
			throws ConverterException {
		booleanString = booleanString.toLowerCase().trim();
		if (booleanString.equals("false") || booleanString.equals("f")
				|| booleanString.equals("no") || booleanString.equals("n")
				|| booleanString.equals("0") || booleanString.equals("falsch")
				|| booleanString.equals("nein")) {
			return false;
		}
		if (booleanString.equals("true") || booleanString.equals("t")
				|| booleanString.equals("yes") || booleanString.equals("y")
				|| booleanString.equals("1") || booleanString.equals("wahr")
				|| booleanString.equals("w") || booleanString.equals("ja")
				|| booleanString.equals("j")) {
			return true;
		}
		throw new ConverterException("Can't parse boolean string: "
				+ booleanString + " to a legal value");
	}

	public static boolean asBoolean(String booleanString, boolean defaultValue) {
		if (StringTools.isEmpty(booleanString)) {
			return defaultValue;
		}
		try {
			return asBoolean(booleanString);
		} catch (ConverterException e) {
			return defaultValue;
		}
	}

	public static boolean asBooleanChecked(String booleanString,
			boolean defaultValue) throws ConverterException {
		if (StringTools.isEmpty(booleanString)) {
			return defaultValue;
		}
		return asBoolean(booleanString);
	}

	public static Class asClass(String str) throws ConverterException {
		str = str.trim();
		if (str.equals("")) {
			return null;
		}
		try {
			return Class.forName(str);
		} catch (ClassNotFoundException cnfe) {
			throw new ConverterException(str + " is not a possible Classname!");
		}
	}

	public static double asDouble(String str) throws ConverterException {
		try {
			str = str.trim();
			return Double.parseDouble(str);
		} catch (NumberFormatException e) {
			throw new ConverterException("Can't parse number string: " + str
					+ " to a legal value");
		}
	}

	public static double asDouble(String str, double defaultValue) {
		if (StringTools.isEmpty(str)) {
			return defaultValue;
		}
		try {
			return asDouble(str);
		} catch (ConverterException e) {
			return defaultValue;
		}
	}

	public static double asDoubleChecked(String str, double defaultValue)
			throws ConverterException {
		if (StringTools.isEmpty(str)) {
			return defaultValue;
		}
		return asDouble(str);
	}

	public static File asFile(String pValue) throws ConverterException {
		String str = pValue.trim();
		str = FileTools.trimPath(str);
		if (str.equals("")) {
			throw new ConverterException("Parameter " + pValue
					+ " is not a valid Filename");
		}
		try {
			return new File(str);
		} catch (NullPointerException e) {
			throw new ConverterException("Can't parse file string: " + str
					+ " to a file");
		}
	}

	public static float asFloat(String str) throws ConverterException {
		try {
			str = str.trim();
			return Float.parseFloat(str);
		} catch (NumberFormatException e) {
			throw new ConverterException("Can't parse number string: " + str
					+ " to a legal value");
		}
	}

	public static float asFloat(String str, float defaultValue) {
		if (StringTools.isEmpty(str)) {
			return defaultValue;
		}
		try {
			return asFloat(str);
		} catch (ConverterException e) {
			return defaultValue;
		}
	}

	public static float[] asFloatArray(String value) {
		if (value == null) {
			return null;
		}
		StringTokenizer tk = new StringTokenizer(value, ELEMENT_SEPARATOR,
				false);
		float[] result = new float[tk.countTokens()];
		int i = 0;
		try {
			while (tk.hasMoreTokens()) {
				String token = tk.nextToken();
				result[i] = Float.parseFloat(token.trim());
				i++;
			}
		} catch (NumberFormatException e) {
			return null;
		}
		return result;
	}

	public static float asFloatChecked(String str, float defaultValue)
			throws ConverterException {
		if (StringTools.isEmpty(str)) {
			return defaultValue;
		}
		return asFloat(str);
	}

	public static int[] asIntArray(String value) {
		if (value == null) {
			return null;
		}
		StringTokenizer tk = new StringTokenizer(value, ELEMENT_SEPARATOR,
				false);
		int[] result = new int[tk.countTokens()];
		int i = 0;
		try {
			while (tk.hasMoreTokens()) {
				String token = tk.nextToken();
				result[i] = Integer.parseInt(token.trim());
				i++;
			}
		} catch (NumberFormatException e) {
			return null;
		}
		return result;
	}

	public static int asInteger(String str) throws ConverterException {
		try {
			str = str.trim();
			return Integer.parseInt(str);
		} catch (NumberFormatException e) {
			throw new ConverterException("Can't parse integer string: " + str
					+ " to a legal value");
		}
	}

	public static int asInteger(String str, int defaultValue) {
		if (StringTools.isEmpty(str)) {
			return defaultValue;
		}
		try {
			return asInteger(str);
		} catch (ConverterException e) {
			return defaultValue;
		}
	}

	public static int asIntegerChecked(String str, int defaultValue)
			throws ConverterException {
		if (StringTools.isEmpty(str)) {
			return defaultValue;
		}
		return asInteger(str);
	}

	public static long asLong(String str) throws ConverterException {
		try {
			str = str.trim();
			return Long.parseLong(str);
		} catch (NumberFormatException e) {
			throw new ConverterException("Can't parse integer string: " + str
					+ " to a legal value");
		}
	}

	public static long asLong(String str, long defaultValue) {
		if (StringTools.isEmpty(str)) {
			return defaultValue;
		}
		try {
			return asLong(str);
		} catch (ConverterException e) {
			return defaultValue;
		}
	}

	public static long asLongChecked(String str, long defaultValue)
			throws ConverterException {
		if (StringTools.isEmpty(str)) {
			return defaultValue;
		}
		return asLong(str);
	}

	public static Map asMap(String string) {
		String key;
		String value;
		String token;
		Map map = new HashMap(5);
		if (string == null) {
			return map;
		}
		StringTokenizer tk = new StringTokenizer(string, ELEMENT_SEPARATOR,
				false);
		while (tk.hasMoreTokens()) {
			token = tk.nextToken();
			int i = token.indexOf(KEY_VALUE_SEPARATOR);
			if (i == -1) {
				key = token;
				value = "";
			} else {
				key = token.substring(0, i);
				if (i >= token.length()) {
					value = "";
				}
				value = token.substring(i + 1);
			}
			map.put(key, value);
		}
		return map;
	}

	public static Map asMapBoolean(String string) {
		Map stringMap = asMap(string);
		Map boolMap = new HashMap(stringMap.size() * 2);
		for (Iterator i = stringMap.entrySet().iterator(); i.hasNext();) {
			Map.Entry entry = (Map.Entry) i.next();
			Boolean value = Boolean.valueOf((String) entry.getValue());
			boolMap.put(entry.getKey(), value);
		}
		return boolMap;
	}

	public static String asString(String str, String defaultValue) {
		if (StringTools.isEmpty(str)) {
			return defaultValue;
		} else {
			return str.trim();
		}
	}

	public static String[] asStringArray(String value) {
		if (value == null) {
			return null;
		}
		return value.split(ELEMENT_SEPARATOR);
	}

	public static Boolean asThreeState(String booleanString)
			throws ConverterException {
		booleanString = booleanString.toLowerCase().trim();
		if (booleanString.equals("false") || booleanString.equals("f")
				|| booleanString.equals("no") || booleanString.equals("n")
				|| booleanString.equals("0") || booleanString.equals("falsch")
				|| booleanString.equals("nein")) {
			return Boolean.FALSE;
		}
		if (booleanString.equals("true") || booleanString.equals("t")
				|| booleanString.equals("yes") || booleanString.equals("y")
				|| booleanString.equals("1") || booleanString.equals("wahr")
				|| booleanString.equals("w") || booleanString.equals("ja")
				|| booleanString.equals("j")) {
			return Boolean.TRUE;
		}
		if (booleanString.equals("undeterminate")
				|| booleanString.equals("undefined")
				|| booleanString.equals("?") || booleanString.equals("u")) {
			return null;
		}
		throw new ConverterException("Can't parse boolean string: "
				+ booleanString + " to a legal value");
	}

	public static Boolean asThreeState(String booleanString,
			Boolean defaultValue) {
		if (StringTools.isEmpty(booleanString)) {
			return defaultValue;
		}
		try {
			return asBoolean(booleanString);
		} catch (ConverterException e) {
			return defaultValue;
		}
	}

	private Converter() {
		super();
	}

}
