001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 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, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.juneau.commons.settings; 018 019import static org.apache.juneau.commons.utils.AssertionUtils.*; 020import static org.apache.juneau.commons.utils.Utils.*; 021 022import java.io.*; 023import java.net.*; 024import java.nio.charset.*; 025import java.nio.file.*; 026import java.util.*; 027import java.util.function.*; 028 029/** 030 * A specialized {@link Setting} for string values that provides convenience methods for type conversion. 031 * 032 * <p> 033 * This class extends {@link Setting} with type-specific conversion methods such as {@link #asInteger()}, 034 * {@link #asBoolean()}, {@link #asCharset()}, etc. 035 */ 036public class StringSetting extends Setting<String> { 037 038 /** 039 * Creates a new StringSetting from a Settings instance and a Supplier. 040 * 041 * @param settings The Settings instance that created this setting. Must not be <jk>null</jk>. 042 * @param supplier The supplier that provides the string value. Must not be <jk>null</jk>. 043 */ 044 public StringSetting(Settings settings, Supplier<String> supplier) { 045 super(settings, supplier); 046 } 047 048 /** 049 * If a value is present, applies the provided mapping function to it and returns a StringSetting describing the result. 050 * 051 * <p> 052 * This method is specifically for String-to-String mappings. For mappings to other types, use the inherited {@link #map(Function)} method. 053 * 054 * <p> 055 * The returned StringSetting maintains its own cache, independent of this supplier. 056 * Resetting the mapped supplier does not affect this supplier, and vice versa. 057 * 058 * @param mapper A mapping function to apply to the value, if present. Must not be <jk>null</jk>. 059 * @return A StringSetting describing the result of applying a mapping function to the value of this StringSetting, if a value is present, otherwise an empty StringSetting. 060 */ 061 public StringSetting mapString(Function<? super String, ? extends String> mapper) { 062 assertArgNotNull("mapper", mapper); 063 return new StringSetting(getSettings(), () -> { 064 String value = get(); 065 return nn(value) ? mapper.apply(value) : null; 066 }); 067 } 068 069 /** 070 * If a value is present, and the value matches the given predicate, returns a StringSetting describing the value, otherwise returns an empty StringSetting. 071 * 072 * <p> 073 * The returned StringSetting maintains its own cache, independent of this supplier. 074 * Resetting the filtered supplier does not affect this supplier, and vice versa. 075 * 076 * @param predicate A predicate to apply to the value, if present. Must not be <jk>null</jk>. 077 * @return A StringSetting describing the value of this StringSetting if a value is present and the value matches the given predicate, otherwise an empty StringSetting. 078 */ 079 @Override 080 public StringSetting filter(Predicate<? super String> predicate) { 081 assertArgNotNull("predicate", predicate); 082 return new StringSetting(getSettings(), () -> { 083 String value = get(); 084 return (nn(value) && predicate.test(value)) ? value : null; 085 }); 086 } 087 088 /** 089 * Converts the string value to an Integer. 090 * 091 * <p> 092 * The property value is parsed using {@link Integer#valueOf(String)}. If the property is not found 093 * or cannot be parsed as an integer, returns {@link Optional#empty()}. 094 * 095 * @return The property value as an Integer, or {@link Optional#empty()} if not found or not a valid integer. 096 */ 097 public Setting<Integer> asInteger() { 098 return map(v -> safeOrNull(() -> Integer.valueOf(v))).filter(Objects::nonNull); 099 } 100 101 /** 102 * Converts the string value to a Long. 103 * 104 * <p> 105 * The property value is parsed using {@link Long#valueOf(String)}. If the property is not found 106 * or cannot be parsed as a long, returns {@link Optional#empty()}. 107 * 108 * @return The property value as a Long, or {@link Optional#empty()} if not found or not a valid long. 109 */ 110 public Setting<Long> asLong() { 111 return map(v -> safeOrNull(() -> Long.valueOf(v))).filter(Objects::nonNull); 112 } 113 114 /** 115 * Converts the string value to a Boolean. 116 * 117 * <p> 118 * The property value is parsed using {@link Boolean#parseBoolean(String)}, which returns <c>true</c> 119 * if the value is (case-insensitive) "true", otherwise <c>false</c>. Note that this method will 120 * return <c>Optional.of(false)</c> for any non-empty value that is not "true", and 121 * {@link Optional#empty()} only if the property is not set. 122 * 123 * @return The property value as a Boolean, or {@link Optional#empty()} if not found. 124 */ 125 public Setting<Boolean> asBoolean() { 126 return map(v -> Boolean.parseBoolean(v)); 127 } 128 129 /** 130 * Converts the string value to a Double. 131 * 132 * <p> 133 * The property value is parsed using {@link Double#valueOf(String)}. If the property is not found 134 * or cannot be parsed as a double, returns {@link Optional#empty()}. 135 * 136 * @return The property value as a Double, or {@link Optional#empty()} if not found or not a valid double. 137 */ 138 public Setting<Double> asDouble() { 139 return map(v -> safeOrNull(() -> Double.valueOf(v))).filter(Objects::nonNull); 140 } 141 142 /** 143 * Converts the string value to a Float. 144 * 145 * <p> 146 * The property value is parsed using {@link Float#valueOf(String)}. If the property is not found 147 * or cannot be parsed as a float, returns {@link Optional#empty()}. 148 * 149 * @return The property value as a Float, or {@link Optional#empty()} if not found or not a valid float. 150 */ 151 public Setting<Float> asFloat() { 152 return map(v -> safeOrNull(() -> Float.valueOf(v))).filter(Objects::nonNull); 153 } 154 155 /** 156 * Converts the string value to a File. 157 * 158 * <p> 159 * The property value is converted to a {@link File} using the {@link File#File(String)} constructor. 160 * If the property is not found, returns {@link Optional#empty()}. Note that this method does not 161 * validate that the file path is valid or that the file exists. 162 * 163 * @return The property value as a File, or {@link Optional#empty()} if not found. 164 */ 165 public Setting<File> asFile() { 166 return map(v -> new File(v)); 167 } 168 169 /** 170 * Converts the string value to a Path. 171 * 172 * <p> 173 * The property value is converted to a {@link Path} using {@link Paths#get(String, String...)}. 174 * If the property is not found or the path string is invalid, returns {@link Optional#empty()}. 175 * 176 * @return The property value as a Path, or {@link Optional#empty()} if not found or not a valid path. 177 */ 178 public Setting<Path> asPath() { 179 return map(v -> safeOrNull(() -> Paths.get(v))).filter(Objects::nonNull); 180 } 181 182 /** 183 * Converts the string value to a URI. 184 * 185 * <p> 186 * The property value is converted to a {@link URI} using {@link URI#create(String)}. 187 * If the property is not found or the URI string is invalid, returns {@link Optional#empty()}. 188 * 189 * @return The property value as a URI, or {@link Optional#empty()} if not found or not a valid URI. 190 */ 191 public Setting<URI> asURI() { 192 return map(v -> safeOrNull(() -> URI.create(v))).filter(Objects::nonNull); 193 } 194 195 /** 196 * Converts the string value to a Charset. 197 * 198 * <p> 199 * The property value is converted to a {@link Charset} using {@link Charset#forName(String)}. 200 * If the property is not found or the charset name is not supported, returns {@link Optional#empty()}. 201 * 202 * @return The property value as a Charset, or {@link Optional#empty()} if not found or not a valid charset. 203 */ 204 public Setting<Charset> asCharset() { 205 return map(v -> safeOrNull(() -> Charset.forName(v))).filter(Objects::nonNull); 206 } 207 208 /** 209 * Converts the string value to the specified type using the Settings type conversion functions. 210 * 211 * <p> 212 * The property value is converted using {@link Settings#toType(String, Class)}. If the property is not found 213 * or cannot be converted to the specified type, returns {@link Optional#empty()}. 214 * 215 * @param <T> The target type. 216 * @param c The target class. Must not be <jk>null</jk>. 217 * @return The property value as the specified type, or {@link Optional#empty()} if not found or not a valid conversion. 218 */ 219 public <T> Setting<T> asType(Class<T> c) { 220 assertArgNotNull("c", c); 221 return map(v -> getSettings().toType(v, c)).filter(Objects::nonNull); 222 } 223}