001/* 002 * ============================================================================ 003 * Copyright © 2002-2023 by Thomas Thrien. 004 * All Rights Reserved. 005 * ============================================================================ 006 * Licensed to the public under the agreements of the GNU Lesser General Public 007 * License, version 3.0 (the "License"). You may obtain a copy of the License at 008 * 009 * http://www.gnu.org/licenses/lgpl.html 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 013 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 014 * License for the specific language governing permissions and limitations 015 * under the License. 016 */ 017 018package org.tquadrat.foundation.util.stringconverter; 019 020import static java.lang.String.format; 021import static org.apiguardian.api.API.Status.STABLE; 022import static org.tquadrat.foundation.lang.Objects.nonNull; 023import static org.tquadrat.foundation.util.StringUtils.isEmptyOrBlank; 024 025import java.io.Serial; 026import java.util.Collection; 027import java.util.List; 028 029import org.apiguardian.api.API; 030import org.tquadrat.foundation.annotation.ClassVersion; 031import org.tquadrat.foundation.lang.StringConverter; 032 033/** 034 * The base class for implementations of 035 * {@link StringConverter} 036 * for types that extend 037 * {@link java.lang.Number}. 038 * 039 * @param <T> The type that is handled by this class. 040 * 041 * @extauthor Thomas Thrien - thomas.thrien@tquadrat.org 042 * @version $Id: NumberStringConverter.java 1080 2024-01-03 11:05:21Z tquadrat $ 043 * @since 0.0.6 044 * 045 * @UMLGraph.link 046 */ 047@ClassVersion( sourceVersion = "$Id: NumberStringConverter.java 1080 2024-01-03 11:05:21Z tquadrat $" ) 048@API( status = STABLE, since = "0.0.6" ) 049public abstract sealed class NumberStringConverter<T extends Number> implements StringConverter<T> 050 permits org.tquadrat.foundation.util.stringconverter.BigDecimalStringConverter, 051 org.tquadrat.foundation.util.stringconverter.BigIntegerStringConverter, 052 org.tquadrat.foundation.util.stringconverter.ByteStringConverter, 053 org.tquadrat.foundation.util.stringconverter.DoubleStringConverter, 054 org.tquadrat.foundation.util.stringconverter.FloatStringConverter, 055 org.tquadrat.foundation.util.stringconverter.IntegerStringConverter, 056 org.tquadrat.foundation.util.stringconverter.LongStringConverter, 057 org.tquadrat.foundation.util.stringconverter.ShortStringConverter 058{ 059 /*-----------*\ 060 ====** Constants **======================================================== 061 \*-----------*/ 062 /** 063 * The error message for a String argument to 064 * {@link #fromString(CharSequence)} 065 * that cannot be parsed to a proper number value: {@value}. 066 */ 067 public static final String MSG_InvalidNumberFormat = "'%1$s' cannot be parsed as a valid number"; 068 069 /*------------*\ 070 ====** Attributes **======================================================= 071 \*------------*/ 072 /** 073 * The subject classes for this converter. 074 * 075 * @serial 076 */ 077 private final Collection<Class<?>> m_SubjectClasses; 078 079 /*------------------------*\ 080 ====** Static Initialisations **=========================================== 081 \*------------------------*/ 082 /** 083 * The serial version UID for objects of this class: {@value}. 084 * 085 * @hidden 086 */ 087 @Serial 088 private static final long serialVersionUID = 1L; 089 090 /*--------------*\ 091 ====** Constructors **===================================================== 092 \*--------------*/ 093 /** 094 * Creates a new instance of {@code NumberStringConverter}. 095 * 096 * @param subjectClasses The subject classes. 097 */ 098 protected NumberStringConverter( final Class<?>... subjectClasses ) 099 { 100 m_SubjectClasses = List.of( subjectClasses ); 101 } // NumberStringConverter() 102 103 /*---------*\ 104 ====** Methods **========================================================== 105 \*---------*/ 106 /** 107 * Parses the given String to a number. The String is not {@code null}, 108 * not empty, and it will not contain blanks only. Leading or trailing 109 * blanks have been cut off. 110 * 111 * @param value The String to parse. 112 * @return The number. 113 * @throws NumberFormatException The given value cannot be parsed to a 114 * number. 115 */ 116 protected abstract T parseNumber( String value ) throws NumberFormatException; 117 118 /** 119 * {@inheritDoc} 120 */ 121 @Override 122 public final T fromString( final CharSequence source ) throws IllegalArgumentException 123 { 124 T retValue = null; 125 if( nonNull( source ) ) 126 { 127 if( isEmptyOrBlank( source ) ) 128 { 129 throw new IllegalArgumentException( format( MSG_InvalidNumberFormat, source ) ); 130 } 131 try 132 { 133 retValue = parseNumber( source.toString().trim() ); 134 } 135 catch( final NumberFormatException e ) 136 { 137 throw new IllegalArgumentException( format( MSG_InvalidNumberFormat, source ), e ); 138 } 139 } 140 141 //---* Done *---------------------------------------------------------- 142 return retValue; 143 } // fromString() 144 145 /** 146 * Provides the subject class for this converter. 147 * 148 * @return The subject class. 149 */ 150 @SuppressWarnings( "PublicMethodNotExposedInInterface" ) 151 public final Collection<Class<?>> getSubjectClass() { return m_SubjectClasses; } 152} 153// class NumberStringConverter 154 155/* 156 * End of File 157 */