001/* 002 * ============================================================================ 003 * Copyright © 2002-2026 by Thomas Thrien. 004 * All Rights Reserved. 005 * ============================================================================ 006 * 007 * Licensed to the public under the agreements of the GNU Lesser General Public 008 * License, version 3.0 (the "License"). You may obtain a copy of the License at 009 * 010 * http://www.gnu.org/licenses/lgpl.html 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 014 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 015 * License for the specific language governing permissions and limitations 016 * under the License. 017 */ 018 019package org.tquadrat.foundation.lang.internal; 020 021import org.apiguardian.api.API; 022import org.tquadrat.foundation.annotation.ClassVersion; 023import org.tquadrat.foundation.annotation.MountPoint; 024import org.tquadrat.foundation.lang.StringConverter; 025 026import java.io.Serial; 027import java.util.Collection; 028import java.util.List; 029 030import static java.lang.String.format; 031import static java.util.Arrays.stream; 032import static org.apiguardian.api.API.Status.INTERNAL; 033import static org.tquadrat.foundation.lang.Objects.isNull; 034import static org.tquadrat.foundation.lang.Objects.nonNull; 035import static org.tquadrat.foundation.lang.Objects.requireNonNullArgument; 036 037/** 038 * <p>{@summary The default implementation of 039 * {@link StringConverter} 040 * for types that are derived from 041 * {@link Enum}.}</p> 042 * <p>The implementation of 043 * {@link #fromString(CharSequence)} 044 * provided here uses 045 * {@link Class#getEnumConstants()} 046 * to find the {@code enum} value:</p> 047 * <div class="source-container"><pre>… 048 * T result = stream( m_EnumType.getEnumConstants() ) 049 * .filter( constant -> value.equals( constant.name() ) ) 050 * .findFirst() 051 * .orElseThrow( () -> new IllegalArgumentException( … ); 052 * …</pre></div> 053 * <p>The implementation of 054 * {@link #toString(Enum)} 055 * in this class will return the value of 056 * {@link Enum#name()}.</p> 057 * 058 * @param <T> The concrete data type that is handled by this string converter 059 * implementation. 060 * 061 * @extauthor Thomas Thrien - thomas.thrien@tquadrat.org 062 * @version $Id: DefaultEnumStringConverter.java 1163 2026-03-20 15:28:33Z tquadrat $ 063 * @since 0.1.0 064 * 065 * @UMLGraph.link 066 */ 067@ClassVersion( sourceVersion = "$Id: DefaultEnumStringConverter.java 1163 2026-03-20 15:28:33Z tquadrat $" ) 068@API( status = INTERNAL, since = "0.1.0" ) 069public class DefaultEnumStringConverter<T extends Enum<T>> implements StringConverter<T> 070{ 071 /*-----------*\ 072 ====** Constants **======================================================== 073 \*-----------*/ 074 /** 075 * The error message for the name of an unknown class on the command line: 076 * {@value}. 077 */ 078 public static final String MSG_UnknownValue = "Unknown/invalid value: %1$s"; 079 080 /*------------*\ 081 ====** Attributes **======================================================= 082 \*------------*/ 083 /** 084 * The data type of the property to set. 085 * 086 * @serial 087 */ 088 private final Class<T> m_EnumType; 089 090 /*------------------------*\ 091 ====** Static Initialisations **=========================================== 092 \*------------------------*/ 093 /** 094 * The serial version UID for objects of this class: {@value}. 095 * 096 * @hidden 097 */ 098 @Serial 099 private static final long serialVersionUID = 1L; 100 101 /*--------------*\ 102 ====** Constructors **===================================================== 103 \*--------------*/ 104 /** 105 * Creates a new {@code EnumValueHandler} instance. 106 * 107 * @param enumType The data type for the property. 108 */ 109 public DefaultEnumStringConverter( final Class<T> enumType ) 110 { 111 m_EnumType = requireNonNullArgument( enumType, "enumType" ); 112 } // EnumValueHandler() 113 114 /*---------*\ 115 ====** Methods **========================================================== 116 \*---------*/ 117 /** 118 * {@inheritDoc} 119 */ 120 @MountPoint 121 @Override 122 public T fromString( final CharSequence source ) throws IllegalArgumentException 123 { 124 T retValue = null; 125 if( nonNull( source ) ) 126 { 127 if( source.isEmpty() ) throw new IllegalArgumentException( format( MSG_UnknownValue, source ) ); 128 retValue = stream( m_EnumType.getEnumConstants() ) 129 .filter( constant -> source.toString().equals( constant.name() ) ) 130 .findFirst() 131 .orElseThrow( () -> new IllegalArgumentException( format( MSG_UnknownValue, source ) ) ); 132 } 133 134 //---* Done *---------------------------------------------------------- 135 return retValue; 136 } // fromString() 137 138 /** 139 * Provides the subject class for this converter. 140 * 141 * @return The subject class. 142 */ 143 @SuppressWarnings( "PublicMethodNotExposedInInterface" ) 144 public final Collection<Class<T>> getSubjectClass() { return List.of( m_EnumType ); } 145 146 /** 147 * {@inheritDoc} 148 */ 149 @MountPoint 150 @Override 151 public String toString( final T source ) 152 { 153 final var retValue = isNull( source ) ? null : source.name(); 154 155 //---* Done *---------------------------------------------------------- 156 return retValue; 157 } // toString() 158} 159// class DefaultEnumStringConverter 160 161/* 162 * End of File 163 */