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.DefaultBeanManager Maven / Gradle / Ivy
package org.deephacks.tools4j.config.internal.core.runtime;
import com.google.common.base.Optional;
import org.deephacks.tools4j.config.admin.query.BeanQuery;
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.spi.BeanManager;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.deephacks.tools4j.config.model.Events.*;
/**
* In memory BeanManager.
*/
public class DefaultBeanManager extends BeanManager {
private static final HashMap beans = new HashMap<>();
@Override
public Optional getEager(BeanId id) {
Map all = readValuesAsMap();
return getEagerly(id, all);
}
private Optional getEagerly(BeanId id, Map all) {
Bean result = all.get(id);
if (result == null) {
return Optional.absent();
}
// bean found, initalize references.
for (BeanId ref : result.getReferences()) {
if (ref.getBean() != null) {
continue;
}
Bean refBean = all.get(ref);
if (refBean == null) {
throw CFG301_MISSING_RUNTIME_REF(result.getId(), ref);
}
ref.setBean(refBean);
getEagerly(ref, all);
}
return Optional.of(result);
}
@Override
public Optional getLazy(BeanId id) throws AbortRuntimeException {
Map all = readValuesAsMap();
Bean bean = all.get(id);
if (bean == null) {
return Optional.absent();
}
for (BeanId ref : bean.getReferences()) {
Bean refBean = all.get(ref);
if (refBean == null) {
throw CFG301_MISSING_RUNTIME_REF(ref);
}
ref.setBean(refBean);
}
return Optional.of(bean);
}
/**
* The direct, but no further, successors that references this bean will also be
* fetched and initalized with their direct, but no further, predecessors.
*/
@Override
public Map getBeanToValidate(Collection beans) throws AbortRuntimeException {
Map beansToValidate = new HashMap<>();
for (Bean bean : beans) {
Map predecessors = new HashMap<>();
// beans read from xml storage will only have their basic properties initalized...
Map all = readValuesAsMap();
// ... but we also need set the direct references/predecessors for beans to validate
Map beansToValidateSubset = getDirectSuccessors(bean, all);
beansToValidateSubset.put(bean.getId(), bean);
for (Bean toValidate : beansToValidateSubset.values()) {
predecessors.putAll(getDirectPredecessors(toValidate, all));
}
for (Bean predecessor : predecessors.values()) {
for (BeanId ref : predecessor.getReferences()) {
Bean b = all.get(ref);
if (b == null) {
throw CFG301_MISSING_RUNTIME_REF(predecessor.getId());
}
ref.setBean(b);
}
}
for (Bean toValidate : beansToValidateSubset.values()) {
// list references of beansToValidate should now
// be available in predecessors.
for (BeanId ref : toValidate.getReferences()) {
Bean predecessor = predecessors.get(ref);
if (predecessor == null) {
throw new IllegalStateException("Bug in algorithm. Reference [" + ref
+ "] of [" + toValidate.getId()
+ "] should be available in predecessors.");
}
ref.setBean(predecessor);
}
}
beansToValidate.putAll(predecessors);
}
return beansToValidate;
}
private Map getDirectPredecessors(Bean bean, Map all) {
Map predecessors = new HashMap<>();
for (BeanId ref : bean.getReferences()) {
Bean predecessor = all.get(ref);
if (predecessor == null) {
throw CFG304_BEAN_DOESNT_EXIST(ref);
}
predecessors.put(predecessor.getId(), predecessor);
}
return predecessors;
}
private Map getDirectSuccessors(Bean bean, Map all) {
Map successors = new HashMap<>();
for (Bean b : all.values()) {
List refs = b.getReferences();
if (refs.contains(bean.getId())) {
successors.put(b.getId(), b);
}
}
return successors;
}
@Override
public Optional getSingleton(String schemaName) throws IllegalArgumentException {
Map all = readValuesAsMap();
for (Bean bean : all.values()) {
if (bean.getId().getSchemaName().equals(schemaName)) {
if (!bean.getId().isSingleton()) {
throw new IllegalArgumentException("Schema [" + schemaName
+ "] is not a get.");
}
BeanId singletonId = bean.getId();
return getEagerly(singletonId, all);
}
}
return Optional.of(Bean.create(BeanId.createSingleton(schemaName)));
}
@Override
public Map list(String name) {
Map all = readValuesAsMap();
Map result = new HashMap<>();
for (Bean b : all.values()) {
if (b.getId().getSchemaName().equals(name)) {
Optional bean = getEagerly(b.getId(), all);
result.put(bean.get().getId(), bean.get());
}
}
return result;
}
@Override
public Map list(String schemaName, Collection ids)
throws AbortRuntimeException {
Map result = new HashMap<>();
for (Bean bean : beans.values()) {
String schema = bean.getId().getSchemaName();
if (!schema.equals(schemaName)) {
continue;
}
for (String id : ids) {
if (bean.getId().getInstanceId().equals(id)) {
result.put(bean.getId(), bean);
}
}
}
return result;
}
@Override
public void create(Bean bean) {
Map values = readValuesAsMap();
checkReferencesExist(bean, values);
if (!bean.isDefault()) {
checkUniquness(bean, values);
values.put(bean.getId(), bean);
} else {
Bean stored = values.get(bean.getId());
if (stored == null) {
values.put(bean.getId(), bean);
}
}
writeValues(values);
}
@Override
public void create(Collection set) {
Map beans = readValuesAsMap();
// first check uniquness towards storage
for (Bean bean : set) {
checkUniquness(bean, beans);
}
// TODO: check that provided beans are unique among themselves.
// references may not exist in storage, but are provided
// as part of the transactions, so add them before validating references.
for (Bean bean : set) {
beans.put(bean.getId(), bean);
}
for (Bean bean : set) {
checkReferencesExist(bean, beans);
}
writeValues(beans);
}
@Override
public void createSingleton(BeanId singleton) {
Map values = readValuesAsMap();
Bean bean = Bean.create(singleton);
try {
checkUniquness(bean, values);
} catch (AbortRuntimeException e) {
// ignore and return silently.
return;
}
values.put(singleton, bean);
writeValues(values);
}
@Override
public void set(Bean bean) {
Map values = readValuesAsMap();
Bean existing = values.get(bean.getId());
if (existing == null) {
throw CFG304_BEAN_DOESNT_EXIST(bean.getId());
}
checkReferencesExist(bean, values);
checkInstanceExist(bean, values);
values.put(bean.getId(), bean);
writeValues(values);
}
@Override
public void set(Collection set) {
Map beans = readValuesAsMap();
// TODO: check that provided beans are unique among themselves.
// references may not exist in storage, but are provided
// as part of the transactions, so add them before validating references.
for (Bean bean : set) {
Bean existing = beans.get(bean.getId());
if (existing == null) {
throw CFG304_BEAN_DOESNT_EXIST(bean.getId());
}
beans.put(bean.getId(), bean);
}
for (Bean bean : set) {
checkReferencesExist(bean, beans);
}
writeValues(beans);
}
@Override
public void merge(Bean bean) {
Map beans = readValuesAsMap();
Bean b = beans.get(bean.getId());
if (b == null) {
throw CFG304_BEAN_DOESNT_EXIST(bean.getId());
}
replace(b, bean, beans);
writeValues(beans);
}
@Override
public void merge(Collection bean) {
Map beans = readValuesAsMap();
for (Bean replace : bean) {
Bean target = beans.get(replace.getId());
if (target == null) {
throw Events.CFG304_BEAN_DOESNT_EXIST(replace.getId());
}
replace(target, replace, beans);
}
writeValues(beans);
}
private void replace(Bean target, Bean replace, Map all) {
if (target == null) {
// bean did not exist in storage, create it.
target = replace;
}
checkReferencesExist(replace, all);
for (String name : replace.getPropertyNames()) {
List values = replace.getValues(name);
if (values == null || values.size() == 0) {
// null/empty indicates a remove/reset-to-default op
target.remove(name);
} else {
target.setProperty(name, replace.getValues(name));
}
}
for (String name : replace.getReferenceNames()) {
List values = replace.getReference(name);
if (values == null || values.size() == 0) {
// null/empty indicates a remove/reset-to-default op
target.remove(name);
} else {
target.setReferences(name, values);
}
}
}
@Override
public void delete(BeanId id) {
Map beans = readValuesAsMap();
checkNoReferencesExist(id, beans);
checkDeleteDefault(beans.get(id));
beans.remove(id);
writeValues(beans);
}
@Override
public void delete(String schemaName, Collection instanceIds) {
Map beans = readValuesAsMap();
for (String instance : instanceIds) {
checkDeleteDefault(beans.get(BeanId.create(instance, schemaName)));
checkNoReferencesExist(BeanId.create(instance, schemaName), beans);
beans.remove(BeanId.create(instance, schemaName));
}
writeValues(beans);
}
@Override
public BeanQuery newQuery(Schema schema) {
throw new UnsupportedOperationException("");
}
private static void checkNoReferencesExist(BeanId deleted, Map storage) {
Collection hasReferences = new ArrayList<>();
for (Bean b : storage.values()) {
if (hasReferences(b, deleted)) {
hasReferences.add(b.getId());
}
}
if (hasReferences.size() > 0) {
throw CFG302_CANNOT_DELETE_BEAN(Arrays.asList(deleted));
}
}
private static void checkReferencesExist(final Bean bean, final Map storage) {
ArrayList allRefs = new ArrayList<>();
for (String name : bean.getReferenceNames()) {
if (bean.getReference(name) == null) {
// the reference is about to be removed.
continue;
}
for (BeanId beanId : bean.getReference(name)) {
allRefs.add(beanId);
}
}
Collection missingReferences = new ArrayList<>();
for (BeanId beanId : allRefs) {
if (beanId.getInstanceId() == null) {
continue;
}
Bean b = storage.get(beanId);
if (b == null) {
missingReferences.add(beanId);
}
}
if (missingReferences.size() > 0) {
throw CFG301_MISSING_RUNTIME_REF(bean.getId(), missingReferences);
}
}
private static void checkInstanceExist(Bean bean, Map storage) {
Collection beans = storage.values();
for (Bean existingBean : beans) {
if (existingBean.getId().equals(bean.getId())) {
return;
}
}
throw CFG304_BEAN_DOESNT_EXIST(bean.getId());
}
private static void checkUniquness(Bean bean, Map storage) {
Collection beans = storage.values();
for (Bean existing : beans) {
if (bean.getId().equals(existing.getId())) {
throw CFG303_BEAN_ALREADY_EXIST(bean.getId());
}
}
}
private static void checkDeleteDefault(Bean bean) {
if (bean == null) {
return;
}
if (bean.isDefault()) {
throw CFG311_DEFAULT_REMOVAL(bean.getId());
}
}
/**
* Returns the a list of property names of the target bean that have
* references to the bean id.
*/
private static boolean hasReferences(Bean target, BeanId reference) {
for (String name : target.getReferenceNames()) {
for (BeanId ref : target.getReference(name)) {
if (ref.equals(reference)) {
return true;
}
}
}
return false;
}
private Map readValuesAsMap() {
Map map = new HashMap<>();
for (Bean bean : beans.values()) {
map.put(bean.getId(), bean);
}
return map;
}
private void writeValues(Map map) {
writeValues(new ArrayList<>(map.values()));
}
private void writeValues(List beans) {
for (Bean bean : beans) {
this.beans.put(bean.getId(), bean);
}
}
public static void clear() {
beans.clear();
}
}