All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.mybatis.scripting.thymeleaf.PropertyAccessor Maven / Gradle / Ivy

The newest version!
/*
 *    Copyright 2018-2022 the original author or authors.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *       https://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
package org.mybatis.scripting.thymeleaf;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * The interface for accessing a property. 
* If you want to customize a default {@code PropertyAccessor}, you implements class of this interface and you need to * specify to a {@link SqlGenerator}.
* * @author Kazuki Shimizu * * @version 1.0.2 */ public interface PropertyAccessor { /** * Get property names of specified type. * * @param type * a target type * * @return property names */ Set getPropertyNames(Class type); /** * Get a property type of specified property. * * @param type * a target type * @param name * a property name * * @return a property type */ Class getPropertyType(Class type, String name); /** * Get a property value from specified target object. * * @param target * a target object * @param name * a property name * * @return a property value */ Object getPropertyValue(Object target, String name); /** * Set a property value to the specified target object. * * @param target * a target object * @param name * a property name * @param value * a property value */ void setPropertyValue(Object target, String name, Object value); /** * The built-in property accessors. */ enum BuiltIn implements PropertyAccessor { /** * The implementation using Java Beans API provided by JDK. */ STANDARD(new StandardPropertyAccessor()); private final PropertyAccessor delegate; BuiltIn(PropertyAccessor delegate) { this.delegate = delegate; } /** * {@inheritDoc} */ @Override public Set getPropertyNames(Class type) { return delegate.getPropertyNames(type); } /** * {@inheritDoc} */ @Override public Class getPropertyType(Class type, String name) { return delegate.getPropertyType(type, name); } /** * {@inheritDoc} */ @Override public Object getPropertyValue(Object target, String name) { return delegate.getPropertyValue(target, name); } /** * {@inheritDoc} */ @Override public void setPropertyValue(Object target, String name, Object value) { delegate.setPropertyValue(target, name, value); } static class StandardPropertyAccessor implements PropertyAccessor { private static Map, Map> cache = new ConcurrentHashMap<>(); /** * {@inheritDoc} */ @Override public Set getPropertyNames(Class type) { return getPropertyDescriptors(type).keySet(); } /** * {@inheritDoc} */ @Override public Class getPropertyType(Class type, String name) { return Optional.ofNullable(getPropertyDescriptors(type).get(name)) .orElseThrow(() -> new IllegalArgumentException(String.format( "Does not get a property type because property '%s' not found on '%s' class.", name, type.getName()))) .getPropertyType(); } /** * {@inheritDoc} */ @Override public Object getPropertyValue(Object target, String name) { try { return Optional.ofNullable(getPropertyDescriptors(target.getClass()).get(name)) .map(PropertyDescriptor::getReadMethod) .orElseThrow(() -> new IllegalArgumentException( String.format("Does not get a property value because property '%s' not found on '%s' class.", name, target.getClass().getName()))) .invoke(target); } catch (IllegalAccessException | InvocationTargetException e) { throw new IllegalStateException(e); } } /** * {@inheritDoc} */ @Override public void setPropertyValue(Object target, String name, Object value) { try { Optional.ofNullable(getPropertyDescriptors(target.getClass()).get(name)) .map(PropertyDescriptor::getWriteMethod) .orElseThrow(() -> new IllegalArgumentException( String.format("Does not set a property value because property '%s' not found on '%s' class.", name, target.getClass().getName()))) .invoke(target, value); } catch (IllegalAccessException | InvocationTargetException e) { throw new IllegalStateException(e); } } /** * Clear cache. *

* This method use by internal processing. *

*/ static void clearCache() { cache.clear(); } private static Map getPropertyDescriptors(Class type) { return cache.computeIfAbsent(type, key -> { try { BeanInfo beanInfo = Introspector.getBeanInfo(type); return Stream.of(beanInfo.getPropertyDescriptors()).filter(x -> !x.getName().equals("class")) .collect(Collectors.toMap(PropertyDescriptor::getName, v -> v)); } catch (IntrospectionException e) { throw new IllegalStateException(e); } finally { Introspector.flushFromCaches(type); } }); } } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy