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 com.google.inject.Injector; 024import org.checkerframework.checker.nullness.qual.NonNull; 025 026import javax.inject.Inject; 027import javax.inject.Singleton; 028import java.util.concurrent.ExecutionException; 029 030import static java.util.Objects.requireNonNull; 031 032/** 033 * A factory for {@link ObjectMapper}s that will inherit the injector from wherever it is provided. 034 * 035 * <p>This class is intended to be constructed through Guice dependency injection.</p> 036 */ 037@Singleton 038public final class GuiceObjectMapperFactory implements ObjectMapperFactory { 039 private final LoadingCache<TypeToken<?>, ObjectMapper<?>> cache = CacheBuilder.newBuilder() 040 .weakKeys().maximumSize(512) 041 .build(new CacheLoader<TypeToken<?>, ObjectMapper<?>>() { 042 @Override 043 public ObjectMapper<?> load(TypeToken<?> key) throws Exception { 044 return new GuiceObjectMapper<>(injector, key); 045 } 046 }); 047 048 private final Injector injector; 049 050 @Inject 051 protected GuiceObjectMapperFactory(Injector baseInjector) { 052 this.injector = baseInjector; 053 } 054 055 @Override 056 public @NonNull <T> ObjectMapper<T> getMapper(@NonNull Class<T> type) throws ObjectMappingException { 057 return getMapper(TypeToken.of(type)); 058 } 059 060 @NonNull 061 @Override 062 @SuppressWarnings("unchecked") 063 public <T> ObjectMapper<T> getMapper(@NonNull TypeToken<T> type) throws ObjectMappingException { 064 requireNonNull(type, "type"); 065 try { 066 return (ObjectMapper<T>) cache.get(type); 067 } catch (ExecutionException e) { 068 if (e.getCause() instanceof ObjectMappingException) { 069 throw (ObjectMappingException) e.getCause(); 070 } else { 071 throw new RuntimeException(e); 072 } 073 } 074 } 075 076 @Override 077 public String toString() { 078 return "GuiceObjectMapperFactory{}"; 079 } 080}