From: Marco Zanon Date: Sat, 2 Mar 2024 17:27:18 +0000 (+0000) Subject: Renamed 'conversion' package to 'conversions'. X-Git-Tag: 10.0.0~2 X-Git-Url: https://gitweb.marcozanon.com/?a=commitdiff_plain;h=784caa3fe19e6db279114fe5344553006b9dffa3;p=Macaco Renamed 'conversion' package to 'conversions'. --- diff --git a/CHANGELOG b/CHANGELOG index cab32f4..1169b68 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -5,6 +5,7 @@ See LICENSE for details. =================== 10.0.0 (2024-03-02) =================== +* Renamed 'conversion' package to 'conversions'. * Renamed some methods and variables. ------------------ diff --git a/src/main/java/com/marcozanon/macaco/conversion/MConversionException.java b/src/main/java/com/marcozanon/macaco/conversion/MConversionException.java deleted file mode 100644 index f4c825f..0000000 --- a/src/main/java/com/marcozanon/macaco/conversion/MConversionException.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Macaco - * Copyright (c) 2009-2024 Marco Zanon . - * See LICENSE for details. - */ - -package com.marcozanon.macaco.conversion; - -import com.marcozanon.macaco.MException; - -public abstract class MConversionException extends MException { - - /* */ - - public MConversionException() { - super(); - } - - public MConversionException(String message) { - super(message); - } - - public MConversionException(Throwable error) { - super(error); - } - - public MConversionException(String message, Throwable error) { - super(message, error); - } - -} diff --git a/src/main/java/com/marcozanon/macaco/conversion/MDateConverter.java b/src/main/java/com/marcozanon/macaco/conversion/MDateConverter.java deleted file mode 100644 index d0e6b05..0000000 --- a/src/main/java/com/marcozanon/macaco/conversion/MDateConverter.java +++ /dev/null @@ -1,255 +0,0 @@ -/** - * Macaco - * Copyright (c) 2009-2024 Marco Zanon . - * See LICENSE for details. - */ - -package com.marcozanon.macaco.conversion; - -import com.marcozanon.macaco.MObject; -import com.marcozanon.macaco.text.MText; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Calendar; -import java.util.Date; -import java.util.GregorianCalendar; -import java.util.LinkedHashSet; -import java.util.Locale; -import java.util.TimeZone; - -public class MDateConverter extends MObject { - - protected LinkedHashSet dateFormats = new LinkedHashSet(); - protected Locale locale = null; - protected TimeZone timeZone = null; - - /* */ - - public MDateConverter(String defaultDateFormat, Locale locale) { - this(defaultDateFormat, locale, TimeZone.getDefault()); - } - - public MDateConverter(String defaultDateFormat, Locale locale, TimeZone timeZone) { - super(); - // - this.addDateFormat(defaultDateFormat); - this.setLocale(locale); - this.setTimeZone(timeZone); - } - - public MDateConverter(LinkedHashSet dateFormats, Locale locale, TimeZone timeZone) { - super(); - // - this.setDateFormats(dateFormats); - this.setLocale(locale); - this.setTimeZone(timeZone); - } - - @Override - public MDateConverter clone() { - return new MDateConverter(this.getDateFormats(), this.getLocale(), this.getTimeZone()); - } - - /* Date formats. */ - - public void setDateFormats(LinkedHashSet dateFormats) { - if (null == dateFormats) { - throw new IllegalArgumentException("Invalid 'dateFormats': null."); - } - else if (0 == dateFormats.size()) { - throw new IllegalArgumentException("Invalid 'dateFormats': empty."); - } - else { - for (String dateFormat: dateFormats) { - MDateConverter.checkDateFormat(dateFormat); - } - } - // - synchronized (this.dateFormats) { - this.dateFormats = dateFormats; - } - } - - public void addDateFormat(String dateFormat) { - MDateConverter.checkDateFormat(dateFormat); - // - synchronized (this.dateFormats) { - this.dateFormats.add(dateFormat); - } - } - - public LinkedHashSet getDateFormats() { - return this.dateFormats; - } - - public String getDefaultDateFormat() { - return this.getDateFormats().iterator().next(); - } - - public LinkedHashSet getSecondaryDateFormats() { - LinkedHashSet dateFormats = (LinkedHashSet)this.getDateFormats().clone(); - // - dateFormats.remove(this.getDefaultDateFormat()); - // - return dateFormats; - } - - /* Locale. */ - - protected void setLocale(Locale locale) { - if (null == locale) { - throw new IllegalArgumentException("Invalid 'locale': null."); - } - // - this.locale = locale; - } - - public Locale getLocale() { - return this.locale; - } - - /* Time zone. */ - - protected void setTimeZone(TimeZone timeZone) { - if (null == timeZone) { - throw new IllegalArgumentException("Invalid 'timeZone': null."); - } - // - this.timeZone = timeZone; - } - - public TimeZone getTimeZone() { - return this.timeZone; - } - - /* Conversions. */ - - protected static void checkDateFormat(String dateFormat) { - if (MText.isBlank(dateFormat)) { - throw new IllegalArgumentException("Invalid 'dateFormat': null or empty."); - } - // - try { - SimpleDateFormat testDateFormat = new SimpleDateFormat(dateFormat); - } - catch (IllegalArgumentException exception) { - throw new IllegalArgumentException(String.format("Invalid 'dateFormat': %s.", dateFormat)); // no need to propagate exception - } - } - - protected static Date createDateFromString(String x, String inputDateFormat, Locale inputLocale, TimeZone inputTimeZone) throws MInvalidConversionFormatException { - if (MText.isBlank(x)) { - throw new IllegalArgumentException("Invalid 'x': null or empty."); - } - MDateConverter.checkDateFormat(inputDateFormat); - if (null == inputLocale) { - throw new IllegalArgumentException("Invalid 'inputLocale': null."); - } - if (null == inputTimeZone) { - throw new IllegalArgumentException("Invalid 'inputTimeZone': null."); - } - // - Calendar c1 = Calendar.getInstance(inputTimeZone, inputLocale); - c1.clear(); - c1.setLenient(false); - SimpleDateFormat sdf = new SimpleDateFormat(inputDateFormat, inputLocale); - sdf.setCalendar(c1); - // - Date d1 = null; - try { - d1 = sdf.parse(x); - } - catch (ParseException exception) { - throw new MInvalidConversionFormatException(String.format("Invalid 'x' or parsing: %s (input format: %s).", x, inputDateFormat)); // no need to propagate exception - } - // - Calendar c2 = Calendar.getInstance(inputTimeZone, inputLocale); - c2.clear(); - c2.set(Calendar.YEAR, c1.get(Calendar.YEAR)); - c2.set(Calendar.MONTH, c1.get(Calendar.MONTH)); - c2.set(Calendar.DAY_OF_MONTH, c1.get(Calendar.DAY_OF_MONTH)); - c2.set(Calendar.HOUR_OF_DAY, c1.get(Calendar.HOUR_OF_DAY)); - c2.set(Calendar.MINUTE, c1.get(Calendar.MINUTE)); - c2.set(Calendar.SECOND, c1.get(Calendar.SECOND)); - // - Date d2 = c2.getTime(); - if (!x.equals(sdf.format(d2))) { - throw new MInvalidConversionFormatException(String.format("Invalid 'x' or parsing: %s (input format: %s).", x, inputDateFormat)); - } - // - return d2; - } - - protected static String createStringFromDate(Date date, String outputDateFormat, Locale outputLocale, TimeZone outputTimeZone) { - if (null == date) { - throw new IllegalArgumentException("Invalid 'date': null."); - } - MDateConverter.checkDateFormat(outputDateFormat); - if (null == outputLocale) { - throw new IllegalArgumentException("Invalid 'outputLocale': null."); - } - if (null == outputTimeZone) { - throw new IllegalArgumentException("Invalid 'outputTimeZone': null."); - } - // - SimpleDateFormat sdf = new SimpleDateFormat(outputDateFormat, outputLocale); - sdf.setCalendar(Calendar.getInstance(outputTimeZone, outputLocale)); - // - return sdf.format(date); - } - - public Date createDateFromString(String x) throws MInvalidConversionFormatException { - Date y = null; - for (String dateFormat: this.getDateFormats()) { - try { - y = MDateConverter.createDateFromString(x, dateFormat, this.getLocale(), this.getTimeZone()); - // - return y; - } - catch (MInvalidConversionFormatException exception) { - } - } - if (null == y) { - throw new MInvalidConversionFormatException(String.format("Invalid 'x': %s.", x)); - } - // - return y; // necessary to avoid Java compilation errors - } - - public String createStringFromDate(Date x) { - return MDateConverter.createStringFromDate(x, this.getDefaultDateFormat(), this.getLocale(), this.getTimeZone()); - } - - /* Helpers. */ - - public static Date getFlatDate(Date x) { - if (null == x) { - return x; - } - // - Calendar calendar = new GregorianCalendar(); - calendar.setTime(x); - calendar.set(Calendar.HOUR_OF_DAY, 0); - calendar.set(Calendar.MINUTE, 0); - calendar.set(Calendar.SECOND, 0); - calendar.set(Calendar.MILLISECOND, 0); - // - return calendar.getTime(); - } - - public static Date getCeilDate(Date x) { - if (null == x) { - return x; - } - // - Calendar calendar = new GregorianCalendar(); - calendar.setTime(x); - calendar.set(Calendar.HOUR_OF_DAY, 23); - calendar.set(Calendar.MINUTE, 59); - calendar.set(Calendar.SECOND, 59); - calendar.set(Calendar.MILLISECOND, 999); - // - return calendar.getTime(); - } - -} diff --git a/src/main/java/com/marcozanon/macaco/conversion/MInvalidConversionFormatException.java b/src/main/java/com/marcozanon/macaco/conversion/MInvalidConversionFormatException.java deleted file mode 100644 index e23c0b1..0000000 --- a/src/main/java/com/marcozanon/macaco/conversion/MInvalidConversionFormatException.java +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Macaco - * Copyright (c) 2009-2024 Marco Zanon . - * See LICENSE for details. - */ - -package com.marcozanon.macaco.conversion; - -@SuppressWarnings("serial") -public class MInvalidConversionFormatException extends MConversionException { - - /* */ - - public MInvalidConversionFormatException() { - super(); - } - - public MInvalidConversionFormatException(String message) { - super(message); - } - - public MInvalidConversionFormatException(Throwable error) { - super(error); - } - - public MInvalidConversionFormatException(String message, Throwable error) { - super(message, error); - } - -} diff --git a/src/main/java/com/marcozanon/macaco/conversion/MLocalDateConverter.java b/src/main/java/com/marcozanon/macaco/conversion/MLocalDateConverter.java deleted file mode 100644 index 6f06a46..0000000 --- a/src/main/java/com/marcozanon/macaco/conversion/MLocalDateConverter.java +++ /dev/null @@ -1,171 +0,0 @@ -/** - * Macaco - * Copyright (c) 2009-2024 Marco Zanon . - * See LICENSE for details. - */ - -package com.marcozanon.macaco.conversion; - -import com.marcozanon.macaco.MObject; -import com.marcozanon.macaco.text.MText; -import java.time.LocalDate; -import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeParseException; -import java.time.format.ResolverStyle; -import java.util.LinkedHashSet; -import java.util.Locale; - -public class MLocalDateConverter extends MObject { - - protected LinkedHashSet dateFormats = new LinkedHashSet(); - protected Locale locale = null; - - /* */ - - public MLocalDateConverter(String defaultDateFormat, Locale locale) { - super(); - // - this.addDateFormat(defaultDateFormat); - this.setLocale(locale); - } - - public MLocalDateConverter(LinkedHashSet dateFormats, Locale locale) { - super(); - // - this.setDateFormats(dateFormats); - this.setLocale(locale); - } - - @Override - public MLocalDateConverter clone() { - return new MLocalDateConverter(this.getDateFormats(), this.getLocale()); - } - - /* Date formats. */ - - public void setDateFormats(LinkedHashSet dateFormats) { - if (null == dateFormats) { - throw new IllegalArgumentException("Invalid 'dateFormats': null."); - } - else if (0 == dateFormats.size()) { - throw new IllegalArgumentException("Invalid 'dateFormats': empty."); - } - else { - for (String dateFormat: dateFormats) { - MLocalDateConverter.checkDateFormat(dateFormat); - } - } - // - synchronized (this.dateFormats) { - this.dateFormats = dateFormats; - } - } - - public void addDateFormat(String dateFormat) { - MLocalDateConverter.checkDateFormat(dateFormat); - // - synchronized (this.dateFormats) { - this.dateFormats.add(dateFormat); - } - } - - public LinkedHashSet getDateFormats() { - return this.dateFormats; - } - - public String getDefaultDateFormat() { - return this.getDateFormats().iterator().next(); - } - - public LinkedHashSet getSecondaryDateFormats() { - LinkedHashSet dateFormats = (LinkedHashSet)this.getDateFormats().clone(); - // - dateFormats.remove(this.getDefaultDateFormat()); - // - return dateFormats; - } - - /* Locale. */ - - protected void setLocale(Locale locale) { - if (null == locale) { - throw new IllegalArgumentException("Invalid 'locale': null."); - } - // - this.locale = locale; - } - - public Locale getLocale() { - return this.locale; - } - - /* Conversions. */ - - protected static void checkDateFormat(String dateFormat) { - if (MText.isBlank(dateFormat)) { - throw new IllegalArgumentException("Invalid 'dateFormat': null or empty."); - } - // - try { - DateTimeFormatter.ofPattern(dateFormat).withResolverStyle(ResolverStyle.STRICT); - } - catch (IllegalArgumentException exception) { - throw new IllegalArgumentException(String.format("Invalid 'dateFormat': %s.", dateFormat)); // no need to propagate exception - } - } - - protected static LocalDate createDateFromString(String x, String inputDateFormat, Locale inputLocale) throws MInvalidConversionFormatException { - if (MText.isBlank(x)) { - throw new IllegalArgumentException("Invalid 'x': null or empty."); - } - MLocalDateConverter.checkDateFormat(inputDateFormat); - if (null == inputLocale) { - throw new IllegalArgumentException("Invalid 'inputLocale': null."); - } - // - LocalDate d = null; - try { - d = LocalDate.parse(x, DateTimeFormatter.ofPattern(inputDateFormat, inputLocale).withResolverStyle(ResolverStyle.STRICT)); - } - catch (DateTimeParseException exception) { - throw new MInvalidConversionFormatException(String.format("Invalid 'x' or parsing: %s (input format: %s).", x, inputDateFormat)); // no need to propagate exception - } - // - return d; - } - - protected static String createStringFromDate(LocalDate date, String outputDateFormat, Locale outputLocale) { - if (null == date) { - throw new IllegalArgumentException("Invalid 'date': null."); - } - MLocalDateConverter.checkDateFormat(outputDateFormat); - if (null == outputLocale) { - throw new IllegalArgumentException("Invalid 'outputLocale': null."); - } - // - return date.format(DateTimeFormatter.ofPattern(outputDateFormat, outputLocale).withResolverStyle(ResolverStyle.STRICT)); - } - - public LocalDate createDateFromString(String x) throws MInvalidConversionFormatException { - LocalDate y = null; - for (String dateFormat: this.getDateFormats()) { - try { - y = MLocalDateConverter.createDateFromString(x, dateFormat, this.getLocale()); - // - return y; - } - catch (MInvalidConversionFormatException exception) { - } - } - if (null == y) { - throw new MInvalidConversionFormatException(String.format("Invalid 'x': %s.", x)); - } - // - return y; // necessary to avoid Java compilation errors - } - - public String createStringFromDate(LocalDate x) { - return MLocalDateConverter.createStringFromDate(x, this.getDefaultDateFormat(), this.getLocale()); - } - -} diff --git a/src/main/java/com/marcozanon/macaco/conversion/MLocalDateTimeConverter.java b/src/main/java/com/marcozanon/macaco/conversion/MLocalDateTimeConverter.java deleted file mode 100644 index 00fae55..0000000 --- a/src/main/java/com/marcozanon/macaco/conversion/MLocalDateTimeConverter.java +++ /dev/null @@ -1,171 +0,0 @@ -/** - * Macaco - * Copyright (c) 2009-2024 Marco Zanon . - * See LICENSE for details. - */ - -package com.marcozanon.macaco.conversion; - -import com.marcozanon.macaco.MObject; -import com.marcozanon.macaco.text.MText; -import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeParseException; -import java.time.format.ResolverStyle; -import java.util.LinkedHashSet; -import java.util.Locale; - -public class MLocalDateTimeConverter extends MObject { - - protected LinkedHashSet datetimeFormats = new LinkedHashSet(); - protected Locale locale = null; - - /* */ - - public MLocalDateTimeConverter(String defaultDatetimeFormat, Locale locale) { - super(); - // - this.addDatetimeFormat(defaultDatetimeFormat); - this.setLocale(locale); - } - - public MLocalDateTimeConverter(LinkedHashSet datetimeFormats, Locale locale) { - super(); - // - this.setDatetimeFormats(datetimeFormats); - this.setLocale(locale); - } - - @Override - public MLocalDateTimeConverter clone() { - return new MLocalDateTimeConverter(this.getDatetimeFormats(), this.getLocale()); - } - - /* Datetime formats. */ - - public void setDatetimeFormats(LinkedHashSet datetimeFormats) { - if (null == datetimeFormats) { - throw new IllegalArgumentException("Invalid 'datetimeFormats': null."); - } - else if (0 == datetimeFormats.size()) { - throw new IllegalArgumentException("Invalid 'datetimeFormats': empty."); - } - else { - for (String datetimeFormat: datetimeFormats) { - MLocalDateTimeConverter.checkDatetimeFormat(datetimeFormat); - } - } - // - synchronized (this.datetimeFormats) { - this.datetimeFormats = datetimeFormats; - } - } - - public void addDatetimeFormat(String datetimeFormat) { - MLocalDateTimeConverter.checkDatetimeFormat(datetimeFormat); - // - synchronized (this.datetimeFormats) { - this.datetimeFormats.add(datetimeFormat); - } - } - - public LinkedHashSet getDatetimeFormats() { - return this.datetimeFormats; - } - - public String getDefaultDatetimeFormat() { - return this.getDatetimeFormats().iterator().next(); - } - - public LinkedHashSet getSecondaryDatetimeFormats() { - LinkedHashSet datetimeFormats = (LinkedHashSet)this.getDatetimeFormats().clone(); - // - datetimeFormats.remove(this.getDefaultDatetimeFormat()); - // - return datetimeFormats; - } - - /* Locale. */ - - protected void setLocale(Locale locale) { - if (null == locale) { - throw new IllegalArgumentException("Invalid 'locale': null."); - } - // - this.locale = locale; - } - - public Locale getLocale() { - return this.locale; - } - - /* Conversions. */ - - protected static void checkDatetimeFormat(String datetimeFormat) { - if (MText.isBlank(datetimeFormat)) { - throw new IllegalArgumentException("Invalid 'datetimeFormat': null or empty."); - } - // - try { - DateTimeFormatter.ofPattern(datetimeFormat).withResolverStyle(ResolverStyle.STRICT); - } - catch (IllegalArgumentException exception) { - throw new IllegalArgumentException(String.format("Invalid 'datetimeFormat': %s.", datetimeFormat)); // no need to propagate exception - } - } - - protected static LocalDateTime createDatetimeFromString(String x, String inputDatetimeFormat, Locale inputLocale) throws MInvalidConversionFormatException { - if (MText.isBlank(x)) { - throw new IllegalArgumentException("Invalid 'x': null or empty."); - } - MLocalDateTimeConverter.checkDatetimeFormat(inputDatetimeFormat); - if (null == inputLocale) { - throw new IllegalArgumentException("Invalid 'inputLocale': null."); - } - // - LocalDateTime dt = null; - try { - dt = LocalDateTime.parse(x, DateTimeFormatter.ofPattern(inputDatetimeFormat, inputLocale).withResolverStyle(ResolverStyle.STRICT)); - } - catch (DateTimeParseException exception) { - throw new MInvalidConversionFormatException(String.format("Invalid 'x' or parsing: %s (input format: %s).", x, inputDatetimeFormat)); // no need to propagate exception - } - // - return dt; - } - - protected static String createStringFromDatetime(LocalDateTime datetime, String outputDatetimeFormat, Locale outputLocale) { - if (null == datetime) { - throw new IllegalArgumentException("Invalid 'datetime': null."); - } - MLocalDateTimeConverter.checkDatetimeFormat(outputDatetimeFormat); - if (null == outputLocale) { - throw new IllegalArgumentException("Invalid 'outputLocale': null."); - } - // - return datetime.format(DateTimeFormatter.ofPattern(outputDatetimeFormat, outputLocale).withResolverStyle(ResolverStyle.STRICT)); - } - - public LocalDateTime createDatetimeFromString(String x) throws MInvalidConversionFormatException { - LocalDateTime y = null; - for (String datetimeFormat: this.getDatetimeFormats()) { - try { - y = MLocalDateTimeConverter.createDatetimeFromString(x, datetimeFormat, this.getLocale()); - // - return y; - } - catch (MInvalidConversionFormatException exception) { - } - } - if (null == y) { - throw new MInvalidConversionFormatException(String.format("Invalid 'x': %s.", x)); - } - // - return y; // necessary to avoid Java compilation errors - } - - public String createStringFromDatetime(LocalDateTime x) { - return MLocalDateTimeConverter.createStringFromDatetime(x, this.getDefaultDatetimeFormat(), this.getLocale()); - } - -} diff --git a/src/main/java/com/marcozanon/macaco/conversion/MNumberConverter.java b/src/main/java/com/marcozanon/macaco/conversion/MNumberConverter.java deleted file mode 100644 index d599c08..0000000 --- a/src/main/java/com/marcozanon/macaco/conversion/MNumberConverter.java +++ /dev/null @@ -1,178 +0,0 @@ -/** - * Macaco - * Copyright (c) 2009-2024 Marco Zanon . - * See LICENSE for details. - */ - -package com.marcozanon.macaco.conversion; - -import com.marcozanon.macaco.MObject; -import com.marcozanon.macaco.text.MText; -import java.math.BigDecimal; -import java.math.RoundingMode; -import java.text.DecimalFormat; -import java.text.DecimalFormatSymbols; -import java.text.ParsePosition; -import java.util.LinkedHashSet; -import java.util.Locale; - -public class MNumberConverter extends MObject { - - protected LinkedHashSet numberFormats = new LinkedHashSet(); - protected Locale locale = null; - - /* */ - - public MNumberConverter(String defaultNumberFormat, Locale locale) { - super(); - // - this.addNumberFormat(defaultNumberFormat); - this.setLocale(locale); - } - - public MNumberConverter(LinkedHashSet numberFormats, Locale locale) { - super(); - // - this.setNumberFormats(numberFormats); - this.setLocale(locale); - } - - @Override - public MNumberConverter clone() { - return new MNumberConverter(this.getNumberFormats(), this.getLocale()); - } - - /* Number formats. */ - - public void setNumberFormats(LinkedHashSet numberFormats) { - if (null == numberFormats) { - throw new IllegalArgumentException("Invalid 'numberFormats': null."); - } - else if (0 == numberFormats.size()) { - throw new IllegalArgumentException("Invalid 'numberFormats': empty."); - } - else { - for (String numberFormat: numberFormats) { - MNumberConverter.checkNumberFormat(numberFormat); - } - } - // - synchronized (this.numberFormats) { - this.numberFormats = numberFormats; - } - } - - public void addNumberFormat(String numberFormat) { - MNumberConverter.checkNumberFormat(numberFormat); - // - synchronized (this.numberFormats) { - this.numberFormats.add(numberFormat); - } - } - - public LinkedHashSet getNumberFormats() { - return this.numberFormats; - } - - public String getDefaultNumberFormat() { - return this.getNumberFormats().iterator().next(); - } - - public LinkedHashSet getSecondaryNumberFormats() { - LinkedHashSet numberFormats = (LinkedHashSet)this.getNumberFormats().clone(); - // - numberFormats.remove(this.getDefaultNumberFormat()); - // - return numberFormats; - } - - /* Locale. */ - - protected void setLocale(Locale locale) { - if (null == locale) { - throw new IllegalArgumentException("Invalid 'locale': null."); - } - // - this.locale = locale; - } - - public Locale getLocale() { - return this.locale; - } - - /* Conversions. */ - - protected static void checkNumberFormat(String numberFormat) { - if (MText.isBlank(numberFormat)) { - throw new IllegalArgumentException("Invalid 'numberFormat': null or empty."); - } - // - try { - DecimalFormat testNumberFormat = new DecimalFormat(numberFormat); - } - catch (IllegalArgumentException exception) { - throw new IllegalArgumentException(String.format("Invalid 'numberFormat': %s.", numberFormat)); // no need to propagate exception - } - } - - protected static BigDecimal createNumberFromString(String x, String inputNumberFormat, Locale inputLocale) throws MInvalidConversionFormatException { - if (MText.isBlank(x)) { - throw new IllegalArgumentException("Invalid 'x': null or empty."); - } - MNumberConverter.checkNumberFormat(inputNumberFormat); - if (null == inputLocale) { - throw new IllegalArgumentException("Invalid 'inputLocale': null."); - } - // - DecimalFormatSymbols dfs = new DecimalFormatSymbols(inputLocale); - DecimalFormat df = new DecimalFormat(inputNumberFormat, dfs); - df.setParseBigDecimal(true); - // - ParsePosition validPosition = new ParsePosition(0); - BigDecimal bd = (BigDecimal)df.parse(x, validPosition); - if (validPosition.getIndex() < x.length()) { - throw new MInvalidConversionFormatException(String.format("Invalid 'x' or parsing: %s (input format: %s).", x, inputNumberFormat)); - } - // - return bd; - } - - protected static String createStringFromNumber(BigDecimal number, String outputNumberFormat, Locale outputLocale) { - if (null == number) { - throw new IllegalArgumentException("Invalid 'number': null."); - } - MNumberConverter.checkNumberFormat(outputNumberFormat); - if (null == outputLocale) { - throw new IllegalArgumentException("Invalid 'outputLocale': null."); - } - // - DecimalFormatSymbols dfs = new DecimalFormatSymbols(outputLocale); - DecimalFormat df = new DecimalFormat(outputNumberFormat, dfs); - df.setRoundingMode(RoundingMode.HALF_UP); - // - return df.format(number); - } - - public BigDecimal createNumberFromString(String x) throws MInvalidConversionFormatException { - BigDecimal y = null; - for (String numberFormat: this.getNumberFormats()) { - try { - y = MNumberConverter.createNumberFromString(x, numberFormat, this.getLocale()); - // - return y; - } - catch (MInvalidConversionFormatException exception) { - } - } - if (null == y) { - throw new MInvalidConversionFormatException(String.format("Invalid 'x': %s.", x)); - } - // - return y; // necessary to avoid Java compilation errors - } - - public String createStringFromNumber(BigDecimal x) { - return MNumberConverter.createStringFromNumber(x, this.getDefaultNumberFormat(), this.getLocale()); - } - -} diff --git a/src/main/java/com/marcozanon/macaco/conversions/MConversionException.java b/src/main/java/com/marcozanon/macaco/conversions/MConversionException.java new file mode 100644 index 0000000..01a8f72 --- /dev/null +++ b/src/main/java/com/marcozanon/macaco/conversions/MConversionException.java @@ -0,0 +1,31 @@ +/** + * Macaco + * Copyright (c) 2009-2024 Marco Zanon . + * See LICENSE for details. + */ + +package com.marcozanon.macaco.conversions; + +import com.marcozanon.macaco.MException; + +public abstract class MConversionException extends MException { + + /* */ + + public MConversionException() { + super(); + } + + public MConversionException(String message) { + super(message); + } + + public MConversionException(Throwable error) { + super(error); + } + + public MConversionException(String message, Throwable error) { + super(message, error); + } + +} diff --git a/src/main/java/com/marcozanon/macaco/conversions/MDateConverter.java b/src/main/java/com/marcozanon/macaco/conversions/MDateConverter.java new file mode 100644 index 0000000..959a4bc --- /dev/null +++ b/src/main/java/com/marcozanon/macaco/conversions/MDateConverter.java @@ -0,0 +1,255 @@ +/** + * Macaco + * Copyright (c) 2009-2024 Marco Zanon . + * See LICENSE for details. + */ + +package com.marcozanon.macaco.conversions; + +import com.marcozanon.macaco.MObject; +import com.marcozanon.macaco.text.MText; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.LinkedHashSet; +import java.util.Locale; +import java.util.TimeZone; + +public class MDateConverter extends MObject { + + protected LinkedHashSet dateFormats = new LinkedHashSet(); + protected Locale locale = null; + protected TimeZone timeZone = null; + + /* */ + + public MDateConverter(String defaultDateFormat, Locale locale) { + this(defaultDateFormat, locale, TimeZone.getDefault()); + } + + public MDateConverter(String defaultDateFormat, Locale locale, TimeZone timeZone) { + super(); + // + this.addDateFormat(defaultDateFormat); + this.setLocale(locale); + this.setTimeZone(timeZone); + } + + public MDateConverter(LinkedHashSet dateFormats, Locale locale, TimeZone timeZone) { + super(); + // + this.setDateFormats(dateFormats); + this.setLocale(locale); + this.setTimeZone(timeZone); + } + + @Override + public MDateConverter clone() { + return new MDateConverter(this.getDateFormats(), this.getLocale(), this.getTimeZone()); + } + + /* Date formats. */ + + public void setDateFormats(LinkedHashSet dateFormats) { + if (null == dateFormats) { + throw new IllegalArgumentException("Invalid 'dateFormats': null."); + } + else if (0 == dateFormats.size()) { + throw new IllegalArgumentException("Invalid 'dateFormats': empty."); + } + else { + for (String dateFormat: dateFormats) { + MDateConverter.checkDateFormat(dateFormat); + } + } + // + synchronized (this.dateFormats) { + this.dateFormats = dateFormats; + } + } + + public void addDateFormat(String dateFormat) { + MDateConverter.checkDateFormat(dateFormat); + // + synchronized (this.dateFormats) { + this.dateFormats.add(dateFormat); + } + } + + public LinkedHashSet getDateFormats() { + return this.dateFormats; + } + + public String getDefaultDateFormat() { + return this.getDateFormats().iterator().next(); + } + + public LinkedHashSet getSecondaryDateFormats() { + LinkedHashSet dateFormats = (LinkedHashSet)this.getDateFormats().clone(); + // + dateFormats.remove(this.getDefaultDateFormat()); + // + return dateFormats; + } + + /* Locale. */ + + protected void setLocale(Locale locale) { + if (null == locale) { + throw new IllegalArgumentException("Invalid 'locale': null."); + } + // + this.locale = locale; + } + + public Locale getLocale() { + return this.locale; + } + + /* Time zone. */ + + protected void setTimeZone(TimeZone timeZone) { + if (null == timeZone) { + throw new IllegalArgumentException("Invalid 'timeZone': null."); + } + // + this.timeZone = timeZone; + } + + public TimeZone getTimeZone() { + return this.timeZone; + } + + /* Conversions. */ + + protected static void checkDateFormat(String dateFormat) { + if (MText.isBlank(dateFormat)) { + throw new IllegalArgumentException("Invalid 'dateFormat': null or empty."); + } + // + try { + SimpleDateFormat testDateFormat = new SimpleDateFormat(dateFormat); + } + catch (IllegalArgumentException exception) { + throw new IllegalArgumentException(String.format("Invalid 'dateFormat': %s.", dateFormat)); // no need to propagate exception + } + } + + protected static Date createDateFromString(String x, String inputDateFormat, Locale inputLocale, TimeZone inputTimeZone) throws MInvalidConversionFormatException { + if (MText.isBlank(x)) { + throw new IllegalArgumentException("Invalid 'x': null or empty."); + } + MDateConverter.checkDateFormat(inputDateFormat); + if (null == inputLocale) { + throw new IllegalArgumentException("Invalid 'inputLocale': null."); + } + if (null == inputTimeZone) { + throw new IllegalArgumentException("Invalid 'inputTimeZone': null."); + } + // + Calendar c1 = Calendar.getInstance(inputTimeZone, inputLocale); + c1.clear(); + c1.setLenient(false); + SimpleDateFormat sdf = new SimpleDateFormat(inputDateFormat, inputLocale); + sdf.setCalendar(c1); + // + Date d1 = null; + try { + d1 = sdf.parse(x); + } + catch (ParseException exception) { + throw new MInvalidConversionFormatException(String.format("Invalid 'x' or parsing: %s (input format: %s).", x, inputDateFormat)); // no need to propagate exception + } + // + Calendar c2 = Calendar.getInstance(inputTimeZone, inputLocale); + c2.clear(); + c2.set(Calendar.YEAR, c1.get(Calendar.YEAR)); + c2.set(Calendar.MONTH, c1.get(Calendar.MONTH)); + c2.set(Calendar.DAY_OF_MONTH, c1.get(Calendar.DAY_OF_MONTH)); + c2.set(Calendar.HOUR_OF_DAY, c1.get(Calendar.HOUR_OF_DAY)); + c2.set(Calendar.MINUTE, c1.get(Calendar.MINUTE)); + c2.set(Calendar.SECOND, c1.get(Calendar.SECOND)); + // + Date d2 = c2.getTime(); + if (!x.equals(sdf.format(d2))) { + throw new MInvalidConversionFormatException(String.format("Invalid 'x' or parsing: %s (input format: %s).", x, inputDateFormat)); + } + // + return d2; + } + + protected static String createStringFromDate(Date date, String outputDateFormat, Locale outputLocale, TimeZone outputTimeZone) { + if (null == date) { + throw new IllegalArgumentException("Invalid 'date': null."); + } + MDateConverter.checkDateFormat(outputDateFormat); + if (null == outputLocale) { + throw new IllegalArgumentException("Invalid 'outputLocale': null."); + } + if (null == outputTimeZone) { + throw new IllegalArgumentException("Invalid 'outputTimeZone': null."); + } + // + SimpleDateFormat sdf = new SimpleDateFormat(outputDateFormat, outputLocale); + sdf.setCalendar(Calendar.getInstance(outputTimeZone, outputLocale)); + // + return sdf.format(date); + } + + public Date createDateFromString(String x) throws MInvalidConversionFormatException { + Date y = null; + for (String dateFormat: this.getDateFormats()) { + try { + y = MDateConverter.createDateFromString(x, dateFormat, this.getLocale(), this.getTimeZone()); + // + return y; + } + catch (MInvalidConversionFormatException exception) { + } + } + if (null == y) { + throw new MInvalidConversionFormatException(String.format("Invalid 'x': %s.", x)); + } + // + return y; // necessary to avoid Java compilation errors + } + + public String createStringFromDate(Date x) { + return MDateConverter.createStringFromDate(x, this.getDefaultDateFormat(), this.getLocale(), this.getTimeZone()); + } + + /* Helpers. */ + + public static Date getFlatDate(Date x) { + if (null == x) { + return x; + } + // + Calendar calendar = new GregorianCalendar(); + calendar.setTime(x); + calendar.set(Calendar.HOUR_OF_DAY, 0); + calendar.set(Calendar.MINUTE, 0); + calendar.set(Calendar.SECOND, 0); + calendar.set(Calendar.MILLISECOND, 0); + // + return calendar.getTime(); + } + + public static Date getCeilDate(Date x) { + if (null == x) { + return x; + } + // + Calendar calendar = new GregorianCalendar(); + calendar.setTime(x); + calendar.set(Calendar.HOUR_OF_DAY, 23); + calendar.set(Calendar.MINUTE, 59); + calendar.set(Calendar.SECOND, 59); + calendar.set(Calendar.MILLISECOND, 999); + // + return calendar.getTime(); + } + +} diff --git a/src/main/java/com/marcozanon/macaco/conversions/MInvalidConversionFormatException.java b/src/main/java/com/marcozanon/macaco/conversions/MInvalidConversionFormatException.java new file mode 100644 index 0000000..40b7d73 --- /dev/null +++ b/src/main/java/com/marcozanon/macaco/conversions/MInvalidConversionFormatException.java @@ -0,0 +1,30 @@ +/** + * Macaco + * Copyright (c) 2009-2024 Marco Zanon . + * See LICENSE for details. + */ + +package com.marcozanon.macaco.conversions; + +@SuppressWarnings("serial") +public class MInvalidConversionFormatException extends MConversionException { + + /* */ + + public MInvalidConversionFormatException() { + super(); + } + + public MInvalidConversionFormatException(String message) { + super(message); + } + + public MInvalidConversionFormatException(Throwable error) { + super(error); + } + + public MInvalidConversionFormatException(String message, Throwable error) { + super(message, error); + } + +} diff --git a/src/main/java/com/marcozanon/macaco/conversions/MLocalDateConverter.java b/src/main/java/com/marcozanon/macaco/conversions/MLocalDateConverter.java new file mode 100644 index 0000000..67c21e6 --- /dev/null +++ b/src/main/java/com/marcozanon/macaco/conversions/MLocalDateConverter.java @@ -0,0 +1,171 @@ +/** + * Macaco + * Copyright (c) 2009-2024 Marco Zanon . + * See LICENSE for details. + */ + +package com.marcozanon.macaco.conversions; + +import com.marcozanon.macaco.MObject; +import com.marcozanon.macaco.text.MText; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; +import java.time.format.ResolverStyle; +import java.util.LinkedHashSet; +import java.util.Locale; + +public class MLocalDateConverter extends MObject { + + protected LinkedHashSet dateFormats = new LinkedHashSet(); + protected Locale locale = null; + + /* */ + + public MLocalDateConverter(String defaultDateFormat, Locale locale) { + super(); + // + this.addDateFormat(defaultDateFormat); + this.setLocale(locale); + } + + public MLocalDateConverter(LinkedHashSet dateFormats, Locale locale) { + super(); + // + this.setDateFormats(dateFormats); + this.setLocale(locale); + } + + @Override + public MLocalDateConverter clone() { + return new MLocalDateConverter(this.getDateFormats(), this.getLocale()); + } + + /* Date formats. */ + + public void setDateFormats(LinkedHashSet dateFormats) { + if (null == dateFormats) { + throw new IllegalArgumentException("Invalid 'dateFormats': null."); + } + else if (0 == dateFormats.size()) { + throw new IllegalArgumentException("Invalid 'dateFormats': empty."); + } + else { + for (String dateFormat: dateFormats) { + MLocalDateConverter.checkDateFormat(dateFormat); + } + } + // + synchronized (this.dateFormats) { + this.dateFormats = dateFormats; + } + } + + public void addDateFormat(String dateFormat) { + MLocalDateConverter.checkDateFormat(dateFormat); + // + synchronized (this.dateFormats) { + this.dateFormats.add(dateFormat); + } + } + + public LinkedHashSet getDateFormats() { + return this.dateFormats; + } + + public String getDefaultDateFormat() { + return this.getDateFormats().iterator().next(); + } + + public LinkedHashSet getSecondaryDateFormats() { + LinkedHashSet dateFormats = (LinkedHashSet)this.getDateFormats().clone(); + // + dateFormats.remove(this.getDefaultDateFormat()); + // + return dateFormats; + } + + /* Locale. */ + + protected void setLocale(Locale locale) { + if (null == locale) { + throw new IllegalArgumentException("Invalid 'locale': null."); + } + // + this.locale = locale; + } + + public Locale getLocale() { + return this.locale; + } + + /* Conversions. */ + + protected static void checkDateFormat(String dateFormat) { + if (MText.isBlank(dateFormat)) { + throw new IllegalArgumentException("Invalid 'dateFormat': null or empty."); + } + // + try { + DateTimeFormatter.ofPattern(dateFormat).withResolverStyle(ResolverStyle.STRICT); + } + catch (IllegalArgumentException exception) { + throw new IllegalArgumentException(String.format("Invalid 'dateFormat': %s.", dateFormat)); // no need to propagate exception + } + } + + protected static LocalDate createDateFromString(String x, String inputDateFormat, Locale inputLocale) throws MInvalidConversionFormatException { + if (MText.isBlank(x)) { + throw new IllegalArgumentException("Invalid 'x': null or empty."); + } + MLocalDateConverter.checkDateFormat(inputDateFormat); + if (null == inputLocale) { + throw new IllegalArgumentException("Invalid 'inputLocale': null."); + } + // + LocalDate d = null; + try { + d = LocalDate.parse(x, DateTimeFormatter.ofPattern(inputDateFormat, inputLocale).withResolverStyle(ResolverStyle.STRICT)); + } + catch (DateTimeParseException exception) { + throw new MInvalidConversionFormatException(String.format("Invalid 'x' or parsing: %s (input format: %s).", x, inputDateFormat)); // no need to propagate exception + } + // + return d; + } + + protected static String createStringFromDate(LocalDate date, String outputDateFormat, Locale outputLocale) { + if (null == date) { + throw new IllegalArgumentException("Invalid 'date': null."); + } + MLocalDateConverter.checkDateFormat(outputDateFormat); + if (null == outputLocale) { + throw new IllegalArgumentException("Invalid 'outputLocale': null."); + } + // + return date.format(DateTimeFormatter.ofPattern(outputDateFormat, outputLocale).withResolverStyle(ResolverStyle.STRICT)); + } + + public LocalDate createDateFromString(String x) throws MInvalidConversionFormatException { + LocalDate y = null; + for (String dateFormat: this.getDateFormats()) { + try { + y = MLocalDateConverter.createDateFromString(x, dateFormat, this.getLocale()); + // + return y; + } + catch (MInvalidConversionFormatException exception) { + } + } + if (null == y) { + throw new MInvalidConversionFormatException(String.format("Invalid 'x': %s.", x)); + } + // + return y; // necessary to avoid Java compilation errors + } + + public String createStringFromDate(LocalDate x) { + return MLocalDateConverter.createStringFromDate(x, this.getDefaultDateFormat(), this.getLocale()); + } + +} diff --git a/src/main/java/com/marcozanon/macaco/conversions/MLocalDateTimeConverter.java b/src/main/java/com/marcozanon/macaco/conversions/MLocalDateTimeConverter.java new file mode 100644 index 0000000..4857f55 --- /dev/null +++ b/src/main/java/com/marcozanon/macaco/conversions/MLocalDateTimeConverter.java @@ -0,0 +1,171 @@ +/** + * Macaco + * Copyright (c) 2009-2024 Marco Zanon . + * See LICENSE for details. + */ + +package com.marcozanon.macaco.conversions; + +import com.marcozanon.macaco.MObject; +import com.marcozanon.macaco.text.MText; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; +import java.time.format.ResolverStyle; +import java.util.LinkedHashSet; +import java.util.Locale; + +public class MLocalDateTimeConverter extends MObject { + + protected LinkedHashSet datetimeFormats = new LinkedHashSet(); + protected Locale locale = null; + + /* */ + + public MLocalDateTimeConverter(String defaultDatetimeFormat, Locale locale) { + super(); + // + this.addDatetimeFormat(defaultDatetimeFormat); + this.setLocale(locale); + } + + public MLocalDateTimeConverter(LinkedHashSet datetimeFormats, Locale locale) { + super(); + // + this.setDatetimeFormats(datetimeFormats); + this.setLocale(locale); + } + + @Override + public MLocalDateTimeConverter clone() { + return new MLocalDateTimeConverter(this.getDatetimeFormats(), this.getLocale()); + } + + /* Datetime formats. */ + + public void setDatetimeFormats(LinkedHashSet datetimeFormats) { + if (null == datetimeFormats) { + throw new IllegalArgumentException("Invalid 'datetimeFormats': null."); + } + else if (0 == datetimeFormats.size()) { + throw new IllegalArgumentException("Invalid 'datetimeFormats': empty."); + } + else { + for (String datetimeFormat: datetimeFormats) { + MLocalDateTimeConverter.checkDatetimeFormat(datetimeFormat); + } + } + // + synchronized (this.datetimeFormats) { + this.datetimeFormats = datetimeFormats; + } + } + + public void addDatetimeFormat(String datetimeFormat) { + MLocalDateTimeConverter.checkDatetimeFormat(datetimeFormat); + // + synchronized (this.datetimeFormats) { + this.datetimeFormats.add(datetimeFormat); + } + } + + public LinkedHashSet getDatetimeFormats() { + return this.datetimeFormats; + } + + public String getDefaultDatetimeFormat() { + return this.getDatetimeFormats().iterator().next(); + } + + public LinkedHashSet getSecondaryDatetimeFormats() { + LinkedHashSet datetimeFormats = (LinkedHashSet)this.getDatetimeFormats().clone(); + // + datetimeFormats.remove(this.getDefaultDatetimeFormat()); + // + return datetimeFormats; + } + + /* Locale. */ + + protected void setLocale(Locale locale) { + if (null == locale) { + throw new IllegalArgumentException("Invalid 'locale': null."); + } + // + this.locale = locale; + } + + public Locale getLocale() { + return this.locale; + } + + /* Conversions. */ + + protected static void checkDatetimeFormat(String datetimeFormat) { + if (MText.isBlank(datetimeFormat)) { + throw new IllegalArgumentException("Invalid 'datetimeFormat': null or empty."); + } + // + try { + DateTimeFormatter.ofPattern(datetimeFormat).withResolverStyle(ResolverStyle.STRICT); + } + catch (IllegalArgumentException exception) { + throw new IllegalArgumentException(String.format("Invalid 'datetimeFormat': %s.", datetimeFormat)); // no need to propagate exception + } + } + + protected static LocalDateTime createDatetimeFromString(String x, String inputDatetimeFormat, Locale inputLocale) throws MInvalidConversionFormatException { + if (MText.isBlank(x)) { + throw new IllegalArgumentException("Invalid 'x': null or empty."); + } + MLocalDateTimeConverter.checkDatetimeFormat(inputDatetimeFormat); + if (null == inputLocale) { + throw new IllegalArgumentException("Invalid 'inputLocale': null."); + } + // + LocalDateTime dt = null; + try { + dt = LocalDateTime.parse(x, DateTimeFormatter.ofPattern(inputDatetimeFormat, inputLocale).withResolverStyle(ResolverStyle.STRICT)); + } + catch (DateTimeParseException exception) { + throw new MInvalidConversionFormatException(String.format("Invalid 'x' or parsing: %s (input format: %s).", x, inputDatetimeFormat)); // no need to propagate exception + } + // + return dt; + } + + protected static String createStringFromDatetime(LocalDateTime datetime, String outputDatetimeFormat, Locale outputLocale) { + if (null == datetime) { + throw new IllegalArgumentException("Invalid 'datetime': null."); + } + MLocalDateTimeConverter.checkDatetimeFormat(outputDatetimeFormat); + if (null == outputLocale) { + throw new IllegalArgumentException("Invalid 'outputLocale': null."); + } + // + return datetime.format(DateTimeFormatter.ofPattern(outputDatetimeFormat, outputLocale).withResolverStyle(ResolverStyle.STRICT)); + } + + public LocalDateTime createDatetimeFromString(String x) throws MInvalidConversionFormatException { + LocalDateTime y = null; + for (String datetimeFormat: this.getDatetimeFormats()) { + try { + y = MLocalDateTimeConverter.createDatetimeFromString(x, datetimeFormat, this.getLocale()); + // + return y; + } + catch (MInvalidConversionFormatException exception) { + } + } + if (null == y) { + throw new MInvalidConversionFormatException(String.format("Invalid 'x': %s.", x)); + } + // + return y; // necessary to avoid Java compilation errors + } + + public String createStringFromDatetime(LocalDateTime x) { + return MLocalDateTimeConverter.createStringFromDatetime(x, this.getDefaultDatetimeFormat(), this.getLocale()); + } + +} diff --git a/src/main/java/com/marcozanon/macaco/conversions/MNumberConverter.java b/src/main/java/com/marcozanon/macaco/conversions/MNumberConverter.java new file mode 100644 index 0000000..3e00bd3 --- /dev/null +++ b/src/main/java/com/marcozanon/macaco/conversions/MNumberConverter.java @@ -0,0 +1,178 @@ +/** + * Macaco + * Copyright (c) 2009-2024 Marco Zanon . + * See LICENSE for details. + */ + +package com.marcozanon.macaco.conversions; + +import com.marcozanon.macaco.MObject; +import com.marcozanon.macaco.text.MText; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.text.DecimalFormat; +import java.text.DecimalFormatSymbols; +import java.text.ParsePosition; +import java.util.LinkedHashSet; +import java.util.Locale; + +public class MNumberConverter extends MObject { + + protected LinkedHashSet numberFormats = new LinkedHashSet(); + protected Locale locale = null; + + /* */ + + public MNumberConverter(String defaultNumberFormat, Locale locale) { + super(); + // + this.addNumberFormat(defaultNumberFormat); + this.setLocale(locale); + } + + public MNumberConverter(LinkedHashSet numberFormats, Locale locale) { + super(); + // + this.setNumberFormats(numberFormats); + this.setLocale(locale); + } + + @Override + public MNumberConverter clone() { + return new MNumberConverter(this.getNumberFormats(), this.getLocale()); + } + + /* Number formats. */ + + public void setNumberFormats(LinkedHashSet numberFormats) { + if (null == numberFormats) { + throw new IllegalArgumentException("Invalid 'numberFormats': null."); + } + else if (0 == numberFormats.size()) { + throw new IllegalArgumentException("Invalid 'numberFormats': empty."); + } + else { + for (String numberFormat: numberFormats) { + MNumberConverter.checkNumberFormat(numberFormat); + } + } + // + synchronized (this.numberFormats) { + this.numberFormats = numberFormats; + } + } + + public void addNumberFormat(String numberFormat) { + MNumberConverter.checkNumberFormat(numberFormat); + // + synchronized (this.numberFormats) { + this.numberFormats.add(numberFormat); + } + } + + public LinkedHashSet getNumberFormats() { + return this.numberFormats; + } + + public String getDefaultNumberFormat() { + return this.getNumberFormats().iterator().next(); + } + + public LinkedHashSet getSecondaryNumberFormats() { + LinkedHashSet numberFormats = (LinkedHashSet)this.getNumberFormats().clone(); + // + numberFormats.remove(this.getDefaultNumberFormat()); + // + return numberFormats; + } + + /* Locale. */ + + protected void setLocale(Locale locale) { + if (null == locale) { + throw new IllegalArgumentException("Invalid 'locale': null."); + } + // + this.locale = locale; + } + + public Locale getLocale() { + return this.locale; + } + + /* Conversions. */ + + protected static void checkNumberFormat(String numberFormat) { + if (MText.isBlank(numberFormat)) { + throw new IllegalArgumentException("Invalid 'numberFormat': null or empty."); + } + // + try { + DecimalFormat testNumberFormat = new DecimalFormat(numberFormat); + } + catch (IllegalArgumentException exception) { + throw new IllegalArgumentException(String.format("Invalid 'numberFormat': %s.", numberFormat)); // no need to propagate exception + } + } + + protected static BigDecimal createNumberFromString(String x, String inputNumberFormat, Locale inputLocale) throws MInvalidConversionFormatException { + if (MText.isBlank(x)) { + throw new IllegalArgumentException("Invalid 'x': null or empty."); + } + MNumberConverter.checkNumberFormat(inputNumberFormat); + if (null == inputLocale) { + throw new IllegalArgumentException("Invalid 'inputLocale': null."); + } + // + DecimalFormatSymbols dfs = new DecimalFormatSymbols(inputLocale); + DecimalFormat df = new DecimalFormat(inputNumberFormat, dfs); + df.setParseBigDecimal(true); + // + ParsePosition validPosition = new ParsePosition(0); + BigDecimal bd = (BigDecimal)df.parse(x, validPosition); + if (validPosition.getIndex() < x.length()) { + throw new MInvalidConversionFormatException(String.format("Invalid 'x' or parsing: %s (input format: %s).", x, inputNumberFormat)); + } + // + return bd; + } + + protected static String createStringFromNumber(BigDecimal number, String outputNumberFormat, Locale outputLocale) { + if (null == number) { + throw new IllegalArgumentException("Invalid 'number': null."); + } + MNumberConverter.checkNumberFormat(outputNumberFormat); + if (null == outputLocale) { + throw new IllegalArgumentException("Invalid 'outputLocale': null."); + } + // + DecimalFormatSymbols dfs = new DecimalFormatSymbols(outputLocale); + DecimalFormat df = new DecimalFormat(outputNumberFormat, dfs); + df.setRoundingMode(RoundingMode.HALF_UP); + // + return df.format(number); + } + + public BigDecimal createNumberFromString(String x) throws MInvalidConversionFormatException { + BigDecimal y = null; + for (String numberFormat: this.getNumberFormats()) { + try { + y = MNumberConverter.createNumberFromString(x, numberFormat, this.getLocale()); + // + return y; + } + catch (MInvalidConversionFormatException exception) { + } + } + if (null == y) { + throw new MInvalidConversionFormatException(String.format("Invalid 'x': %s.", x)); + } + // + return y; // necessary to avoid Java compilation errors + } + + public String createStringFromNumber(BigDecimal x) { + return MNumberConverter.createStringFromNumber(x, this.getDefaultNumberFormat(), this.getLocale()); + } + +}