001/* 002 * JDrupes Builder 003 * Copyright (C) 2025 Michael N. Lipp 004 * 005 * This program is free software: you can redistribute it and/or modify 006 * it under the terms of the GNU Affero General Public License as 007 * published by the Free Software Foundation, either version 3 of the 008 * License, or (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 013 * GNU Affero General Public License for more details. 014 * 015 * You should have received a copy of the GNU Affero General Public License 016 * along with this program. If not, see <https://www.gnu.org/licenses/>. 017 */ 018 019package org.jdrupes.builder.api; 020 021import java.util.function.Supplier; 022 023/// Defines a named parameter. Java doesn't have named parameters, but 024/// this comes pretty close. Define the named parameters that you need 025/// as static members of your class: 026/// 027/// public static NamedParameter<String> name(String name) { 028/// return new NamedParameter<>("name", name); 029/// } 030/// 031/// Defines the method that is to be invoked with named parameters as 032/// 033/// public void method(NamedParameter<?>... params) { 034/// var name = NamedParameter.<String> get(params, "name", null); 035/// } 036/// 037/// And invoke it with: 038/// 039/// method(name("test")); 040/// 041/// Of course, this requires a static import for `name`. If you have several 042/// classes using the pattern, you'll have to use `className.paramName(...)` 043/// to provide the value for the parameter which is, admittedly less elegant. 044/// 045/// A possible workaround is to define a hierarchy of classes with 046/// [NamedParameter] as base class and put commonly used names in the base 047/// classes. 048/// 049/// @param <T> the generic type 050/// @param name the name 051/// @param value the value 052/// 053public record NamedParameter<T>(String name, T value) { 054 055 /// Looks up the named parameter with the given `name` in array 056 /// of [NamedParameter]s. If it isn't found, return the result 057 /// from invoking the supplier (or `null`). 058 /// 059 /// @param <T> the generic type 060 /// @param parameters the parameters 061 /// @param name the name 062 /// @param fallback supplier for a fallback value or `null` 063 /// @return the value 064 /// 065 @SuppressWarnings("unchecked") 066 public static <T> T get(NamedParameter<?>[] parameters, String name, 067 Supplier<T> fallback) { 068 for (var param : parameters) { 069 if (param.name.equals(name)) { 070 return (T) param.value; 071 } 072 } 073 if (fallback != null) { 074 return fallback.get(); 075 } 076 return null; 077 } 078}