001/* 002 * Configurate 003 * Copyright (C) zml and Configurate contributors 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * 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 ninja.leaping.configurate; 018 019import org.checkerframework.checker.nullness.qual.Nullable; 020 021/** 022 * Contains functions useful for performing configuration type conversions. 023 * 024 * <p>The naming scheme is as follows:</p> 025 * 026 * <ul> 027 * <li><code>as</code> methods attempt to convert the data passed to the appropriate type</li> 028 * <li><code>strictAs</code> methods will only return values if the input value is already of an appropriate type</li> 029 * </ul> 030 */ 031public final class Types { 032 private Types() {} 033 034 /** 035 * Attempts to convert <code>value</code> to a {@link String}. 036 * 037 * <p>Returns null if <code>value</code> is null, and the {@link Object#toString()} 038 * representation of <code>value</code> otherwise.</p> 039 * 040 * @param value The value 041 * @return <code>value</code> as a {@link String}, or null 042 * @see Object#toString() 043 */ 044 @Nullable 045 public static String asString(@Nullable Object value) { 046 return value == null ? null : value.toString(); 047 } 048 049 /** 050 * Returns <code>value</code> if it is a {@link String}. 051 * 052 * @param value The value 053 * @return <code>value</code> as a {@link String}, or null 054 */ 055 @Nullable 056 public static String strictAsString(@Nullable Object value) { 057 return value instanceof String ? (String) value : null; 058 } 059 060 /** 061 * Attempts to convert <code>value</code> to a {@link Float}. 062 * 063 * <p>Returns null if <code>value</code> is null.</p> 064 * 065 * <p>This method will attempt to cast <code>value</code> to {@link Float}, or 066 * {@link Float#parseFloat(String) parse} the <code>value</code> if it is a {@link String}.</p> 067 * 068 * @param value The value 069 * @return <code>value</code> as a {@link Float}, or null 070 */ 071 @Nullable 072 public static Float asFloat(@Nullable Object value) { 073 if (value == null) { 074 return null; 075 } 076 077 if (value instanceof Float) { 078 return (Float) value; 079 } else if (value instanceof Integer) { 080 return ((Number) value).floatValue(); 081 } 082 083 try { 084 return Float.parseFloat(value.toString()); 085 } catch (IllegalArgumentException ex) { 086 return null; 087 } 088 } 089 090 /** 091 * Returns <code>value</code> if it is a {@link Float}. 092 * 093 * @param value The value 094 * @return <code>value</code> as a {@link Float}, or null 095 */ 096 @Nullable 097 public static Float strictAsFloat(@Nullable Object value) { 098 if (value == null) { 099 return null; 100 } 101 102 if (value instanceof Float 103 || value instanceof Integer) { 104 return ((Number) value).floatValue(); 105 } 106 107 return null; 108 } 109 110 /** 111 * Attempts to convert <code>value</code> to a {@link Double}. 112 * 113 * <p>Returns null if <code>value</code> is null.</p> 114 * 115 * <p>This method will attempt to cast <code>value</code> to {@link Double}, or 116 * {@link Double#parseDouble(String) parse} the <code>value</code> if it is a {@link String}.</p> 117 * 118 * @param value The value 119 * @return <code>value</code> as a {@link Float}, or null 120 */ 121 @Nullable 122 public static Double asDouble(@Nullable Object value) { 123 if (value == null) { 124 return null; 125 } 126 127 if (value instanceof Double) { 128 return (Double) value; 129 } else if (value instanceof Integer 130 || value instanceof Long 131 || value instanceof Float) { 132 return ((Number) value).doubleValue(); 133 } 134 135 try { 136 return Double.parseDouble(value.toString()); 137 } catch (IllegalArgumentException ex) { 138 return null; 139 } 140 } 141 142 /** 143 * Returns <code>value</code> if it is a {@link Double}. 144 * 145 * @param value The value 146 * @return <code>value</code> as a {@link Double}, or null 147 */ 148 @Nullable 149 public static Double strictAsDouble(@Nullable Object value) { 150 if (value == null) { 151 return null; 152 } 153 154 if (value instanceof Double 155 || value instanceof Float 156 || value instanceof Integer 157 || value instanceof Long) { 158 return ((Number) value).doubleValue(); 159 } 160 161 return null; 162 } 163 164 /** 165 * Attempts to convert <code>value</code> to a {@link Integer}. 166 * 167 * <p>Returns null if <code>value</code> is null.</p> 168 * 169 * <p>This method will attempt to cast <code>value</code> to {@link Integer}, or 170 * {@link Integer#parseInt(String) parse} the <code>value</code> if it is a {@link String}.</p> 171 * 172 * @param value The value 173 * @return <code>value</code> as a {@link Float}, or null 174 */ 175 @Nullable 176 public static Integer asInt(@Nullable Object value) { 177 if (value == null) { 178 return null; 179 } 180 181 if (value instanceof Integer) { 182 return (Integer) value; 183 } 184 185 if (value instanceof Float 186 || value instanceof Double) { 187 double val = ((Number) value).doubleValue(); 188 if (val == Math.floor(val)) { 189 return (int) val; 190 } 191 } 192 193 try { 194 return Integer.parseInt(value.toString()); 195 } catch (IllegalArgumentException ex) { 196 return null; 197 } 198 } 199 200 /** 201 * Returns <code>value</code> if it is a {@link Integer}. 202 * 203 * @param value The value 204 * @return <code>value</code> as a {@link Integer}, or null 205 */ 206 @Nullable 207 public static Integer strictAsInt(@Nullable Object value) { 208 if (value == null) { 209 return null; 210 } 211 212 return value instanceof Integer ? (Integer) value : null; 213 } 214 215 /** 216 * Attempts to convert <code>value</code> to a {@link Long}. 217 * 218 * <p>Returns null if <code>value</code> is null.</p> 219 * 220 * <p>This method will attempt to cast <code>value</code> to {@link Long}, or 221 * {@link Long#parseLong(String) parse} the <code>value</code> if it is a {@link String}.</p> 222 * 223 * @param value The value 224 * @return <code>value</code> as a {@link Float}, or null 225 */ 226 @Nullable 227 public static Long asLong(@Nullable Object value) { 228 if (value == null) { 229 return null; 230 } 231 232 if (value instanceof Long) { 233 return (Long) value; 234 } else if (value instanceof Integer) { 235 return ((Number) value).longValue(); 236 } 237 238 if (value instanceof Float 239 || value instanceof Double) { 240 double val = ((Number) value).doubleValue(); 241 if (val == Math.floor(val)) { 242 return (long) val; 243 } 244 } 245 246 try { 247 return Long.parseLong(value.toString()); 248 } catch (IllegalArgumentException ex) { 249 return null; 250 } 251 } 252 253 /** 254 * Returns <code>value</code> if it is a {@link Long}. 255 * 256 * @param value The value 257 * @return <code>value</code> as a {@link Long}, or null 258 */ 259 @Nullable 260 public static Long strictAsLong(@Nullable Object value) { 261 if (value == null) { 262 return null; 263 } 264 265 if (value instanceof Long) { 266 return (Long) value; 267 } else if (value instanceof Integer) { 268 return ((Number) value).longValue(); 269 } 270 271 return null; 272 } 273 274 /** 275 * Attempts to convert <code>value</code> to a {@link Boolean}. 276 * 277 * <ul> 278 * <li>If <code>value</code> is a {@link Boolean}, casts and returns</li> 279 * <li>If <code>value</code> is a {@link Number}, returns true if value is not 0</li> 280 * <li>If <code>value.toString()</code> returns true, t, yes, y, or 1, returns true</li> 281 * <li>If <code>value.toString()</code> returns false, f, no, n, or 0, returns false</li> 282 * <li>Otherwise returns null</li> 283 * </ul> 284 * 285 * @param value The value 286 * @return <code>value</code> as a {@link Boolean}, or null 287 */ 288 @Nullable 289 public static Boolean asBoolean(@Nullable Object value) { 290 if (value == null) { 291 return null; 292 } 293 294 if (value instanceof Boolean) { 295 return (Boolean) value; 296 } 297 298 if (value instanceof Number) { 299 return !value.equals(0); 300 } 301 302 final String potential = value.toString(); 303 if (potential.equals("true") 304 || potential.equals("t") 305 || potential.equals("yes") 306 || potential.equals("y") 307 || potential.equals("1")) { 308 return true; 309 } else if (potential.equals("false") 310 || potential.equals("f") 311 || potential.equals("no") 312 || potential.equals("n") 313 || potential.equals("0")) { 314 return false; 315 } 316 317 return null; 318 } 319 320 /** 321 * Returns <code>value</code> if it is a {@link Boolean}. 322 * 323 * @param value The value 324 * @return <code>value</code> as a {@link Boolean}, or null 325 */ 326 @Nullable 327 public static Boolean strictAsBoolean(@Nullable Object value) { 328 if (value == null) { 329 return null; 330 } 331 332 return value instanceof Boolean ? (Boolean) value : null; 333 } 334}