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.Utils.*; 020 021import java.util.*; 022import java.util.function.*; 023 024/** 025 * A functional interface for creating read-only {@link SettingSource} instances from a function. 026 * 027 * <p> 028 * This functional interface allows you to create setting sources directly from lambda expressions or method references, 029 * making it easy to wrap existing property sources (e.g., {@link System#getProperty(String)}, 030 * {@link System#getenv(String)}) as {@link SettingSource} instances. 031 * 032 * <p> 033 * Functional sources are read-only and do not implement {@link SettingStore}. If you need a writable source, 034 * use {@link MapStore} or {@link FunctionalStore} instead. 035 * 036 * <h5 class='section'>Return Value Semantics:</h5> 037 * <ul class='spaced-list'> 038 * <li>If the function returns <c>null</c>, this source returns <c>null</c> (key doesn't exist). 039 * <li>If the function returns a non-null value, this source returns <c>Optional.of(value)</c>. 040 * </ul> 041 * 042 * <p> 043 * Note: This source cannot distinguish between a key that doesn't exist and a key that exists with a null value, 044 * since the function only returns a <c>String</c>. If you need to distinguish these cases, use {@link MapStore} instead. 045 * 046 * <h5 class='section'>Example:</h5> 047 * <p class='bjava'> 048 * <jc>// Create a read-only source directly from a lambda (returns Optional)</jc> 049 * Settings.<jsf>get</jsf>().addSource(name -> opt(System.getProperty(name))); 050 * 051 * <jc>// Using the static factory method (takes Function<String, String>)</jc> 052 * Settings.<jsf>get</jsf>().addSource(FunctionalSource.<jsf>of</jsf>(System::getProperty)); 053 * 054 * <jc>// Create a read-only source from System.getenv</jc> 055 * Settings.<jsf>get</jsf>().addSource(FunctionalSource.<jsf>of</jsf>(System::getenv)); 056 * 057 * <jc>// Explicit creation for reuse</jc> 058 * FunctionalSource <jv>sysProps</jv> = FunctionalSource.<jsf>of</jsf>(System::getProperty); 059 * Settings.<jsf>get</jsf>().addSource(<jv>sysProps</jv>); 060 * </p> 061 */ 062@FunctionalInterface 063public interface FunctionalSource extends SettingSource { 064 065 /** 066 * Returns a setting by applying the function. 067 * 068 * <p> 069 * If the function returns <c>null</c>, this method returns <c>null</c> (indicating the key doesn't exist). 070 * If the function returns a non-null value, this method returns <c>Optional.of(value)</c>. 071 * 072 * @param name The property name. 073 * @return The property value, or <c>null</c> if the function returns <c>null</c>. 074 */ 075 @Override 076 Optional<String> get(String name); 077 078 /** 079 * Creates a functional source from a function that returns a string. 080 * 081 * <p> 082 * This is a convenience factory method for creating functional sources from functions that return 083 * <c>String</c> values. The function's return value is converted to an <c>Optional</c> as follows: 084 * <ul> 085 * <li>If the function returns <c>null</c>, the source returns <c>null</c> (key doesn't exist). 086 * <li>If the function returns a non-null value, the source returns <c>Optional.of(value)</c>. 087 * </ul> 088 * 089 * <h5 class='section'>Example:</h5> 090 * <p class='bjava'> 091 * <jc>// Create from a lambda</jc> 092 * FunctionalSource <jv>source1</jv> = FunctionalSource.<jsf>of</jsf>(name -> System.getProperty(name)); 093 * 094 * <jc>// Create from a method reference</jc> 095 * FunctionalSource <jv>source2</jv> = FunctionalSource.<jsf>of</jsf>(System::getProperty); 096 * </p> 097 * 098 * @param function The function to delegate property lookups to. Must not be <c>null</c>. 099 * @return A new functional source instance. 100 */ 101 static FunctionalSource of(Function<String, String> function) { 102 return name -> { 103 var v = function.apply(name); 104 return v == null ? null : opt(v); 105 }; 106 } 107}