All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.enterprisemath.dao.big.InMemoryBigEntityDao Maven / Gradle / Ivy

There is a newer version: 4.3.2
Show newest version
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