JCash/src/me/teridax/jcash/decode/StringDecoder.java

173 lines
6.4 KiB
Java

package me.teridax.jcash.decode;
import org.junit.Test;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.Locale;
import java.util.Objects;
import java.util.regex.Pattern;
import static junit.framework.TestCase.assertEquals;
/**
* Utility class for converting various single line strings into a specific data type according
* to a format mostly dictated by a locale.
*/
public class StringDecoder {
/**
* Locale to use when converting strings
*/
private static final Locale LOCALE = Locale.GERMANY;
/**
* NumberFormat to use when converting strings
*/
public static final NumberFormat LOCAL_NUMBER_FORMAT = NumberFormat.getInstance(LOCALE);
/**
* Attempts to convert the given string into a double value representing a percentage.
* The percentage is stored in the range [0,1] and can linearly be mapped to [0, 100] by multiplying with 100.
* @param number the string to convert
* @return the double value
* @throws IllegalArgumentException when the format is invalid
* @throws NullPointerException when the argument is null
*/
public static double decodePercent(String number) throws IllegalArgumentException, NullPointerException {
Objects.requireNonNull(number);
// trim the number and cut out optional percent symbols
var trimmed = number.trim().replace("%", "");
try {
return LOCAL_NUMBER_FORMAT.parse(trimmed).doubleValue();
} catch (ParseException ex) {
throw new IllegalArgumentException("Not a valid number: " + number, ex);
}
}
/**
* Attempts to convert the given string into a currency value.
* @param currency the string to convert
* @return the double value
* @throws IllegalArgumentException when the format is invalid
* @throws NullPointerException when the argument is null
*/
public static double decodeCurrency(String currency) throws IllegalArgumentException, NullPointerException {
Objects.requireNonNull(currency);
try {
return LOCAL_NUMBER_FORMAT.parse(currency.trim()).doubleValue();
} catch (ParseException ex) {
throw new IllegalArgumentException("Not a valid currency in german locale: " + currency, ex);
}
}
/**
* Attempts to convert the given string into universally unique number.
* This function does not check for duplicates. The number must be a positive integer.
* @param number the string to convert
* @return the integer serial number
* @throws IllegalArgumentException when the format is invalid
* @throws NullPointerException when the argument is null
*/
public static int decodeUniqueIdentificationNumber(String number) throws IllegalArgumentException, NullPointerException {
Objects.requireNonNull(number);
// check if the string is a valid unsigned number
try {
LOCAL_NUMBER_FORMAT.setParseIntegerOnly(true);
var serialNumber = LOCAL_NUMBER_FORMAT.parse(number.trim());
LOCAL_NUMBER_FORMAT.setParseIntegerOnly(false);
if (serialNumber.intValue() < 0)
throw new IllegalArgumentException("Not a valid unique identification number: " + number);
return serialNumber.intValue();
} catch (ParseException ex) {
throw new IllegalArgumentException("Not a valid serial number: " + number, ex);
}
}
/**
* Attempts to convert the given string into a name.
* This method performs validation and trimming.
* @param name the string to convert
* @return the qualified name
* @throws IllegalArgumentException when the format is invalid
* @throws NullPointerException when the argument is null
*/
public static String decodeName(String name) throws IllegalArgumentException, NullPointerException {
Objects.requireNonNull(name);
var trimmed = name.trim();
var pattern = Pattern.compile("[\\w-\\s]+", Pattern.CASE_INSENSITIVE);
var matcher = pattern.matcher(trimmed);
if (matcher.find()) {
return matcher.group();
} else {
throw new IllegalArgumentException("not a void name");
}
}
/**
* Attempts to convert the given string into a street and an optional house address.
* @param street the string to convert
* @return the address name
* @throws IllegalArgumentException when the format is invalid
* @throws NullPointerException when the argument is null
*/
public static String decodeStreet(String street) throws IllegalArgumentException, NullPointerException {
Objects.requireNonNull(street);
var pattern = Pattern.compile("\\S+(\\s+\\d+(/\\d+)?)?", Pattern.CASE_INSENSITIVE);
var matcher = pattern.matcher(street);
if (matcher.find()) {
return matcher.group();
} else {
throw new IllegalArgumentException("not a void address");
}
}
@Test
public void testDecodeSuccessfulFunctions() {
decodeUniqueIdentificationNumber("95786978625347895");
decodeUniqueIdentificationNumber(" 927856347 ");
decodeUniqueIdentificationNumber("0");
decodeName("Adolf");
decodeName("Günther");
decodeName("Saßkia");
decodeStreet("Bahnhofstraße 40/1");
decodeStreet("Gülleweg 9");
decodeStreet("Echsengaße 67 / 4");
assertEquals(decodePercent("1,4%"), 1.4d);
assertEquals(decodePercent("99"), 99.0d);
assertEquals(decodePercent("1,003 %"), 1.003d);
assertEquals(decodeCurrency("1,3€"), 1.3d);
assertEquals(decodeCurrency("145,34"), 145,34d);
assertEquals(decodeCurrency("0,45 €"), 0.45d);
}
@Test(expected = IllegalArgumentException.class)
public void testDecodeInvalidFunctions() {
decodeUniqueIdentificationNumber("q0948tvb6q047t 740 t74z0tz 784");
decodeUniqueIdentificationNumber("-39867.8475");
decodeUniqueIdentificationNumber("-398678475");
decodeUniqueIdentificationNumber(" ß9qu908t76q34798t6q734vb9843");
decodeName("John Doe");
decodeName("3490qt67v 0b34");
decodeName("Alexander9");
decodeName("-ga76re78g6$§");
decodeStreet("Bahnhofstraße -40/1");
decodeStreet("Gülleweg 9//567");
decodeStreet("23Echsengaße 67 / 4 Hofwetg 9");
}
}