package com.kryptnostic.rhizome.configuration.service; import java.io.IOException; import javax.annotation.Nullable; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.dataloom.mappers.ObjectMappers; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.Module; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.base.Preconditions; import com.google.common.eventbus.AsyncEventBus; import com.kryptnostic.rhizome.configuration.ConfigurationKey; /** * Abstract class for loading YAML format configuration classes that handles low level resource reading, validation, and * update publishing. * * @author Matthew Tamayo-Rios */ // TODO: Add hibernate validation public abstract class AbstractYamlConfigurationService implements ConfigurationService { protected ObjectMapper mapper = ObjectMappers.getYamlMapper(); protected final Logger logger = LoggerFactory.getLogger( getClass() ); protected final AsyncEventBus configurationEvents; public AbstractYamlConfigurationService( AsyncEventBus configurationEvents ) { this.configurationEvents = configurationEvents; } @Override public <T> T getConfiguration( Class<T> clazz ) throws IOException { Preconditions.checkNotNull( clazz, "Requested configuration class cannot be null." ); ConfigurationKey key = ConfigurationService.StaticLoader.getConfigurationKey( clazz ); Preconditions.checkState( key != null && StringUtils.isNotBlank( key.getUri() ), "Configuration id for class " + clazz.getName() + " cannot be blank or null" ); try { return mapper.readValue( Preconditions.checkNotNull( fetchConfiguration( key ), "Configuration cannot be null" ), clazz ); } catch ( JsonParseException | JsonMappingException e ) { logger.error( "Invalid YAML configuration file for class {}", clazz.getName(), e ); return null; } } @Override public <T> void setConfiguration( T configuration ) { ConfigurationKey key = ConfigurationService.StaticLoader.getConfigurationKey( configuration.getClass() ); try { persistConfiguration( key, mapper.writeValueAsString( configuration ) ); post( configuration ); } catch ( IOException e ) { logger.error( "Failed to persist configuration {}", configuration, e ); } } protected synchronized void setObjectMapper( ObjectMapper mapper ) { this.mapper = mapper; } @Override public void registerModule( Module module ) { mapper.registerModule( module ); } @Override public void subscribe( Object subscriber ) { configurationEvents.register( subscriber ); } protected void post( Object configuration ) { configurationEvents.post( configuration ); } protected abstract @Nullable String fetchConfiguration( ConfigurationKey key ); protected abstract void persistConfiguration( ConfigurationKey key, String configurationYaml ); }