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 ninja.leaping.configurate.objectmapping;
018
019import com.google.common.cache.CacheBuilder;
020import com.google.common.cache.CacheLoader;
021import com.google.common.cache.LoadingCache;
022import com.google.common.reflect.TypeToken;
023import org.checkerframework.checker.nullness.qual.NonNull;
024
025import java.util.concurrent.ExecutionException;
026
027import static java.util.Objects.requireNonNull;
028
029/**
030 * Factory for a basic {@link ObjectMapper}.
031 */
032public class DefaultObjectMapperFactory implements ObjectMapperFactory {
033    private static final ObjectMapperFactory INSTANCE = new DefaultObjectMapperFactory();
034
035    @NonNull
036    public static ObjectMapperFactory getInstance() {
037        return INSTANCE;
038    }
039
040    private final LoadingCache<TypeToken<?>, ObjectMapper<?>> mapperCache = CacheBuilder.newBuilder()
041            .weakKeys()
042            .maximumSize(500)
043            .build(new CacheLoader<TypeToken<?>, ObjectMapper<?>>() {
044                @Override
045                public ObjectMapper<?> load(TypeToken<?> key) throws Exception {
046                    return new ObjectMapper<>(key);
047                }
048            });
049
050    @Override
051    public @NonNull <T> ObjectMapper<T> getMapper(@NonNull Class<T> type) throws ObjectMappingException {
052        return getMapper(TypeToken.of(type));
053    }
054
055    @NonNull
056    @Override
057    @SuppressWarnings("unchecked")
058    public <T> ObjectMapper<T> getMapper(@NonNull TypeToken<T> type) throws ObjectMappingException {
059        requireNonNull(type, "type");
060        try {
061            return (ObjectMapper<T>) mapperCache.get(type);
062        } catch (ExecutionException e) {
063            if (e.getCause() instanceof ObjectMappingException) {
064                throw (ObjectMappingException) e.getCause();
065            } else {
066                throw new ObjectMappingException(e);
067            }
068        }
069    }
070
071    @Override
072    public String toString() {
073        return "DefaultObjectMapperFactory{}";
074    }
075}