001/*
002 * Configurate
003 * Copyright (C) zml and Configurate contributors
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * 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.spongepowered.configurate.objectmapping.guice;
018
019import com.google.inject.ConfigurationException;
020import com.google.inject.Injector;
021import com.google.inject.Key;
022import com.google.inject.Provider;
023import org.spongepowered.configurate.objectmapping.FieldDiscoverer;
024import org.spongepowered.configurate.objectmapping.ObjectMapper;
025import org.spongepowered.configurate.serialize.SerializationException;
026
027import javax.inject.Inject;
028import javax.inject.Singleton;
029
030/**
031 * A factory for {@link ObjectMapper}s that will inherit the injector from
032 * wherever it is provided.
033 *
034 * <p>This class is intended to be constructed through Guice
035 * dependency injection.</p>
036 *
037 * @since 4.0.0
038 */
039@Singleton
040public final class GuiceObjectMapperProvider {
041
042    private final ObjectMapper.Factory factory;
043
044    @Inject
045    GuiceObjectMapperProvider(final Injector baseInjector) {
046        this.factory = ObjectMapper.factoryBuilder()
047                .addDiscoverer(injectedObjectDiscoverer(baseInjector))
048                .build();
049    }
050
051    /**
052     * Get the default factory, with guice support added.
053     *
054     * @return the default guice factory
055     * @since 4.0.0
056     */
057    public ObjectMapper.Factory get() {
058        return this.factory;
059    }
060
061    /**
062     * Create a field discoverer that uses the provided injector.
063     *
064     * @param injector injector to create instances with
065     * @return new discoverer
066     * @since 4.0.0
067     */
068    public static FieldDiscoverer<?> injectedObjectDiscoverer(final Injector injector) {
069        return FieldDiscoverer.object(type -> {
070            try {
071                final Provider<?> prov = injector.getProvider(Key.get(type.getType()));
072                return prov::get;
073            } catch (final ConfigurationException ex) {
074                throw new SerializationException(type.getType(), "Cannot create instances", ex);
075            }
076        });
077    }
078
079    @Override
080    public String toString() {
081        return "GuiceObjectMapperFactory{}";
082    }
083
084}