All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.deephacks.tools4j.config.internal.core.runtime.ConfigCoreContext Maven / Gradle / Ivy
/**
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.deephacks.tools4j.config.internal.core.runtime;
import com.google.common.base.Optional;
import org.deephacks.tools4j.config.Config;
import org.deephacks.tools4j.config.ConfigContext;
import org.deephacks.tools4j.config.internal.core.ConfigCore;
import org.deephacks.tools4j.config.internal.core.DefaultSchemaManager;
import org.deephacks.tools4j.config.internal.core.Lookup;
import org.deephacks.tools4j.config.internal.core.SystemProperties;
import org.deephacks.tools4j.config.internal.core.query.ConfigIndexedCollection;
import org.deephacks.tools4j.config.internal.core.query.ConfigQuery;
import org.deephacks.tools4j.config.model.AbortRuntimeException;
import org.deephacks.tools4j.config.model.Bean;
import org.deephacks.tools4j.config.model.Bean.BeanId;
import org.deephacks.tools4j.config.model.Events;
import org.deephacks.tools4j.config.model.Schema;
import org.deephacks.tools4j.config.model.Schema.SchemaPropertyRef;
import org.deephacks.tools4j.config.spi.BeanManager;
import org.deephacks.tools4j.config.spi.CacheManager;
import org.deephacks.tools4j.config.spi.Conversion;
import org.deephacks.tools4j.config.spi.SchemaManager;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.deephacks.tools4j.config.model.Events.CFG102_NOT_CONFIGURABLE;
import static org.deephacks.tools4j.config.model.Events.CFG303;
/**
* ConfigCoreContext is responsible for separating the admin, config and spi
* context so that no dependencies (compile nor config) exist between them.
*/
@Singleton
public final class ConfigCoreContext extends ConfigContext {
private Conversion conversion;
private static final Lookup lookup = Lookup.get();
private SchemaManager schemaManager = lookup.lookup(SchemaManager.class, DefaultSchemaManager.class);
private BeanManager beanManager = lookup.lookup(BeanManager.class, DefaultBeanManager.class);
private Optional cacheManager;
private HashMap schemas = new HashMap<>();
private SystemProperties properties = SystemProperties.instance();
private static HashMap FILE_CONFIG;
private static HashMap, Class> initalized = new HashMap<>();
@Inject
private ConfigCore core;
@Override
public void register(Class... configurable) {
doLookup();
for (Class clazz : configurable) {
getSchema(clazz);
}
}
@Override
public void unregister(Class... configurable) {
doLookup();
for (Class clazz : configurable) {
Schema schema = conversion.convert(clazz, Schema.class);
schemaManager.removeSchema(schema.getName());
core.removeIndex(schema);
}
}
@Override
public void registerDefault(Object... instances) {
doLookup();
for (Object instance : instances) {
Bean bean = conversion.convert(instance, Bean.class);
bean.setDefault();
try {
beanManager.create(bean);
} catch (AbortRuntimeException e) {
// ignore if bean already exist
if (e.getEvent().getCode() != CFG303) {
throw e;
}
}
}
}
@Override
public T get(Class configurable) {
doLookup();
Schema schema = getSchema(configurable);
BeanId singleton = getSingletonId(schema, configurable);
Optional bean = beanManager.getEager(singleton);
if (!bean.isPresent()) {
initFile(configurable);
Bean fileBean = FILE_CONFIG.get(singleton);
if (fileBean != null) {
fileBean.set(schema);
bean = Optional.of(fileBean);
}
if (bean.isPresent()) {
T object = conversion.convert(bean.get(), configurable);
core.cache(bean.get());
return object;
}
}
if (!bean.isPresent()) {
bean = Optional.of(Bean.create(BeanId.createSingleton(schema.getName())));
}
core.setSchema(bean.get(), schemas);
setSingletonReferences(bean.get(), schemas);
T object = conversion.convert(bean.get(), configurable);
core.cache(bean.get());
return object;
}
@Override
public List list(Class configurable) {
doLookup();
Schema s = getSchema(configurable);
initFile(configurable);
Map beans = new HashMap<>();
Map schemas = schemaManager.getSchemas();
Map found = beanManager.list(s.getName());
// only fallback to file if no beans were found.
// maybe good if file and storage beans were merged?
// on the other hand, that would mean that file bean instances
// never can be removed, which may be annoying?
if (found.isEmpty()) {
for (Bean bean : FILE_CONFIG.values()) {
if (bean.getId().getSchemaName().equals(s.getName())) {
beans.put(bean.getId(), bean);
}
}
}
for (Bean foundBean : found.values()) {
beans.put(foundBean.getId(), foundBean);
}
core.setSchema(schemas, beans);
for (Bean bean : beans.values()) {
setSingletonReferences(bean, schemas);
core.cache(bean);
}
ArrayList objects = new ArrayList<>();
for(T object : conversion.convert(beans.values(), configurable)) {
objects.add(object);
}
return objects;
}
@Override
public Optional get(String id, Class configurable) {
doLookup();
Schema s = getSchema(configurable);
Map schemas = schemaManager.getSchemas();
BeanId beanId = BeanId.create(id, s.getName());
Optional bean = beanManager.getEager(beanId);
if (!bean.isPresent()) {
initFile(configurable);
Bean fileBean = FILE_CONFIG.get(beanId);
if (fileBean != null) {
bean = Optional.of(fileBean);
} else {
return Optional.absent();
}
}
core.setSchema(bean.get(), schemas);
setSingletonReferences(bean.get(), schemas);
T object = conversion.convert(bean.get(), configurable);
core.cache(bean.get());
return Optional.of(object);
}
@Override
public ConfigQuery newQuery(Class configurable) {
doLookup();
Schema schema = getSchema(configurable);
ConfigIndexedCollection collection = core.get(schema);
if(collection == null) {
throw Events.CFG101_SCHEMA_NOT_EXIST(configurable.getName());
}
if(!cacheManager.isPresent()) {
throw new IllegalStateException("Queries are not possible without a cache manager.");
}
return new ConfigQuery(collection, cacheManager.get());
}
private BeanId getSingletonId(Schema s, Class configurable) {
return BeanId.createSingleton(s.getName());
}
private void setSingletonReferences(Bean bean, Map schemas) {
Schema s = bean.getSchema();
for (SchemaPropertyRef ref : s.get(SchemaPropertyRef.class)) {
if (ref.isSingleton()) {
Schema singletonSchema = schemas.get(ref.getSchemaName());
Optional singleton = beanManager.getSingleton(ref.getSchemaName());
if (!singleton.isPresent()) {
initFile(null);
Bean fileBean = FILE_CONFIG.get(BeanId.createSingleton(ref.getSchemaName()));
if (fileBean != null) {
singleton = Optional.of(fileBean);
}
}
if (!singleton.isPresent()) {
singleton = Optional.of(Bean.create(BeanId.createSingleton(ref.getSchemaName())));
}
singleton.get().set(singletonSchema);
BeanId singletonId = singleton.get().getId();
singletonId.setBean(singleton.get());
// recursive call.
setSingletonReferences(singleton.get(), schemas);
bean.setReference(ref.getName(), singletonId);
}
}
}
private synchronized void initFile(Class configurable) {
if (configurable == null) {
return;
}
if (FILE_CONFIG == null) {
FILE_CONFIG = new HashMap<>();
}
if (initalized.get(configurable) != null) {
return;
}
Schema schema = getSchema(configurable);
for (Bean bean : properties.list(schema)) {
FILE_CONFIG.put(bean.getId(), bean);
}
}
public void doLookup() {
// core would already be injected in a cdi environment
if (core == null) {
core = new ConfigCore();
}
if (conversion == null) {
conversion = Conversion.get();
conversion.register(new ObjectToBeanConverter());
conversion.register(new ClassToSchemaConverter());
conversion.register(new FieldToSchemaPropertyConverter());
conversion.register(new BeanToObjectConverter());
}
if (cacheManager == null) {
cacheManager = core.lookupCacheManager();
}
}
private Schema getSchema(Class clazz) {
Schema schema = schemas.get(clazz);
if(schema != null) {
return schema;
}
ClassIntrospector introspector = new ClassIntrospector(clazz);
Config config = introspector.getAnnotation(Config.class);
if (config == null) {
throw CFG102_NOT_CONFIGURABLE(clazz);
}
String schemaName = config.name();
if (schemaName == null || "".equals(schemaName)) {
schemaName = clazz.getName();
}
schema = conversion.convert(clazz, Schema.class);
for (Class cls : schema.getReferenceSchemaTypes()) {
if (schemas.get(clazz) != null) {
getSchema(cls);
}
}
properties.registerSchema(schema);
schemas.put(schema.getName(), schema);
schemaManager.registerSchema(schema);
core.putIndex(schema);
return schema;
}
}