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.camel.spi;
018
019import java.lang.reflect.Method;
020import java.util.Map;
021import java.util.Set;
022
023import org.apache.camel.CamelContext;
024import org.apache.camel.LoggingLevel;
025import org.apache.camel.StaticService;
026import org.apache.camel.TypeConverter;
027import org.apache.camel.meta.Experimental;
028
029/**
030 * Used for introspecting beans properties via Java reflection; such as extracting current property values,
031 * or updating one or more properties etc.
032 *
033 * End users should favour using org.apache.camel.support.PropertyBindingSupport instead.
034 */
035@Experimental
036public interface BeanIntrospection extends StaticService {
037
038    /**
039     * Structure of an introspected class.
040     */
041    final class ClassInfo {
042        public Class<?> clazz;
043        public MethodInfo[] methods;
044    }
045
046    /**
047     * Structure of an introspected method.
048     */
049    final class MethodInfo {
050        public Method method;
051        public Boolean isGetter;
052        public Boolean isSetter;
053        public String getterOrSetterShorthandName;
054        public Boolean hasGetterAndSetter;
055    }
056
057    // Statistics
058    // ----------------------------------------------------
059
060    /**
061     * Number of times bean introspection has been invoked
062     */
063    long getInvokedCounter();
064
065    /**
066     * Reset the statistics counters.
067     */
068    void resetCounters();
069
070    /**
071     * Whether to gather extended statistics for introspection usage.
072     */
073    boolean isExtendedStatistics();
074
075    /**
076     * Whether to gather extended statistics for introspection usage.
077     */
078    void setExtendedStatistics(boolean extendedStatistics);
079
080    /**
081     * Logging level used for logging introspection usage. Is using TRACE level as default.
082     */
083    LoggingLevel getLoggingLevel();
084
085    /**
086     * Logging level used for logging introspection usage. Is using TRACE level as default.
087     */
088    void setLoggingLevel(LoggingLevel loggingLevel);
089
090    // Introspection
091    // ----------------------------------------------------
092
093    /**
094     * Will inspect the target for properties.
095     * <p/>
096     * Notice a property must have both a getter/setter method to be included.
097     * Notice all <tt>null</tt> values will be included.
098     *
099     * @param target         the target bean
100     * @param properties     the map to fill in found properties
101     * @param optionPrefix   an optional prefix to append the property key
102     * @return <tt>true</tt> if any properties was found, <tt>false</tt> otherwise.
103     */
104    boolean getProperties(Object target, Map<String, Object> properties, String optionPrefix);
105
106    /**
107     * Will inspect the target for properties.
108     * <p/>
109     * Notice a property must have both a getter/setter method to be included.
110     *
111     * @param target         the target bean
112     * @param properties     the map to fill in found properties
113     * @param optionPrefix   an optional prefix to append the property key
114     * @param includeNull    whether to include <tt>null</tt> values
115     * @return <tt>true</tt> if any properties was found, <tt>false</tt> otherwise.
116     */
117    boolean getProperties(Object target, Map<String, Object> properties, String optionPrefix, boolean includeNull);
118
119    /**
120     * Introspects the given class.
121     *
122     * @param clazz the class
123     * @return the introspection result as a {@link ClassInfo} structure.
124     */
125    ClassInfo cacheClass(Class<?> clazz);
126
127    /**
128     * Clears the introspection cache.
129     */
130    void clearCache();
131
132    /**
133     * Number of classes in the introspection cache.
134     */
135    long getCachedClassesCounter();
136
137    /**
138     * Gets the property or else returning the default value.
139     *
140     * @param target         the target bean
141     * @param propertyName   the property name
142     * @param defaultValue   the default value
143     * @param ignoreCase     whether to ignore case for matching the property name
144     * @return the property value, or the default value if the target does not have a property with the given name
145     */
146    Object getOrElseProperty(Object target, String propertyName, Object defaultValue, boolean ignoreCase);
147
148    /**
149     * Gets the getter method for the property.
150     *
151     * @param type            the target class
152     * @param propertyName    the property name
153     * @param ignoreCase      whether to ignore case for matching the property name
154     * @return                the getter method
155     * @throws NoSuchMethodException  is thrown if there are no getter method for the property
156     */
157    Method getPropertyGetter(Class<?> type, String propertyName, boolean ignoreCase) throws NoSuchMethodException;
158
159    /**
160     * This method supports three modes to set a property:
161     *
162     * 1. Setting a Map property where the property name refers to a map via name[aKey] where aKey is the map key to use.
163     *
164     * 2. Setting a property that has already been resolved, this is the case when {@code context} and {@code refName} are
165     * NULL and {@code value} is non-NULL.
166     *
167     * 3. Setting a property that has not yet been resolved, the property will be resolved based on the suitable methods
168     * found matching the property name on the {@code target} bean. For this mode to be triggered the parameters
169     * {@code context} and {@code refName} must NOT be NULL, and {@code value} MUST be NULL.
170     */
171    boolean setProperty(CamelContext context, Object target, String name, Object value) throws Exception;
172
173    /**
174     * This method supports three modes to set a property:
175     *
176     * 1. Setting a Map property where the property name refers to a map via name[aKey] where aKey is the map key to use.
177     *
178     * 2. Setting a property that has already been resolved, this is the case when {@code context} and {@code refName} are
179     * NULL and {@code value} is non-NULL.
180     *
181     * 3. Setting a property that has not yet been resolved, the property will be resolved based on the suitable methods
182     * found matching the property name on the {@code target} bean. For this mode to be triggered the parameters
183     * {@code context} and {@code refName} must NOT be NULL, and {@code value} MUST be NULL.
184     */
185    boolean setProperty(CamelContext context, TypeConverter typeConverter, Object target, String name, Object value, String refName,
186                                      boolean allowBuilderPattern, boolean allowPrivateSetter, boolean ignoreCase) throws Exception;
187
188    /**
189     * Find all the setter methods on the class
190     */
191    Set<Method> findSetterMethods(Class<?> clazz, String name, boolean allowBuilderPattern, boolean allowPrivateSetter, boolean ignoreCase);
192
193}