com.enterprisemath.dao.big.InMemoryBigEntityDao Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of em-dao Show documentation
Show all versions of em-dao Show documentation
Simple and powerful data access layer.
package com.enterprisemath.dao.big;
import com.enterprisemath.dao.filter.Criterium;
import com.enterprisemath.dao.filter.Direction;
import com.enterprisemath.dao.filter.Filter;
import com.enterprisemath.dao.filter.Operator;
import com.enterprisemath.dao.filter.Order;
import com.enterprisemath.utils.DomainUtils;
import com.enterprisemath.utils.ValidationUtils;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import org.apache.commons.lang3.builder.ToStringBuilder;
/**
* Big entity data access layer which holds all objects in memory.
*
* @author radek.hecl
*/
public class InMemoryBigEntityDao implements BigEntityDao {
/**
* Builder object.
*/
public static class Builder {
/**
* Builds the result object.
*
* @return created object
*/
public InMemoryBigEntityDao build() {
return new InMemoryBigEntityDao(this);
}
}
/**
* Cache memory.
*/
private Map> cache = new HashMap>();
/**
* Creates new instance.
*
* @param builder builder object
*/
public InMemoryBigEntityDao(Builder builder) {
guardInvariants();
}
/**
* Guards this object to be consistent. Throws exception if this is not the case.
*/
private void guardInvariants() {
}
@Override
public void insertBigEntity(String type, BigEntity entity, InsertOptions options) {
if (!cache.containsKey(type)) {
cache.put(type, new ArrayList());
}
for (BigEntity ent : cache.get(type)) {
if (entity.getCode().equals(ent.getCode())) {
throw new RuntimeException("unique identification code violation exception: code = " + ent.getCode());
}
}
cache.get(type).add(entity);
}
@Override
public void insertBigEntities(String type, List entities, InsertOptions options) {
for (BigEntity ent : entities) {
insertBigEntity(type, ent, options);
}
}
@Override
public BigEntityIterator selectBigEntities(String type, Filter filter, Set fields, SelectOptions options) {
List filtered = selectByCriteria(type, filter.getCriteria());
List ordered = new ArrayList(filtered);
Collections.sort(ordered, new BigEntityComparator(filter.getOrders()));
int from = (int) filter.getFrom();
int limit = filter.getLimit() == null ? ordered.size() : filter.getLimit();
List res = new ArrayList(limit);
for (int i = from; i < from + limit && i < ordered.size(); ++i) {
BigEntity entity = ordered.get(i);
BigEntity.Builder resEntity = new BigEntity.Builder();
resEntity.setCode(entity.getCode());
for (String field : fields) {
resEntity.addField(field, entity.getFields().get(field));
}
res.add(resEntity.build());
}
return new EntIterator(res);
}
@Override
public long countBigEntities(String type, List> criteria, CountOptions options) {
return selectByCriteria(type, criteria).size();
}
@Override
public void updateBigEntity(String type, String code, BigEntityUpdate update, UpdateOptions options) {
if (update.getUpdateFields().isEmpty() && update.getDropFields().isEmpty()) {
return;
}
List entities = cache.get(type);
int index = -1;
for (int i = 0; i < entities.size(); ++i) {
if (entities.get(i).getCode().equals(code)) {
index = i;
break;
}
}
if (index == -1) {
return;
}
Map newFields = new HashMap(entities.get(index).getFields());
for (String fld : update.getUpdateFields().keySet()) {
newFields.put(fld, update.getUpdateFields().get(fld));
}
for (String fld : update.getDropFields()) {
newFields.remove(fld);
}
entities.set(index, new BigEntity.Builder().
setCode(code).
setFields(newFields).
build());
return;
}
@Override
public void deleteBigEntity(String type, String code, DeleteOptions options) {
List collection = cache.get(type);
if (collection == null) {
return;
}
for (int i = 0; i < collection.size(); ++i) {
if (collection.get(i).getCode().equals(code)) {
collection.remove(i);
return;
}
}
}
/**
* Selects entities by criteria.
*
* @param type type
* @param criteria criteria
* @return selected entities
*/
private List selectByCriteria(String type, List> criteria) {
List collection = cache.get(type);
if (collection == null) {
return Collections.emptyList();
}
List res = new ArrayList();
for (BigEntity entity : collection) {
boolean matched = true;
for (Criterium crit : criteria) {
Object val = null;
if (crit.getColumn().equals("code")) {
val = entity.getCode();
}
else {
val = entity.getFields().get(crit.getColumn());
}
if (crit.getOperator().equals(Operator.EQUAL)) {
if (!DomainUtils.safeEquals(val, crit.getValue())) {
matched = false;
break;
}
}
else if (crit.getOperator().equals(Operator.NOT_EQUAL)) {
if (DomainUtils.safeEquals(val, crit.getValue())) {
matched = false;
break;
}
}
else if (crit.getOperator().equals(Operator.IN)) {
Collection col = (Collection) crit.getValue();
if (!col.contains(val)) {
matched = false;
break;
}
}
else if (crit.getOperator().equals(Operator.GREATER)) {
ValidationUtils.guardInstanceOf(val, Comparable.class, "value must be Comparable for greater criterium: " + val);
Comparable comparableVal = (Comparable) val;
if (comparableVal.compareTo(crit.getValue()) <= 0) {
matched = false;
break;
}
}
else if (crit.getOperator().equals(Operator.GREATER_OR_EQUAL)) {
ValidationUtils.guardInstanceOf(val, Comparable.class, "value must be Comparable for greater or equal criterium: " + val);
Comparable comparableVal = (Comparable) val;
if (comparableVal.compareTo(crit.getValue()) < 0) {
matched = false;
break;
}
}
else if (crit.getOperator().equals(Operator.LESS)) {
ValidationUtils.guardInstanceOf(val, Comparable.class, "value must be Comparable for less criterium: " + val);
Comparable comparableVal = (Comparable) val;
if (comparableVal.compareTo(crit.getValue()) >= 0) {
matched = false;
break;
}
}
else if (crit.getOperator().equals(Operator.LESS_OR_EQUAL)) {
ValidationUtils.guardInstanceOf(val, Comparable.class, "value must be Comparable for less or equal criterium: " + val);
Comparable comparableVal = (Comparable) val;
if (comparableVal.compareTo(crit.getValue()) > 0) {
matched = false;
break;
}
}
else if (crit.getOperator().equals(Operator.LIKE)) {
ValidationUtils.guardInstanceOf(val, String.class, "value must be String for like criterium: " + val);
String exp = (String) crit.getValue();
exp = exp.replaceAll("%", ".*");
if (!((String) val).matches(exp)) {
matched = false;
break;
}
}
else {
throw new RuntimeException("unsupported operator: " + crit);
}
}
if (matched) {
res.add(entity);
}
}
return res;
}
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this);
}
/**
* Comparator for big entities.
*/
private static class BigEntityComparator implements Comparator {
/**
* Orders.
*/
private List> orders;
/**
* Creates new instance.
*
* @param orders orders
*/
public BigEntityComparator(List> orders) {
this.orders = DomainUtils.softCopyUnmodifiableList(orders);
}
@Override
public int compare(BigEntity o1, BigEntity o2) {
for (Order order : orders) {
Object val1 = order.getColumn().equals("code") ? o1.getCode() : o1.getFields().get(order.getColumn());
Object val2 = order.getColumn().equals("code") ? o2.getCode() : o2.getFields().get(order.getColumn());
ValidationUtils.guardInstanceOf(val1, Comparable.class, "val1 must be comparable: " + val1);
ValidationUtils.guardInstanceOf(val2, Comparable.class, "val2 must be comparable: " + val2);
Comparable val1Comp = (Comparable) val1;
Comparable val2Comp = (Comparable) val2;
int res = val1Comp.compareTo(val2Comp);
if (res != 0) {
if (order.getDirection().equals(Direction.ASCENDANT)) {
return res;
}
else if (order.getDirection().equals(Direction.DESCENDANT)) {
return -res;
}
else {
throw new RuntimeException("unknown direction: " + order.getDirection());
}
}
}
return 0;
}
}
/**
* Implementation of iterator for entities.
*/
private static class EntIterator implements BigEntityIterator {
/**
* Entities.
*/
private List entities;
/**
* Index.
*/
private int index = 0;
/**
* Lock object.
*/
private final Object lock = new Object();
/**
* Creates new instance.
*
* @param entities list of entities
*/
public EntIterator(List entities) {
this.entities = DomainUtils.softCopyList(entities);
guardInvariants();
}
/**
* Guards this object to be consistent. Throws exception if this is not the case.
*/
private void guardInvariants() {
ValidationUtils.guardNotNullCollection(entities, "entities cannot have null element");
}
@Override
public boolean isNextAvailable() {
synchronized (lock) {
return index < entities.size();
}
}
@Override
public BigEntity getNext() throws NoSuchElementException {
synchronized (lock) {
if (index >= entities.size()) {
throw new NoSuchElementException("iterator is consumed");
}
BigEntity res = entities.get(index);
index = index + 1;
return res;
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy