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.*;
020
021/**
022 * Abstract interface for Bean-Centric Test (BCT) object conversion and property access.
023 *
024 * <p>This interface defines the core contract for converting objects to strings and lists,
025 * and for accessing object properties in a uniform way. It forms the foundation of the BCT
026 * testing framework, enabling consistent object introspection and value extraction across
027 * different object types and structures.</p>
028 *
029 * <h5 class='section'>Core Conversion Operations:</h5>
030 * <dl>
031 *    <dt><b>{@link #stringify(Object)}</b></dt>
032 *    <dd>Converts any object to its string representation, handling nested structures</dd>
033 *
034 *    <dt><b>{@link #listify(Object)}</b></dt>
035 *    <dd>Converts collection-like objects (arrays, Collections, Iterables, etc.) to List&lt;Object&gt;</dd>
036 *
037 *    <dt><b>{@link #swap(Object)}</b></dt>
038 *    <dd>Pre-processes objects before conversion (e.g., unwrapping Optional, calling Supplier)</dd>
039 *
040 *    <dt><b>{@link #getProperty(Object, String)}</b></dt>
041 *    <dd>Accesses object properties using multiple fallback mechanisms</dd>
042 * </dl>
043 *
044 * <h5 class='section'>Property Access Strategy:</h5>
045 * <p>The {@link #getProperty(Object, String)} method uses a comprehensive fallback approach:</p>
046 *
047 * <h5 class='section'>Usage in BCT Framework:</h5>
048 * <p>This interface is used internally by BCT assertion methods like:</p>
049 * <ul>
050 *    <li>{@link BctAssertions#assertBean(Object, String, String)}</li>
051 *    <li>{@link BctAssertions#assertMapped(Object, java.util.function.BiFunction, String, String)}</li>
052 *    <li>{@link BctAssertions#assertList(List, Object...)}</li>
053 *    <li>{@link BctAssertions#assertBeans(Collection, String, String...)}</li>
054 * </ul>
055 *
056 * @see BasicBeanConverter
057 * @see BctAssertions
058 */
059public interface BeanConverter {
060
061   /**
062    * Determines if an object can be converted to a list.
063    *
064    * @param o The object to test. May be null.
065    * @return True if the object can be listified, false if null or cannot be listified
066    */
067   boolean canListify(Object o);
068
069   /**
070    * Extracts a nested property value using structured field access syntax.
071    *
072    * @param o The object to extract nested properties from. May be null.
073    * @param token The parsed token containing the property access structure. Must not be null.
074    * @return A formatted string representation of the extracted nested values
075    * @throws IllegalArgumentException if the token is null
076    */
077   String getNested(Object o, NestedTokenizer.Token token);
078
079   /**
080    * Accesses a named property or field from an object.
081    *
082    * @param object The object to access properties from
083    * @param name The property/field name to access
084    * @return The property value
085    * @throws RuntimeException if the property cannot be found or accessed
086    */
087   Object getProperty(Object object, String name);
088
089   /**
090    * Retrieves a configuration setting value with a fallback default.
091    *
092    * @param <T> The type of the setting value
093    * @param key The setting key to retrieve
094    * @param defaultValue The value to return if the setting is not found
095    * @return The setting value if found, otherwise the default value
096    */
097   <T> T getSetting(String key, T defaultValue);
098
099   /**
100    * Converts a collection-like object to a standardized List&lt;Object&gt; format.
101    *
102    * @param o The object to convert to a list. Must not be null.
103    * @return A List containing the elements
104    * @throws IllegalArgumentException if the object is null or cannot be converted to a list
105    */
106   List<Object> listify(Object o);
107
108   /**
109    * Computes the size of an object.
110    *
111    * <p>
112    * This method determines the size of collection-like objects for test assertions.
113    * The size is computed based on registered {@link Sizer} implementations, with
114    * built-in support for collections, maps, arrays, and strings.
115    *
116    * @param o The object to compute the size of. Must not be <jk>null</jk>.
117    * @return The size of the object.
118    * @throws IllegalArgumentException if the object's size cannot be determined.
119    */
120   int size(Object o);
121
122   /**
123    * Converts an object to its string representation for testing purposes.
124    *
125    * @param o The object to stringify
126    * @return The string representation of the object
127    */
128   String stringify(Object o);
129
130   /**
131    * Pre-processes objects before conversion operations.
132    *
133    * @param o The object to swap
134    * @return The swapped object, or the original object if no swapping is needed
135    */
136   Object swap(Object o);
137}