001/* 002 * ============================================================================ 003 * Copyright © 2002-2023 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.util.stringconverter; 020 021import static java.lang.String.format; 022import static org.apiguardian.api.API.Status.STABLE; 023import static org.tquadrat.foundation.lang.Objects.isNull; 024import static org.tquadrat.foundation.lang.Objects.nonNull; 025import static org.tquadrat.foundation.util.StringUtils.isEmptyOrBlank; 026 027import java.io.Serial; 028import java.net.MalformedURLException; 029import java.net.URI; 030import java.net.URISyntaxException; 031import java.net.URL; 032import java.util.Collection; 033import java.util.List; 034 035import org.apiguardian.api.API; 036import org.tquadrat.foundation.annotation.ClassVersion; 037import org.tquadrat.foundation.exception.ValidationException; 038import org.tquadrat.foundation.lang.StringConverter; 039 040/** 041 * <p>{@summary An implementation of 042 * {@link StringConverter} 043 * for 044 * {@link URL} 045 * values.}</p> 046 * <p>The method 047 * {@link #fromString(CharSequence)} 048 * will use the constructor 049 * {@link URI#URI(String)} 050 * and then 051 * {@link URI#toURL()} 052 * to create a {@code URL} instance from the given value. It requires that the 053 * URL is absolute.</p> 054 * <p>Generally, when dealing with relative URLs, URIs should be used 055 * instead.</p> 056 * 057 * @extauthor Thomas Thrien - thomas.thrien@tquadrat.org 058 * @version $Id: URLStringConverter.java 1157 2025-12-31 14:05:44Z tquadrat $ 059 * @since 0.0.6 060 * 061 * @UMLGraph.link 062 */ 063@ClassVersion( sourceVersion = "$Id: URLStringConverter.java 1157 2025-12-31 14:05:44Z tquadrat $" ) 064@API( status = STABLE, since = "0.0.6" ) 065public sealed class URLStringConverter implements StringConverter<URL> 066 permits EncodedURLStringConverter 067{ 068 /*-----------*\ 069 ====** Constants **======================================================== 070 \*-----------*/ 071 /** 072 * The error message for an invalid URL: {@value}. 073 */ 074 public static final String MSG_InvalidURL = "'%1$s' cannot be parsed as a valid URL"; 075 076 /*------------------------*\ 077 ====** Static Initialisations **=========================================== 078 \*------------------------*/ 079 /** 080 * The serial version UID for objects of this class: {@value}. 081 * 082 * @hidden 083 */ 084 @Serial 085 private static final long serialVersionUID = 1L; 086 087 /** 088 * An instance of this class. 089 */ 090 public static final URLStringConverter INSTANCE = new URLStringConverter(); 091 092 /*--------------*\ 093 ====** Constructors **===================================================== 094 \*--------------*/ 095 /** 096 * Creates a new instance of {@code URLStringConverter}. 097 */ 098 public URLStringConverter() {} 099 100 /*---------*\ 101 ====** Methods **========================================================== 102 \*---------*/ 103 /** 104 * {@inheritDoc} 105 */ 106 @Override 107 public URL fromString( final CharSequence source ) throws IllegalArgumentException 108 { 109 URL retValue = null; 110 if( nonNull( source ) ) 111 { 112 try 113 { 114 if( isEmptyOrBlank( source ) ) throw new ValidationException( "URL is blank or empty" ); 115 final var uri = new URI( source.toString() ); 116 retValue = uri.toURL(); 117 } 118 catch( final MalformedURLException | URISyntaxException | ValidationException e ) 119 { 120 throw new IllegalArgumentException( format( MSG_InvalidURL, source ), e ); 121 } 122 } 123 124 //---* Done *---------------------------------------------------------- 125 return retValue; 126 } // fromString() 127 128 /** 129 * Provides the subject class for this converter. 130 * 131 * @return The subject class. 132 */ 133 @SuppressWarnings( "PublicMethodNotExposedInInterface" ) 134 public final Collection<Class<?>> getSubjectClass() { return List.of( URL.class ); } 135 136 /** 137 * This method is used by the 138 * {@link java.util.ServiceLoader} 139 * to obtain the instance for this 140 * {@link org.tquadrat.foundation.lang.StringConverter} 141 * implementation. 142 * 143 * @return The instance for this {@code StringConverter} implementation. 144 */ 145 public static final URLStringConverter provider() { return INSTANCE; } 146 147 /** 148 * {@inheritDoc} 149 */ 150 @Override 151 public String toString( final URL source ) 152 { 153 final var retValue = isNull( source ) ? null : source.toExternalForm(); 154 155 //---* Done *---------------------------------------------------------- 156 return retValue; 157 } // toString() 158} 159// class URLStringConverter 160 161/* 162 * End of File 163 */