001package ball.databind;
002/*-
003 * ##########################################################################
004 * Data Binding Utilities
005 * $Id: AbstractObjectMapperConfiguration.java 5285 2020-02-05 04:23:21Z ball $
006 * $HeadURL: svn+ssh://svn.hcf.dev/var/spool/scm/repository.svn/ball-databind/trunk/src/main/java/ball/databind/AbstractObjectMapperConfiguration.java $
007 * %%
008 * Copyright (C) 2016 - 2020 Allen D. Ball
009 * %%
010 * Licensed under the Apache License, Version 2.0 (the "License");
011 * you may not use this file except in compliance with the License.
012 * You may obtain a copy of the License at
013 *
014 *      http://www.apache.org/licenses/LICENSE-2.0
015 *
016 * Unless required by applicable law or agreed to in writing, software
017 * distributed under the License is distributed on an "AS IS" BASIS,
018 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
019 * See the License for the specific language governing permissions and
020 * limitations under the License.
021 * ##########################################################################
022 */
023import ball.util.EnumLookupMap;
024import ball.util.PropertiesImpl;
025import com.fasterxml.jackson.databind.ObjectMapper;
026import java.io.InputStream;
027import java.util.SortedMap;
028
029import static java.util.Collections.unmodifiableSortedMap;
030
031/**
032 * Abstract base class for {@link ObjectMapper} configurations.  The typical
033 * implementation is a trivial subclass combined with a corresponding
034 * {@link java.util.Properties} file.
035 *
036 * @author {@link.uri mailto:ball@hcf.dev Allen D. Ball}
037 * @version $Revision: 5285 $
038 */
039public abstract class AbstractObjectMapperConfiguration
040                      extends PropertiesImpl {
041    private static final long serialVersionUID = 3380012687021883148L;
042
043    /**
044     * Features supported by this configuration.
045     */
046    public static enum Feature {
047        /**
048         * If set and {@code true}, calls
049         * {@link ObjectMapper#registerModules(Iterable)} with the return
050         * value of {@link ObjectMapper#findModules(ClassLoader)}.
051         */
052        REGISTER_MODULES;
053
054        private static final SortedMap<String,Enum<?>> MAP =
055            unmodifiableSortedMap(new EnumLookupMap(Feature.class));
056    }
057
058    /**
059     * Sole constructor.
060     */
061    protected AbstractObjectMapperConfiguration() {
062        super();
063
064        String name = getClass().getSimpleName() + ".properties";
065
066        try (InputStream in = getClass().getResourceAsStream(name)) {
067            if (in != null) {
068                load(in);
069            }
070        } catch (Exception exception) {
071            throw new ExceptionInInitializerError(exception);
072        }
073    }
074
075    /**
076     * Method to configure an {@link ObjectMapper}.
077     *
078     * @param   mapper          The {@link ObjectMapper} to configure.
079     *
080     * @return  The {@link ObjectMapper}.
081     */
082    public ObjectMapper configure(ObjectMapper mapper) {
083        for (String name : stringPropertyNames()) {
084            if (ObjectMapperFeature.MAP.containsKey(name)) {
085                ObjectMapperFeature
086                    .configure(mapper,
087                               ObjectMapperFeature.MAP.get(name),
088                               Boolean.valueOf(getProperty(name)));
089            }
090        }
091
092        for (String name : stringPropertyNames()) {
093            if (Feature.MAP.containsKey(name)) {
094                switch ((Feature) Feature.MAP.get(name)) {
095                case REGISTER_MODULES:
096                    ClassLoader loader = getClass().getClassLoader();
097
098                    mapper.registerModules(ObjectMapper.findModules(loader));
099                    break;
100
101                default:
102                    break;
103                }
104            }
105        }
106
107        return mapper;
108    }
109
110    /**
111     * Method to return a new, configured {@link ObjectMapper}.
112     *
113     * @return  The {@link ObjectMapper}.
114     */
115    public ObjectMapper newObjectMapper() {
116        return configure(new ObjectMapper());
117    }
118}