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.junit.bct;
018
019import java.util.function.*;
020
021/**
022 * Functional interface for converting objects of a specific type to their string representation.
023 *
024 * <p>Stringifiers provide custom string conversion logic for specific object types within the
025 * Bean-Centric Testing framework. They enable precise control over how objects are displayed
026 * in test assertions and error messages, going beyond simple {@code toString()} calls.</p>
027 *
028 * <h5 class='section'>Usage Examples:</h5>
029 * <p class='bjava'>
030 *    <jc>// Simple custom format</jc>
031 *    Stringifier&lt;LocalDate&gt; <jv>dateStringifier</jv> = (<jp>conv</jp>, <jp>date</jp>) -&gt;
032 *       <jp>date</jp>.format(DateTimeFormatter.<jsf>ISO_LOCAL_DATE</jsf>);
033 *
034 *    <jc>// Complex nested object formatting</jc>
035 *    Stringifier&lt;Person&gt; <jv>personStringifier</jv> = (<jp>conv</jp>, <jp>person</jp>) -&gt;
036 *       <jp>person</jp>.getName() + <js>" ("</js> + <jp>conv</jp>.stringify(<jp>person</jp>.getAddress()) + <js>")"</js>;
037 *
038 *    <jc>// Conditional formatting</jc>
039 *    Stringifier&lt;Order&gt; <jv>orderStringifier</jv> = (<jp>conv</jp>, <jp>order</jp>) -&gt; {
040 *       <jk>var</jk> <jv>status</jv> = <jp>order</jp>.getStatus();
041 *       <jk>return</jk> <jv>status</jv> == OrderStatus.<jsf>COMPLETED</jsf> ?
042 *          <js>"Order #"</js> + <jp>order</jp>.getId() + <js>" [DONE]"</js> :
043 *          <js>"Order #"</js> + <jp>order</jp>.getId() + <js>" ["</js> + <jv>status</jv> + <js>"]"</js>;
044 *    };
045 * </p>
046 *
047 * <h5 class='section'>Registration:</h5>
048 * <p class='bjava'>
049 *    <jk>var</jk> <jv>converter</jv> = BasicBeanConverter.<jsm>builder</jsm>()
050 *       .defaultSettings()
051 *       .addStringifier(LocalDate.<jk>class</jk>, <jv>dateStringifier</jv>)
052 *       .addStringifier(Person.<jk>class</jk>, <jv>personStringifier</jv>)
053 *       .addStringifier(Order.<jk>class</jk>, <jv>orderStringifier</jv>)
054 *       .build();
055 * </p>
056 *
057 * <h5 class='section'>Best Practices:</h5>
058 * <ul>
059 *    <li><b>Use the converter parameter</b> for recursive conversion of nested objects</li>
060 *    <li><b>Keep output concise</b> but informative for test readability</li>
061 *    <li><b>Handle edge cases</b> gracefully (empty collections, special values)</li>
062 *    <li><b>Consider test context</b> - focus on properties relevant to testing</li>
063 * </ul>
064 *
065 * @param <T> The type of object this stringifier handles
066 * @see BasicBeanConverter.Builder#addStringifier(Class, Stringifier)
067 * @see BeanConverter#stringify(Object)
068 */
069@FunctionalInterface
070public interface Stringifier<T> extends BiFunction<BeanConverter,T,String> {}