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.config.cli; 019 020import static java.lang.Boolean.FALSE; 021import static java.util.Locale.ROOT; 022import static org.apiguardian.api.API.Status.STABLE; 023import static org.tquadrat.foundation.util.StringUtils.isNotEmptyOrBlank; 024 025import java.util.Collection; 026import java.util.HashMap; 027import java.util.HashSet; 028import java.util.Locale; 029import java.util.Map; 030import java.util.Set; 031import java.util.function.BiConsumer; 032 033import org.apiguardian.api.API; 034import org.tquadrat.foundation.annotation.ClassVersion; 035import org.tquadrat.foundation.config.spi.CLIDefinition; 036import org.tquadrat.foundation.lang.StringConverter; 037 038/** 039 * An implementation of 040 * {@link CmdLineValueHandler} 041 * for {@code boolean} and 042 * {@link Boolean} 043 * values that does accept also "yes", "qui", 044 * "ja", "sí", "sì", "да", 045 * "sim", "tak" and more as {@code true}. Still any other 046 * phrase and {@code null} are taken as {@code false}. 047 * 048 * @extauthor Thomas Thrien - thomas.thrien@tquadrat.org 049 * @version $Id: YesNoValueHandler.java 1078 2023-10-19 14:39:47Z tquadrat $ 050 * @since 0.0.1 051 * 052 * @UMLGraph.link 053 */ 054@ClassVersion( sourceVersion = "$Id: YesNoValueHandler.java 1078 2023-10-19 14:39:47Z tquadrat $" ) 055@API( status = STABLE, since = "0.0.1" ) 056public final class YesNoValueHandler extends SimpleCmdLineValueHandler<Boolean> 057{ 058 /*---------------*\ 059 ====** Inner Classes **==================================================== 060 \*---------------*/ 061 /** 062 * <p>{@summary An implementation of 063 * {@link StringConverter} 064 * that translates 'yes' in various languages into {@code true}.}</p> 065 * <p>'yes', 'true' and 'ok' will always be taken as {@code true}, the 066 * other variants only when valid for the current locale/language.</p> 067 * 068 * @see Locale#getDefault() 069 * 070 * @author Thomas Thrien - thomas.thrien@tquadrat.org 071 * @version $Id: YesNoValueHandler.java 1078 2023-10-19 14:39:47Z tquadrat $ 072 * @since 0.0.1 073 * 074 * @UMLGraph.link 075 */ 076 @ClassVersion( sourceVersion = "$Id: YesNoValueHandler.java 1078 2023-10-19 14:39:47Z tquadrat $" ) 077 @API( status = STABLE, since = "0.0.1" ) 078 private static final class YesNoStringConverter implements StringConverter<Boolean> 079 { 080 /*------------------------*\ 081 ====** Static Initialisations **======================================= 082 \*------------------------*/ 083 /** 084 * The one and only instance for this 085 * {@link StringConverter}. 086 */ 087 public static final YesNoStringConverter INSTANCE; 088 089 /** 090 * The various forms of 'yes'. 091 */ 092 @SuppressWarnings( "StaticCollection" ) 093 public static final Map<Locale,Set<String>> YES; 094 095 static 096 { 097 final Map<Locale,Set<String>> yes = new HashMap<>(); 098 099 yes.put( ROOT, Set.of( "ok", "true", "yes" ) ); 100 yes.put( Locale.of( "ar" ), Set.of( "naʿam", "نعم" ) ); 101 yes.put( Locale.of( "cs" ), Set.of( "ano" ) ); 102 yes.put( Locale.of( "el" ), Set.of( "ne", "ναι" ) ); 103 yes.put( Locale.of( "es" ), Set.of( "sí" ) ); 104 yes.put( Locale.of( "et" ), Set.of( "jah" ) ); 105 yes.put( Locale.of( "fa" ), Set.of( "baleh", "بله" ) ); 106 yes.put( Locale.of( "fi" ), Set.of( "kyllä" ) ); 107 yes.put( Locale.of( "fr" ), Set.of( "oui" ) ); 108 yes.put( Locale.of( "he" ), Set.of( "ken", "כֵּן", "כן" ) ); 109 yes.put( Locale.of( "hi" ), Set.of( "hā̃ ", "हाँ", "jī", "जी", "jī hā̃ ", "जी हाँ" ) ); 110 yes.put( Locale.of( "hu" ), Set.of( "igen" ) ); 111 yes.put( Locale.of( "id" ), Set.of( "ya" ) ); 112 yes.put( Locale.of( "is" ), Set.of( "já" ) ); 113 yes.put( Locale.of( "it" ), Set.of( "sì" ) ); 114 yes.put( Locale.of( "jp" ), Set.of( "hai", "はい", "ee", "ええ", "un", "うん" ) ); 115 yes.put( Locale.of( "ko" ), Set.of( "ne", "네" ) ); 116 yes.put( Locale.of( "ku" ), Set.of( "are" ) ); 117 yes.put( Locale.of( "lt" ), Set.of( "taip" ) ); 118 yes.put( Locale.of( "pl" ), Set.of( "tak" ) ); 119 yes.put( Locale.of( "pt" ), Set.of( "sim" ) ); 120 yes.put( Locale.of( "sq" ), Set.of( "po" ) ); 121 yes.put( Locale.of( "sw" ), Set.of( "ndiyo", "naam" ) ); 122 yes.put( Locale.of( "ta" ), Set.of( "ām", "ஆம்", "āmām", "ஆமாம்", "ōm", "ஓம்" ) ); 123 yes.put( Locale.of( "tg" ), Set.of( "bale", "бале", "ore", "оре" ) ); 124 yes.put( Locale.of( "tr" ), Set.of( "evet" ) ); 125 yes.put( Locale.of( "uk" ), Set.of( "tak", "так" ) ); 126 127 var set = Set.of( "ja" ); 128 yes.put( Locale.of( "af" ), set ); 129 yes.put( Locale.of( "da" ), set ); 130 yes.put( Locale.of( "de" ), set ); 131 yes.put( Locale.of( "no" ), set ); 132 yes.put( Locale.of( "sv" ), set ); 133 134 set = Set.of( "da", "да" ); 135 yes.put( Locale.of( "bg" ), set ); 136 yes.put( Locale.of( "hr" ), set ); 137 yes.put( Locale.of( "mk" ), set ); 138 yes.put( Locale.of( "ro" ), set ); 139 yes.put( Locale.of( "ru" ), set ); 140 yes.put( Locale.of( "sh" ), set ); 141 yes.put( Locale.of( "sl" ), set ); 142 yes.put( Locale.of( "sr" ), set ); 143 144 YES = Map.copyOf( yes ); 145 146 INSTANCE = new YesNoStringConverter(); 147 } 148 149 /*--------------*\ 150 ====** Constructors **================================================= 151 \*--------------*/ 152 /** 153 * Creates a new instance of {@code YesNoValueStringConverter}. 154 */ 155 public YesNoStringConverter() { super(); } 156 157 /*---------*\ 158 ====** Methods **====================================================== 159 \*---------*/ 160 /** 161 * {@inheritDoc} 162 */ 163 @Override 164 public Boolean fromString( final CharSequence source ) throws IllegalArgumentException 165 { 166 var retValue = FALSE; 167 if( isNotEmptyOrBlank( source ) ) 168 { 169 final Collection<String> yes = new HashSet<>( YES.get( ROOT ) ); 170 final var language = Locale.of( Locale.getDefault().getLanguage() ); 171 if( YES.containsKey( language ) ) yes.addAll( YES.get( language ) ); 172 retValue = Boolean.valueOf( yes.contains( source.toString().toLowerCase( Locale.getDefault() ) ) ); 173 } 174 175 //---* Done *------------------------------------------------------ 176 return retValue; 177 } // fromString() 178 } 179 // class YesNoStringConverter 180 181 /*--------------*\ 182 ====** Constructors **===================================================== 183 \*--------------*/ 184 /** 185 * Creates a new {@code YesNoValueHandler} instance. 186 * 187 * @param context The CLI definition that provides the context for this 188 * value handler. 189 * @param valueSetter The function that places the translated value to 190 * the property. 191 */ 192 public YesNoValueHandler( final CLIDefinition context, final BiConsumer<String,Boolean> valueSetter ) 193 { 194 //---* Daddy will do the null check *---------------------------------- 195 super( context, valueSetter, YesNoStringConverter.INSTANCE ); 196 } // YesNoValueHandler() 197 198 /** 199 * Creates a new {@code YesNoValueHandler} instance. 200 * 201 * @param valueSetter The function that places the translated value to 202 * the property. 203 */ 204 public YesNoValueHandler( final BiConsumer<String,Boolean> valueSetter ) 205 { 206 //---* Daddy will do the null check *---------------------------------- 207 super( valueSetter, YesNoStringConverter.INSTANCE ); 208 } // YesNoValueHandler() 209} 210// class YesNoValueHandler 211 212/* 213 * End of File 214 */