![JAR search and dependency download from the Maven repository](/logo.png)
com.yahoo.elide.standalone.config.ElideStandaloneSettings Maven / Gradle / Ivy
Show all versions of elide-standalone Show documentation
/*
* Copyright 2017, Yahoo Inc.
* Licensed under the Apache License, Version 2.0
* See LICENSE file in project root for terms.
*/
package com.yahoo.elide.standalone.config;
import static com.yahoo.elide.datastores.jpa.JpaDataStore.DEFAULT_LOGGER;
import com.yahoo.elide.ElideSettings;
import com.yahoo.elide.ElideSettings.ElideSettingsBuilder;
import com.yahoo.elide.Serdes;
import com.yahoo.elide.Serdes.SerdesBuilder;
import com.yahoo.elide.async.AsyncSettings;
import com.yahoo.elide.async.AsyncSettings.AsyncSettingsBuilder;
import com.yahoo.elide.async.models.AsyncQuery;
import com.yahoo.elide.async.models.TableExport;
import com.yahoo.elide.core.audit.AuditLogger;
import com.yahoo.elide.core.audit.Slf4jLogger;
import com.yahoo.elide.core.datastore.DataStore;
import com.yahoo.elide.core.dictionary.EntityDictionary;
import com.yahoo.elide.core.dictionary.Injector;
import com.yahoo.elide.core.exceptions.ExceptionLogger;
import com.yahoo.elide.core.exceptions.ExceptionMappers;
import com.yahoo.elide.core.exceptions.Slf4jExceptionLogger;
import com.yahoo.elide.core.filter.dialect.RSQLFilterDialect;
import com.yahoo.elide.core.request.Pagination;
import com.yahoo.elide.core.request.route.RouteResolver;
import com.yahoo.elide.core.security.checks.Check;
import com.yahoo.elide.core.security.checks.prefab.Role;
import com.yahoo.elide.core.security.obfuscation.IdObfuscator;
import com.yahoo.elide.core.type.ClassType;
import com.yahoo.elide.core.type.Type;
import com.yahoo.elide.core.utils.ClassScanner;
import com.yahoo.elide.core.utils.DefaultClassScanner;
import com.yahoo.elide.core.utils.coerce.CoerceUtil;
import com.yahoo.elide.datastores.aggregation.AggregationDataStore;
import com.yahoo.elide.datastores.aggregation.DefaultQueryValidator;
import com.yahoo.elide.datastores.aggregation.QueryEngine;
import com.yahoo.elide.datastores.aggregation.cache.Cache;
import com.yahoo.elide.datastores.aggregation.cache.CaffeineCache;
import com.yahoo.elide.datastores.aggregation.core.Slf4jQueryLogger;
import com.yahoo.elide.datastores.aggregation.metadata.MetaDataStore;
import com.yahoo.elide.datastores.aggregation.query.DefaultQueryPlanMerger;
import com.yahoo.elide.datastores.aggregation.queryengines.sql.ConnectionDetails;
import com.yahoo.elide.datastores.aggregation.queryengines.sql.DataSourceConfiguration;
import com.yahoo.elide.datastores.aggregation.queryengines.sql.SQLQueryEngine;
import com.yahoo.elide.datastores.aggregation.queryengines.sql.dialects.SQLDialectFactory;
import com.yahoo.elide.datastores.aggregation.queryengines.sql.query.AggregateBeforeJoinOptimizer;
import com.yahoo.elide.datastores.aggregation.validator.TemplateConfigValidator;
import com.yahoo.elide.datastores.jpa.JpaDataStore;
import com.yahoo.elide.datastores.jpa.transaction.NonJtaTransaction;
import com.yahoo.elide.datastores.multiplex.MultiplexManager;
import com.yahoo.elide.graphql.DefaultGraphQLErrorMapper;
import com.yahoo.elide.graphql.DefaultGraphQLExceptionHandler;
import com.yahoo.elide.graphql.GraphQLErrorMapper;
import com.yahoo.elide.graphql.GraphQLExceptionHandler;
import com.yahoo.elide.graphql.GraphQLSettings.GraphQLSettingsBuilder;
import com.yahoo.elide.jsonapi.DefaultJsonApiErrorMapper;
import com.yahoo.elide.jsonapi.DefaultJsonApiExceptionHandler;
import com.yahoo.elide.jsonapi.JsonApiErrorMapper;
import com.yahoo.elide.jsonapi.JsonApiExceptionHandler;
import com.yahoo.elide.jsonapi.JsonApiMapper;
import com.yahoo.elide.jsonapi.JsonApiSettings.JsonApiSettingsBuilder;
import com.yahoo.elide.modelconfig.DBPasswordExtractor;
import com.yahoo.elide.modelconfig.DynamicConfiguration;
import com.yahoo.elide.modelconfig.store.ConfigDataStore;
import com.yahoo.elide.modelconfig.store.models.ConfigChecks;
import com.yahoo.elide.modelconfig.validator.DynamicConfigValidator;
import com.yahoo.elide.swagger.OpenApiBuilder;
import com.yahoo.elide.swagger.resources.ApiDocsEndpoint;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.jetty.ee10.servlet.ServletContextHandler;
import org.glassfish.hk2.api.ServiceLocator;
import org.glassfish.jersey.server.ResourceConfig;
import org.hibernate.Session;
import graphql.execution.DataFetcherExceptionHandler;
import graphql.execution.SimpleDataFetcherExceptionHandler;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.SpecVersion;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.servers.Server;
import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityManagerFactory;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Properties;
import java.util.Set;
import java.util.TimeZone;
import java.util.function.Consumer;
import java.util.function.Function;
/**
* Interface for configuring an ElideStandalone application.
*/
public interface ElideStandaloneSettings {
public static final ObjectMapper DEFAULT_OBJECT_MAPPER = new ObjectMapper();
/**
* The OpenAPI Specification Version.
*/
public enum OpenApiVersion {
OPENAPI_3_0("3.0"),
OPENAPI_3_1("3.1");
private final String value;
OpenApiVersion(String value) {
this.value = value;
}
public String getValue() {
return this.value;
}
public static OpenApiVersion from(String version) {
if (version.startsWith(OPENAPI_3_1.getValue())) {
return OPENAPI_3_1;
} else if (version.startsWith(OPENAPI_3_0.getValue())) {
return OPENAPI_3_0;
}
throw new IllegalArgumentException("Invalid OpenAPI version. Only versions 3.0 and 3.1 are supported.");
}
}
/* Elide settings */
public final Consumer TXCANCEL = em -> em.unwrap(Session.class).cancelQuery();
/**
* A map containing check mappings for security across Elide. If not provided, then an empty map is used.
* In case of an empty map, checks can be referenced by their fully qualified class names.
*
* @return Check mappings.
*/
default Map> getCheckMappings() {
return Collections.emptyMap();
}
/**
* A Set containing Types to be excluded from EntityDictionary's EntityBinding.
* @return Set of Types.
*/
default Set> getEntitiesToExclude() {
Set> entitiesToExclude = new HashSet<>();
ElideStandaloneAsyncSettings asyncProperties = getAsyncProperties();
if (asyncProperties == null || !asyncProperties.enabled()) {
entitiesToExclude.add(ClassType.of(AsyncQuery.class));
}
if (asyncProperties == null || !asyncProperties.enableExport()) {
entitiesToExclude.add(ClassType.of(TableExport.class));
}
return entitiesToExclude;
}
/**
* Override this to customize the {@link JsonApiSettingsBuilder}.
*
* @param dictionary the dictionary
* @param mapper the mapper
* @return the JsonApiSettingsBuilder
*/
default JsonApiSettingsBuilder getJsonApiSettingsBuilder(EntityDictionary dictionary, JsonApiMapper mapper) {
return JsonApiSettingsBuilder.withDefaults(dictionary)
.path(getJsonApiPathSpec().replace("/*", ""))
.joinFilterDialect(RSQLFilterDialect.builder().dictionary(dictionary).build())
.subqueryFilterDialect(RSQLFilterDialect.builder().dictionary(dictionary).build())
.jsonApiMapper(mapper)
.jsonApiExceptionHandler(getJsonApiExceptionHandler());
}
/**
* Override this to customize the {@link GraphQLSettingsBuilder}.
*
* @param dictionary the dictionary
* @return the GraphQLSettingsBuilder
*/
default GraphQLSettingsBuilder getGraphQLSettingsBuilder(EntityDictionary dictionary) {
return GraphQLSettingsBuilder.withDefaults(dictionary)
.path(getGraphQLApiPathSpec().replace("/*", ""))
.graphqlExceptionHandler(getGraphQLExceptionHandler());
}
/**
* Override this to customize the {@link AsyncSettingsBuilder}.
*
* @return the AsyncSettingsBuilder
*/
default AsyncSettingsBuilder getAsyncSettingsBuilder() {
return AsyncSettings.builder().export(export -> export
.enabled(getAsyncProperties().enableExport())
.path(getAsyncProperties().getExportApiPathSpec().replace("/*", "")));
}
/**
* Override this to customize the {@link ElideSettingsBuilder}.
*
* The following example only customizes the {@link ElideSettingsBuilder#maxPageSize}.
*
*
* public ElideSettingsBuilder getElideSettingsBuilder(EntityDictionary dictionary, DataStore dataStore,
* JsonApiMapper mapper) {
* return ElideStandaloneSettings.super.getElideSettingsBuilder(dictionary, dataStore, mapper)
* .maxPageSize(1000);
* }
*
*
* @param dictionary the dictionary
* @param dataStore the data store
* @param mapper the mapper
* @return the ElideSettingsBuilder
*
* @see #getJsonApiSettingsBuilder(EntityDictionary, JsonApiMapper)
* @see #getGraphQLSettingsBuilder(EntityDictionary)
* @see #getAsyncSettingsBuilder()
*/
default ElideSettingsBuilder getElideSettingsBuilder(EntityDictionary dictionary, DataStore dataStore,
JsonApiMapper mapper) {
ElideSettingsBuilder builder = ElideSettings.builder().dataStore(dataStore)
.entityDictionary(dictionary)
.baseUrl(getBaseUrl())
.objectMapper(mapper.getObjectMapper())
.auditLogger(getAuditLogger())
.maxPageSize(getMaxPageSize())
.defaultPageSize(getDefaultPageSize());
if (verboseErrors()) {
builder.verboseErrors(true);
}
if (enableJsonApi()) {
builder.settings(getJsonApiSettingsBuilder(dictionary, mapper));
}
if (enableGraphQL()) {
builder.settings(getGraphQLSettingsBuilder(dictionary));
}
if (getAsyncProperties().enabled()) {
builder.settings(getAsyncSettingsBuilder());
}
builder.serdes(serdes -> serdes.entries(entries -> {
entries.clear();
getSerdesBuilder().build().entrySet().stream().forEach(entry -> {
entries.put(entry.getKey(), entry.getValue());
});
}));
return builder;
}
/**
* Override this to customize the {@link SerdesBuilder}.
*
* @return the SerdesBuilder
*/
default SerdesBuilder getSerdesBuilder() {
SerdesBuilder serdesBuilder = Serdes.builder().withDefaults();
if (enableISO8601Dates()) {
serdesBuilder.withISO8601Dates("yyyy-MM-dd'T'HH:mm'Z'", TimeZone.getTimeZone("UTC"));
}
return serdesBuilder;
}
/**
* Elide settings to be used for bootstrapping the Elide service. By default, this method constructs an
* ElideSettings object using the application overrides provided in this class. If this method is overridden,
* the returned settings object is used over any additional Elide setting overrides.
*
* That is to say, if you intend to override this method, expect to fully configure the ElideSettings object to
* your needs.
*
* Alternatively override {@link #getElideSettingsBuilder} to only customize the settings you wish to change.
*
* @param dictionary EntityDictionary object.
* @param dataStore DataStore object
* @param mapper Object mapper
* @return Configured ElideSettings object.
*
* @see #getElideSettingsBuilder(EntityDictionary, DataStore, JsonApiMapper)
*/
default ElideSettings getElideSettings(EntityDictionary dictionary, DataStore dataStore, JsonApiMapper mapper) {
ElideSettingsBuilder builder = getElideSettingsBuilder(dictionary, dataStore, mapper);
return builder.build();
}
/* Non-required application/server settings */
/**
* Port for HTTP server to listen on.
*
* @return Default: 8080
*/
default int getPort() {
return 8080;
}
/**
* Package name containing your models. This package will be recursively scanned for @Entity's and
* registered with Elide.
*
* NOTE: This will scan for all entities in that package and bind this data to a set named "elideAllModels".
* If providing a custom ElideSettings object, you can inject this data into your class by using:
*
* @Inject @Named("elideAllModels") Set<Class> entities;
*
* @return Default: com.yourcompany.elide.models
*/
default String getModelPackageName() {
return "com.yourcompany.elide.models";
}
/**
* API root path specification for JSON-API. Namely, this is the mount point of your API.
* By default it will look something like:
* yourcompany.com/api/YOUR_ENTITY
*
* @return Default: /api/*
*/
default String getJsonApiPathSpec() {
return "/api/*";
}
/**
* API root path specification for the GraphQL endpoint. Namely, this is the root uri for GraphQL.
*
* @return Default: /graphql/api
*/
default String getGraphQLApiPathSpec() {
return "/graphql/api/*";
}
/**
* API root path specification for the OpenAPI endpoint. Namely, this is the root uri for OpenAPI docs.
*
* @return Default: /api-docs/*
*/
default String getApiDocsPathSpec() {
return "/api-docs/*";
}
/**
* Enable the JSONAPI endpoint. If false, the endpoint will be disabled.
*
* @return Default: True
*/
default boolean enableJsonApi() {
return true;
}
/**
* Enable the GraphQL endpoint. If false, the endpoint will be disabled.
*
* @return Default: True
*/
default boolean enableGraphQL() {
return true;
}
/**
* Enable/disable verbose error responses.
* @return Default: False
*/
default boolean verboseErrors() {
return false;
}
/**
* Async Properties.
*
* @return AsyncProperties type object.
*/
default ElideStandaloneAsyncSettings getAsyncProperties() {
//Default Properties
return new ElideStandaloneAsyncSettings() { };
}
/**
* Analytic Properties.
*
* @return AnalyticProperties type object.
*/
default ElideStandaloneAnalyticSettings getAnalyticProperties() {
//Default Properties
return new ElideStandaloneAnalyticSettings() { };
}
/**
* Subscription Properties.
*
* @return SubscriptionProperties type object.
*/
default ElideStandaloneSubscriptionSettings getSubscriptionProperties() {
//Default Properties
return new ElideStandaloneSubscriptionSettings() { };
}
/**
* Whether Dates should be ISO8601 strings (true) or epochs (false).
* @return whether ISO8601Dates are enabled.
*/
default boolean enableISO8601Dates() {
return true;
}
/**
* Whether or not Codahale metrics, healthchecks, thread, ping, and admin servlet
* should be enabled.
* @return whether ServiceMonitoring is enabled.
*/
default boolean enableServiceMonitoring() {
return true;
}
/**
* Enable OpenAPI documentation.
* @return whether OpenAPI is enabled;
*/
default boolean enableApiDocs() {
return false;
}
/**
* The OpenAPI Specification Version to generate.
* @return the OpenAPI Specification Version to generate
*/
default OpenApiVersion getOpenApiVersion() {
return OpenApiVersion.OPENAPI_3_0;
}
/**
* The service base URL that clients use in queries. Elide will reference this name
* in any callback URLs returned by the service. If not set, Elide uses the API request to generate the base URL.
* @return The base URL of the service.
*/
default String getBaseUrl() {
return "";
}
/**
* OpenAPI documentation requires an API name.
* @return open api service name;
*/
default String getApiTitle() {
return "Elide Service";
}
/**
* Creates a singular OpenAPI document for JSON-API.
* @param dictionary Contains the static metadata about Elide models. .
* @return list of OpenAPI registration objects.
*/
default List buildApiDocs(EntityDictionary dictionary) {
List docs = new ArrayList<>();
dictionary.getApiVersions().stream().forEach(apiVersion -> {
Info info = new Info()
.title(getApiTitle())
.version(apiVersion);
OpenApiBuilder builder = new OpenApiBuilder(dictionary, openApi -> {
OpenApiVersion openApiVersion = getOpenApiVersion();
if (OpenApiVersion.OPENAPI_3_1.equals(openApiVersion)) {
openApi.specVersion(SpecVersion.V31).openapi("3.1.0");
}
}).apiVersion(apiVersion);
if (!EntityDictionary.NO_VERSION.equals(apiVersion)) {
// Path needs to be set
builder.basePath("/" + "v" + apiVersion);
}
String moduleBasePath = getJsonApiPathSpec().replace("/*", "");
OpenAPI openApi = builder.build().info(info).addServersItem(new Server().url(moduleBasePath));
docs.add(new ApiDocsEndpoint.ApiDocsRegistration("", () -> openApi, apiVersion));
});
return docs;
}
/**
* JAX-RS filters to register with the web service.
*
* @return Default: Empty
*/
default List> getFilters() {
return Collections.emptyList();
}
/**
* Supplemental resource configuration for Elide application. This should be a fully qualified class name.
*
* Before calling the consumer, the class will be injected by the ServiceLocator.
*
* @return Default: null
*/
default Consumer getApplicationConfigurator() {
// Do nothing by default
return (x) -> { };
}
/**
* Gets properties to configure the database.
*
* @return Default: ./settings/hibernate.cfg.xml
*/
default Properties getDatabaseProperties() {
return new Properties();
}
/**
* A hook to directly modify the jetty servlet context handler as necessary.
*
* @param servletContextHandler ServletContextHandler in use by Elide standalone.
*/
default void updateServletContextHandler(ServletContextHandler servletContextHandler) {
// Do nothing
}
/**
* Gets the audit logger for elide.
*
* @return Default: Slf4jLogger
*/
default AuditLogger getAuditLogger() {
return new Slf4jLogger();
}
/**
* Get the query cache implementation. If null, query cache is disabled.
*
* @return Default: {@code new CaffeineCache(getQueryCacheSize())}
*/
default Cache getQueryCache() {
return getAnalyticProperties().getQueryCacheMaxSize() > 0
? new CaffeineCache(getAnalyticProperties().getQueryCacheMaxSize(),
getAnalyticProperties().getQueryCacheExpiration())
: null;
}
/**
* Gets the dynamic configuration for models, security roles, and database connection.
* @param scanner Class scanner
* @param injector Injector injector
* @return Optional DynamicConfiguration
* @throws IOException thrown when validator fails to read configuration.
*/
default Optional getDynamicConfiguration(ClassScanner scanner, Injector injector)
throws IOException {
DynamicConfigValidator validator = null;
if (getAnalyticProperties().enableAggregationDataStore()
&& getAnalyticProperties().enableDynamicModelConfig()) {
validator = new DynamicConfigValidator(
entityDictionaryBuilderCustomizer -> entityDictionaryBuilderCustomizer.scanner(scanner)
.injector(injector),
getAnalyticProperties().getDynamicConfigPath());
validator.readAndValidateConfigs();
}
return Optional.ofNullable(validator);
}
/**
* Provides the default Hikari DataSource Configuration.
* @return An instance of DataSourceConfiguration.
*/
default DataSourceConfiguration getDataSourceConfiguration() {
return new DataSourceConfiguration() {
};
}
/**
* Gets the DataStore for elide.
* @param metaDataStore MetaDataStore object.
* @param aggregationDataStore AggregationDataStore object.
* @param entityManagerFactory EntityManagerFactory object.
* @param injector the injector
* @return DataStore object initialized.
*/
default DataStore getDataStore(MetaDataStore metaDataStore, AggregationDataStore aggregationDataStore,
EntityManagerFactory entityManagerFactory, Injector injector) {
List stores = new ArrayList<>();
DataStore jpaDataStore = new JpaDataStore(
() -> entityManagerFactory.createEntityManager(),
em -> new NonJtaTransaction(em, TXCANCEL, DEFAULT_LOGGER, true, true),
entityManagerFactory::getMetamodel);
stores.add(jpaDataStore);
if (getAnalyticProperties().enableDynamicModelConfigAPI()) {
stores.add(new ConfigDataStore(getAnalyticProperties().getDynamicConfigPath(), new TemplateConfigValidator(
getClassScanner(), injector, getAnalyticProperties().getDynamicConfigPath())));
}
stores.add(metaDataStore);
stores.add(aggregationDataStore);
return new MultiplexManager(stores.toArray(new DataStore[0]));
}
/**
* Gets the DataStore for elide when aggregation store is disabled.
* @param entityManagerFactory EntityManagerFactory object.
* @return DataStore object initialized.
*/
default DataStore getDataStore(EntityManagerFactory entityManagerFactory) {
DataStore jpaDataStore = new JpaDataStore(
() -> entityManagerFactory.createEntityManager(),
em -> new NonJtaTransaction(em, TXCANCEL, DEFAULT_LOGGER, true, true),
entityManagerFactory::getMetamodel);
return jpaDataStore;
}
/**
* Gets the AggregationDataStore for elide.
* @param queryEngine query engine object.
* @return AggregationDataStore object initialized.
*/
default AggregationDataStore getAggregationDataStore(QueryEngine queryEngine) {
AggregationDataStore.AggregationDataStoreBuilder aggregationDataStoreBuilder = AggregationDataStore.builder()
.queryEngine(queryEngine).queryLogger(new Slf4jQueryLogger());
if (getAnalyticProperties().enableDynamicModelConfig()) {
aggregationDataStoreBuilder.dynamicCompiledClasses(queryEngine.getMetaDataStore().getDynamicTypes());
}
aggregationDataStoreBuilder.cache(getQueryCache());
return aggregationDataStoreBuilder.build();
}
/**
* Gets the EntityDictionary for elide.
* @param injector Service locator for web service for dependency injection.
* @param dynamicConfiguration optional dynamic config object.
* @param entitiesToExclude set of Entities to exclude from binding.
* @param idObfuscator the id obfuscator
* @return EntityDictionary object initialized.
*/
default EntityDictionary getEntityDictionary(ServiceLocator injector, ClassScanner scanner,
Optional dynamicConfiguration, Set> entitiesToExclude,
IdObfuscator idObfuscator) {
Map> checks = new HashMap<>();
if (getAnalyticProperties().enableDynamicModelConfigAPI()) {
checks.put(ConfigChecks.CAN_CREATE_CONFIG, ConfigChecks.CanNotCreate.class);
checks.put(ConfigChecks.CAN_READ_CONFIG, ConfigChecks.CanNotRead.class);
checks.put(ConfigChecks.CAN_DELETE_CONFIG, ConfigChecks.CanNotDelete.class);
checks.put(ConfigChecks.CAN_UPDATE_CONFIG, ConfigChecks.CanNotUpdate.class);
}
EntityDictionary dictionary = new EntityDictionary(
new HashMap<>(), //Checks
new HashMap<>(), //Role Checks
new Injector() {
@Override
public void inject(Object entity) {
injector.inject(entity);
}
@Override
public T instantiate(Class cls) {
return injector.create(cls);
}
},
CoerceUtil::lookup, //Serde Lookup
entitiesToExclude,
scanner,
idObfuscator);
dynamicConfiguration.map(DynamicConfiguration::getRoles).orElseGet(Collections::emptySet).forEach(role ->
dictionary.addRoleCheck(role, new Role.RoleMemberCheck(role))
);
return dictionary;
}
/**
* Gets the metadatastore for elide.
* @param scanner Class scanner.
* @param injector the injector
* @param dynamicConfiguration optional dynamic config object.
* @return MetaDataStore object initialized.
*/
default MetaDataStore getMetaDataStore(ClassScanner scanner, Injector injector,
Optional dynamicConfiguration) {
boolean enableMetaDataStore = getAnalyticProperties().enableMetaDataStore();
return dynamicConfiguration
.map(dc -> new MetaDataStore(scanner, injector, dc.getTables(),
dc.getNamespaceConfigurations(), enableMetaDataStore))
.orElseGet(() -> new MetaDataStore(scanner, injector, enableMetaDataStore));
}
/**
* Gets the QueryEngine for elide.
* @param metaDataStore MetaDataStore object.
* @param defaultConnectionDetails default DataSource Object and SQLDialect Object.
* @param dynamicConfiguration Optional dynamic config.
* @param dataSourceConfiguration DataSource Configuration.
* @param dbPasswordExtractor Password Extractor Implementation.
* @return QueryEngine object initialized.
*/
default QueryEngine getQueryEngine(MetaDataStore metaDataStore, ConnectionDetails defaultConnectionDetails,
Optional dynamicConfiguration,
DataSourceConfiguration dataSourceConfiguration, DBPasswordExtractor dbPasswordExtractor) {
if (dynamicConfiguration.isPresent()) {
Map connectionDetailsMap = new HashMap<>();
dynamicConfiguration.get().getDatabaseConfigurations().forEach(dbConfig ->
connectionDetailsMap.put(dbConfig.getName(),
new ConnectionDetails(
dataSourceConfiguration.getDataSource(dbConfig, dbPasswordExtractor),
SQLDialectFactory.getDialect(dbConfig.getDialect())))
);
Function connectionDetailsLookup = (name) -> {
if (StringUtils.isEmpty(name)) {
return defaultConnectionDetails;
}
return Optional.ofNullable(connectionDetailsMap.get(name))
.orElseThrow(() -> new IllegalStateException("ConnectionDetails undefined for connection: "
+ name));
};
return new SQLQueryEngine(metaDataStore, connectionDetailsLookup,
new HashSet<>(Arrays.asList(new AggregateBeforeJoinOptimizer(metaDataStore))),
new DefaultQueryPlanMerger(metaDataStore),
new DefaultQueryValidator(metaDataStore.getMetadataDictionary()));
}
return new SQLQueryEngine(metaDataStore, (unused) -> defaultConnectionDetails);
}
/**
* Get the class scanner for this Elide instance.
* @return class scanner implementation.
*/
default ClassScanner getClassScanner() {
return new DefaultClassScanner();
}
/**
* Get the exception mappers for this Elide instance. By default no exceptions will be mapped.
*
* @return the exception mappers.
*/
default ExceptionMappers getExceptionMappers() {
return null;
}
/**
* Gets the json api error mapper.
*
* @return the json api error mapper.
*/
default JsonApiErrorMapper getJsonApiErrorMapper() {
return new DefaultJsonApiErrorMapper();
}
/**
* Gets the json api exception handler.
*
* @return the json api exception handler.
*/
default JsonApiExceptionHandler getJsonApiExceptionHandler() {
return new DefaultJsonApiExceptionHandler(getExceptionLogger(), getExceptionMappers(),
getJsonApiErrorMapper());
}
/**
* Gets the graphql error mapper.
*
* @return the graphql error mapper.
*/
default GraphQLErrorMapper getGraphQLErrorMapper() {
return new DefaultGraphQLErrorMapper();
}
/**
* Gets the graphql exception handler.
*
* @return the graphql exception handler.
*/
default GraphQLExceptionHandler getGraphQLExceptionHandler() {
return new DefaultGraphQLExceptionHandler(getExceptionLogger(), getExceptionMappers(),
getGraphQLErrorMapper());
}
/**
* Gets the exception logger.
*
* @return the exception logger.
*/
default ExceptionLogger getExceptionLogger() {
return new Slf4jExceptionLogger();
}
/**
* Get the JsonApiMapper for Elide.
*
* @return object mapper.
*/
default JsonApiMapper getJsonApiMapper() {
return new JsonApiMapper(getObjectMapper());
}
/**
* Get the Jackson object mapper for Elide.
*
* @return object mapper.
*/
default ObjectMapper getObjectMapper() {
return DEFAULT_OBJECT_MAPPER;
}
/**
* Gets the DataFetcherExceptionHandler for GraphQL.
*
* @return the DataFetcherExceptionHandler for GraphQL
*/
default DataFetcherExceptionHandler getDataFetcherExceptionHandler() {
return new SimpleDataFetcherExceptionHandler();
}
/**
* Gets the route resolver to determine the API version.
*
* @return the route resolver
*/
default RouteResolver getRouteResolver() {
return null;
}
/**
* The maximum pagination size a client can request.
*
* The {@link com.yahoo.elide.annotation.Paginate#maxPageSize()} annotation
* takes precendence.
*
* @return the max page size
*/
default int getMaxPageSize() {
return Pagination.MAX_PAGE_SIZE;
}
/**
* Default pagination size for collections if the client doesn't paginate.
*
* The {@link com.yahoo.elide.annotation.Paginate#defaultPageSize()} annotation
* takes precendence.
*
* @return the default page size
*/
default int getDefaultPageSize() {
return Pagination.DEFAULT_PAGE_SIZE;
}
/**
* The id obfuscator to use to obfuscate ids.
*
* @return the id obfuscator
*/
default IdObfuscator getIdObfuscator() {
return null;
}
}