001/*
002 * JDrupes Json-B plugins
003 * Copyright (C) 2024 Michael N. Lipp
004 * 
005 * This program is free software: you can redistribute it and/or modify
006 * it under the terms of the GNU Affero General Public License as
007 * published by the Free Software Foundation, either version 3 of the
008 * License, or (at your option) any later version.
009 *
010 * This program is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
013 * GNU Affero General Public License for more details.
014 *
015 * You should have received a copy of the GNU Affero General Public License
016 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
017 */
018
019package org.jdrupes.jsonb.beans;
020
021import java.beans.BeanInfo;
022import java.beans.IntrospectionException;
023import java.beans.Introspector;
024import java.beans.PropertyEditor;
025import java.beans.PropertyEditorManager;
026import java.util.Collections;
027import java.util.Map;
028import java.util.WeakHashMap;
029
030/// Common base class for the JavaBean serializer and deserializer.
031public class JavaBeanConverter {
032
033    @SuppressWarnings({ "PMD.UseConcurrentHashMap",
034        "PMD.FieldNamingConventions", "PMD.VariableNamingConventions" })
035    private static final Map<Class<?>, PropertyEditor> propertyEditorCache
036        = Collections.synchronizedMap(new WeakHashMap<>());
037    @SuppressWarnings({ "PMD.UseConcurrentHashMap",
038        "PMD.FieldNamingConventions", "PMD.VariableNamingConventions" })
039    private static final Map<Class<?>, BeanInfo> beanInfoCache
040        = Collections.synchronizedMap(new WeakHashMap<>());
041
042    /// Find the property editor for the given class.
043    ///
044    /// @param cls the class
045    /// @return the property editor
046    protected static PropertyEditor findPropertyEditor(Class<?> cls) {
047        PropertyEditor propertyEditor = propertyEditorCache.get(cls);
048        if (propertyEditor == null && !propertyEditorCache.containsKey(cls)) {
049            // Never looked for before.
050            propertyEditor = PropertyEditorManager.findEditor(cls);
051            propertyEditorCache.put(cls, propertyEditor);
052        }
053        return propertyEditor;
054    }
055
056    /// Find the bean info for the given class.
057    ///
058    /// @param cls the class
059    /// @return the bean info
060    @SuppressWarnings("PMD.EmptyCatchBlock")
061    protected static BeanInfo findBeanInfo(Class<?> cls) {
062        BeanInfo beanInfo = beanInfoCache.get(cls);
063        if (beanInfo == null && !beanInfoCache.containsKey(cls)) {
064            try {
065                beanInfo = Introspector.getBeanInfo(cls, Object.class);
066            } catch (IntrospectionException e) {
067                // Bad luck
068            }
069            beanInfoCache.put(cls, beanInfo);
070        }
071        return beanInfo;
072    }
073
074    /// Create a new instance.
075    public JavaBeanConverter() {
076        // Can be instantiated.
077    }
078}