/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.ofbiz.entity;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;
import java.sql.Timestamp;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;

import javax.xml.parsers.ParserConfigurationException;

import org.ofbiz.base.concurrent.ConstantFuture;
import org.ofbiz.base.concurrent.ExecutionPool;
import org.ofbiz.base.util.Debug;
import org.ofbiz.base.util.GeneralRuntimeException;
import org.ofbiz.base.util.UtilDateTime;
import org.ofbiz.base.util.UtilFormatOut;
import org.ofbiz.base.util.UtilGenerics;
import org.ofbiz.base.util.UtilMisc;
import org.ofbiz.base.util.UtilObject;
import org.ofbiz.base.util.UtilValidate;
import org.ofbiz.base.util.UtilXml;
import org.ofbiz.entity.cache.Cache;
import org.ofbiz.entity.condition.EntityCondition;
import org.ofbiz.entity.config.model.Datasource;
import org.ofbiz.entity.config.model.DelegatorElement;
import org.ofbiz.entity.config.model.EntityConfig;
import org.ofbiz.entity.datasource.GenericHelper;
import org.ofbiz.entity.datasource.GenericHelperFactory;
import org.ofbiz.entity.datasource.GenericHelperInfo;
import org.ofbiz.entity.eca.EntityEcaHandler;
import org.ofbiz.entity.model.DynamicViewEntity;
import org.ofbiz.entity.model.ModelEntity;
import org.ofbiz.entity.model.ModelEntityChecker;
import org.ofbiz.entity.model.ModelField;
import org.ofbiz.entity.model.ModelFieldType;
import org.ofbiz.entity.model.ModelFieldTypeReader;
import org.ofbiz.entity.model.ModelGroupReader;
import org.ofbiz.entity.model.ModelKeyMap;
import org.ofbiz.entity.model.ModelReader;
import org.ofbiz.entity.model.ModelRelation;
import org.ofbiz.entity.model.ModelViewEntity;
import org.ofbiz.entity.serialize.SerializeException;
import org.ofbiz.entity.serialize.XmlSerializer;
import org.ofbiz.entity.transaction.TransactionUtil;
import org.ofbiz.entity.util.DistributedCacheClear;
import org.ofbiz.entity.util.EntityCrypto;
import org.ofbiz.entity.util.EntityFindOptions;
import org.ofbiz.entity.util.EntityListIterator;
import org.ofbiz.entity.util.EntityQuery;
import org.ofbiz.entity.util.SequenceUtil;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;

/**
 * The default implementation of the <code>Delegator</code> interface.
 *
 */
public class GenericDelegator implements Delegator {

    public static final String module = GenericDelegator.class.getName();

    protected ModelReader modelReader = null;
    protected ModelGroupReader modelGroupReader = null;
    /** This flag is only here for lower level technical testing, it shouldn't be user configurable (or at least I don't think so yet); when true all operations without a transaction will be wrapped in one; seems to be necessary for some (all?) XA aware connection pools, and should improve overall stability and consistency */
    public static final boolean alwaysUseTransaction = true;

    protected String delegatorBaseName = null;
    protected String delegatorFullName = null;
    protected String delegatorTenantId = null;
    private String originalDelegatorName = null;

    protected DelegatorElement delegatorInfo = null;

    protected Cache cache = null;

    protected final AtomicReference<Future<DistributedCacheClear>> distributedCacheClear = new AtomicReference<Future<DistributedCacheClear>>();
    protected boolean warnNoEcaHandler = false;
    protected final AtomicReference<Future<EntityEcaHandler<?>>> entityEcaHandler = new AtomicReference<Future<EntityEcaHandler<?>>>();
    protected final AtomicReference<SequenceUtil> AtomicRefSequencer = new AtomicReference<SequenceUtil>(null);
    protected EntityCrypto crypto = null;

    /** A ThreadLocal variable to allow other methods to specify a user identifier (usually the userLoginId, though technically the Entity Engine doesn't know anything about the UserLogin entity) */
    protected static ThreadLocal<List<String>> userIdentifierStack = new ThreadLocal<List<String>>();
    /** A ThreadLocal variable to allow other methods to specify a session identifier (usually the visitId, though technically the Entity Engine doesn't know anything about the Visit entity) */
    protected static ThreadLocal<List<String>> sessionIdentifierStack = new ThreadLocal<List<String>>();

    private boolean testMode = false;
    private boolean testRollbackInProgress = false;
    private static final AtomicReferenceFieldUpdater<GenericDelegator, LinkedBlockingDeque<?>> testOperationsUpdater = UtilGenerics.cast(AtomicReferenceFieldUpdater.newUpdater(GenericDelegator.class, LinkedBlockingDeque.class, "testOperations"));
    private volatile LinkedBlockingDeque<TestOperation> testOperations = null;

    protected static List<String> getUserIdentifierStack() {
        List<String> curValList = userIdentifierStack.get();
        if (curValList == null) {
            curValList = new LinkedList<String>();
            userIdentifierStack.set(curValList);
        }
        return curValList;
    }

    public static void pushUserIdentifier(String userIdentifier) {
        if (userIdentifier == null) {
            return;
        }
        List<String> curValList = getUserIdentifierStack();
        curValList.add(0, userIdentifier);
    }

    public static String popUserIdentifier() {
        List<String> curValList = getUserIdentifierStack();
        if (curValList.size() == 0) {
            return null;
        } else {
            return curValList.remove(0);
        }
    }

    public static void clearUserIdentifierStack() {
        List<String> curValList = getUserIdentifierStack();
        curValList.clear();
    }

    protected static List<String> getSessionIdentifierStack() {
        List<String> curValList = sessionIdentifierStack.get();
        if (curValList == null) {
            curValList = new LinkedList<String>();
            sessionIdentifierStack.set(curValList);
        }
        return curValList;
    }

    public static void pushSessionIdentifier(String sessionIdentifier) {
        if (sessionIdentifier == null) {
            return;
        }
        List<String> curValList = getSessionIdentifierStack();
        curValList.add(0, sessionIdentifier);
    }

    public static String popSessionIdentifier() {
        List<String> curValList = getSessionIdentifierStack();
        if (curValList.size() == 0) {
            return null;
        } else {
            return curValList.remove(0);
        }
    }

    public static void clearSessionIdentifierStack() {
        List<String> curValList = getSessionIdentifierStack();
        curValList.clear();
    }

    /** Only allow creation through the factory method */
    protected GenericDelegator() {}

    /** Only allow creation through the factory method */
    protected GenericDelegator(String delegatorFullName) throws GenericEntityException {
        //if (Debug.infoOn()) Debug.logInfo("Creating new Delegator with name \"" + delegatorFullName + "\".", module);
        this.setDelegatorNames(delegatorFullName);
        this.delegatorInfo = EntityConfig.getInstance().getDelegator(delegatorBaseName);

        String kekText;
        // before continuing, if there is a tenantId use the base delegator to see if it is valid
        if (UtilValidate.isNotEmpty(this.delegatorTenantId)) {
            Delegator baseDelegator = DelegatorFactory.getDelegator(this.delegatorBaseName);
            GenericValue tenant = EntityQuery.use(baseDelegator).from("Tenant").where("tenantId", this.delegatorTenantId).cache(true).queryOne();
            if (tenant == null) {
                throw new GenericEntityException("No Tenant record found for delegator [" + this.delegatorFullName + "] with tenantId [" + this.delegatorTenantId + "]");
            } else if ("Y".equals(tenant.getString("disabled"))) {
                throw new GenericEntityException("No Tenant record found for delegator [" + this.delegatorFullName + "] with tenantId [" + this.delegatorTenantId + "]");
            }
            GenericValue kekValue = EntityQuery.use(baseDelegator).from("TenantKeyEncryptingKey").where("tenantId", getDelegatorTenantId()).cache(true).queryOne();
            if (kekValue != null) {
                kekText = kekValue.getString("kekText");
            } else {
                kekText = this.delegatorInfo.getKeyEncryptingKey();
            }
        } else {
            kekText = this.delegatorInfo.getKeyEncryptingKey();
        }

        this.modelReader = ModelReader.getModelReader(delegatorBaseName);
        this.modelGroupReader = ModelGroupReader.getModelGroupReader(delegatorBaseName);

        cache = new Cache(delegatorFullName);

        // do the entity model check
        List<String> warningList = new LinkedList<String>();
        Debug.logInfo("Doing entity definition check...", module);
        ModelEntityChecker.checkEntities(this, warningList);
        if (warningList.size() > 0) {
            Debug.logWarning("=-=-=-=-= Found " + warningList.size() + " warnings when checking the entity definitions:", module);
            for (String warning: warningList) {
                Debug.logWarning(warning, module);
            }
        }

        // initialize helpers by group
        Set<String> groupNames = getModelGroupReader().getGroupNames(delegatorBaseName);
        List<Future<Void>> futures = new LinkedList<Future<Void>>();
        for (String groupName: groupNames) {
            futures.add(ExecutionPool.GLOBAL_BATCH.submit(createHelperCallable(groupName)));
        }
        ExecutionPool.getAllFutures(futures);

        // NOTE: doing some things before the ECAs and such to make sure it is in place just in case it is used in a service engine startup thing or something

        // setup the crypto class; this also after the delegator is in the cache otherwise we get infinite recursion
        this.crypto = new EntityCrypto(this, kekText);
    }

    private void initializeOneGenericHelper(String groupName) {
        GenericHelperInfo helperInfo = this.getGroupHelperInfo(groupName);
        if (helperInfo == null) {
            if (Debug.infoOn()) {
                Debug.logInfo("Delegator \"" + delegatorFullName + "\" NOT initializing helper for entity group \"" + groupName + "\" because the group is not associated to this delegator.", module);
            }
            return;
        }
        String helperBaseName = helperInfo.getHelperBaseName();

        if (Debug.infoOn()) {
            Debug.logInfo("Delegator \"" + delegatorFullName + "\" initializing helper \"" + helperBaseName + "\" for entity group \"" + groupName + "\".", module);
        }
        if (UtilValidate.isNotEmpty(helperInfo.getHelperFullName())) {
            // pre-load field type defs, the return value is ignored
            ModelFieldTypeReader.getModelFieldTypeReader(helperBaseName);
            // get the helper and if configured, do the datasource check
            GenericHelper helper = GenericHelperFactory.getHelper(helperInfo);

            try {
                Datasource datasource = EntityConfig.getDatasource(helperBaseName);
                if (datasource.getCheckOnStart()) {
                    if (Debug.infoOn()) {
                        Debug.logInfo("Doing database check as requested in entityengine.xml with addMissing=" + datasource.getAddMissingOnStart(), module);
                    }
                    helper.checkDataSource(this.getModelEntityMapByGroup(groupName), null, datasource.getAddMissingOnStart());
                }
            } catch (GenericEntityException e) {
                Debug.logWarning(e, e.getMessage(), module);
            }
        }
    }

    protected Callable<Void> createHelperCallable(final String groupName) {
        return new Callable<Void>() {
            @Override
            public Void call() {
                initializeOneGenericHelper(groupName);
                return null;
            }
        };
    }

    protected void setDelegatorNames(String delegatorFullName) {
        this.delegatorFullName = delegatorFullName;

        int hashSymbolIndex = delegatorFullName.indexOf('#');
        if (hashSymbolIndex == -1) {
            this.delegatorBaseName = delegatorFullName;
        } else {
            this.delegatorBaseName = delegatorFullName.substring(0, hashSymbolIndex);
            this.delegatorTenantId = delegatorFullName.substring(hashSymbolIndex + 1);
        }
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#initEntityEcaHandler()
     */
    @Override
    public synchronized void initEntityEcaHandler() {
        // Nothing to do if already assigned: the class loader has already been called, the class instantiated and casted to EntityEcaHandler
        if (this.entityEcaHandler.get() != null || this.warnNoEcaHandler) {
            return;
        }

        Callable<EntityEcaHandler<?>> creator = new Callable<EntityEcaHandler<?>>() {
            public EntityEcaHandler<?> call() {
                return createEntityEcaHandler();
            }
        };
        FutureTask<EntityEcaHandler<?>> futureTask = new FutureTask<EntityEcaHandler<?>>(creator);
        if (this.entityEcaHandler.compareAndSet(null, futureTask)) {
            // This needs to use BATCH, as the service engine might add it's own items into a thread pool.
            ExecutionPool.GLOBAL_BATCH.submit(futureTask);
        }
    }

    protected EntityEcaHandler<?> createEntityEcaHandler() {
        // If useEntityEca is false do nothing: the entityEcaHandler member field with a null value would cause its code to do nothing
        if (this.delegatorInfo.getEntityEcaEnabled()) {
            //time to do some tricks with manual class loading that resolves circular dependencies, like calling services
            ClassLoader loader = Thread.currentThread().getContextClassLoader();
            // initialize the entity eca handler
            String entityEcaHandlerClassName = this.delegatorInfo.getEntityEcaHandlerClassName();

            try {
                Class<?> eecahClass = loader.loadClass(entityEcaHandlerClassName);
                EntityEcaHandler<?> entityEcaHandler = UtilGenerics.cast(eecahClass.newInstance());
                entityEcaHandler.setDelegator(this);
                return entityEcaHandler;
            } catch (ClassNotFoundException e) {
                Debug.logWarning(e, "EntityEcaHandler class with name " + entityEcaHandlerClassName + " was not found, Entity ECA Rules will be disabled", module);
            } catch (InstantiationException e) {
                Debug.logWarning(e, "EntityEcaHandler class with name " + entityEcaHandlerClassName + " could not be instantiated, Entity ECA Rules will be disabled", module);
            } catch (IllegalAccessException e) {
                Debug.logWarning(e, "EntityEcaHandler class with name " + entityEcaHandlerClassName + " could not be accessed (illegal), Entity ECA Rules will be disabled", module);
            } catch (ClassCastException e) {
                Debug.logWarning(e, "EntityEcaHandler class with name " + entityEcaHandlerClassName + " does not implement the EntityEcaHandler interface, Entity ECA Rules will be disabled", module);
            }
        } else if (!this.warnNoEcaHandler) {
            Debug.logInfo("Entity ECA Handler disabled for delegator [" + delegatorFullName + "]", module);
            this.warnNoEcaHandler = true;
        }
        return null;
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#getDelegatorName()
     */
    @Override
    public String getDelegatorName() {
        return this.delegatorFullName;
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#getDelegatorBaseName()
     */
    @Override
    public String getDelegatorBaseName() {
        return this.delegatorBaseName;
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#getDelegatorBaseName()
     */
    @Override
    public String getDelegatorTenantId() {
        return this.delegatorTenantId;
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#getOriginalDelegatorName()
     */
    @Override
    public String getOriginalDelegatorName() {
        return this.originalDelegatorName == null ? this.delegatorFullName : this.originalDelegatorName;
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#getModelReader()
     */
    @Override
    public ModelReader getModelReader() {
        return this.modelReader;
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#getModelGroupReader()
     */
    @Override
    public ModelGroupReader getModelGroupReader() {
        return this.modelGroupReader;
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#getModelEntity(java.lang.String)
     */
    @Override
    public ModelEntity getModelEntity(String entityName) {
        try {
            return getModelReader().getModelEntity(entityName);
        } catch (GenericEntityException e) {
            Debug.logError(e, "Error getting entity definition from model", module);
            return null;
        }
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#getEntityGroupName(java.lang.String)
     */
    @Override
    public String getEntityGroupName(String entityName) {
        return getModelGroupReader().getEntityGroupName(entityName, this.delegatorBaseName);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#getModelEntityMapByGroup(java.lang.String)
     */
    @Override
    public Map<String, ModelEntity> getModelEntityMapByGroup(String groupName) throws GenericEntityException {
        Set<String> entityNameSet = getModelGroupReader().getEntityNamesByGroup(groupName);

        if (this.delegatorInfo.getDefaultGroupName().equals(groupName)) {
            // add all entities with no group name to the Set
            Set<String> allEntityNames = this.getModelReader().getEntityNames();
            for (String entityName: allEntityNames) {
                if (this.delegatorInfo.getDefaultGroupName().equals(getModelGroupReader().getEntityGroupName(entityName, this.delegatorBaseName))) {
                    entityNameSet.add(entityName);
                }
            }
        }

        Map<String, ModelEntity> entities = new HashMap<String, ModelEntity>();
        if (UtilValidate.isEmpty(entityNameSet)) {
            return entities;
        }

        int errorCount = 0;
        for (String entityName: entityNameSet) {
            try {
                ModelEntity entity = getModelReader().getModelEntity(entityName);
                if (entity != null) {
                    entities.put(entity.getEntityName(), entity);
                } else {
                    throw new IllegalStateException("Could not find entity with name " + entityName);
                }
            } catch (GenericEntityException ex) {
                errorCount++;
                Debug.logError("Entity [" + entityName + "] named in Entity Group with name " + groupName + " are not defined in any Entity Definition file", module);
            }
        }

        if (errorCount > 0) {
            Debug.logError(errorCount + " entities were named in ModelGroup but not defined in any EntityModel", module);
        }

        return entities;
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#getGroupHelperName(java.lang.String)
     */
    @Override
    public String getGroupHelperName(String groupName) {
        return this.delegatorInfo.getGroupDataSource(groupName);
    }

    @Override
    public GenericHelperInfo getGroupHelperInfo(String entityGroupName) {
        if (entityGroupName == null) {
            return null;
        }
        String helperBaseName = this.getGroupHelperName(entityGroupName);
        if (helperBaseName == null) {
            return null;
        }
        if (UtilValidate.isNotEmpty(this.delegatorTenantId) && "org.ofbiz.tenant".equals(entityGroupName)) {
            Debug.logInfo("Can't access entity of entityGroup = " + entityGroupName + " using tenant delegator "+ this.getDelegatorName()+", use base delegator instead", module);
            return null;
        }

        GenericHelperInfo helperInfo = new GenericHelperInfo(entityGroupName, helperBaseName);
        if (UtilValidate.isNotEmpty(this.delegatorTenantId)) {
            // get the JDBC parameters from the DB for the entityGroupName and tenantId
            try {
                // NOTE: instead of caching the GenericHelpInfo object do a cached query here and create a new object each time, will avoid issues when the database data changes during run time
                // NOTE: always use the base delegator for this to avoid problems when this is being initialized
                Delegator baseDelegator = DelegatorFactory.getDelegator(this.delegatorBaseName);
                GenericValue tenantDataSource = EntityQuery.use(baseDelegator).from("TenantDataSource").where("tenantId", this.delegatorTenantId, "entityGroupName", entityGroupName).cache(true).queryOne();
                if (tenantDataSource != null) {
                    helperInfo.setTenantId(this.delegatorTenantId);
                    helperInfo.setOverrideJdbcUri(tenantDataSource.getString("jdbcUri"));
                    helperInfo.setOverrideUsername(tenantDataSource.getString("jdbcUsername"));
                    helperInfo.setOverridePassword(tenantDataSource.getString("jdbcPassword"));
                } else {
                    return null;
                }
            } catch (GenericEntityException e) {
                // don't complain about this too much, just log the error if there is one
                Debug.logInfo(e, "Error getting TenantDataSource info for tenantId=" + this.delegatorTenantId + ", entityGroupName=" + entityGroupName, module);
            }
        }
        return helperInfo;
    }

    protected GenericHelperInfo getEntityHelperInfo(String entityName) {
        return this.getGroupHelperInfo(this.getEntityGroupName(entityName));
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#getEntityHelperName(java.lang.String)
     */
    @Override
    public String getEntityHelperName(String entityName) {
        return this.getGroupHelperName(this.getEntityGroupName(entityName));
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#getEntityHelperName(org.ofbiz.entity.model.ModelEntity)
     */
    @Override
    public String getEntityHelperName(ModelEntity entity) {
        if (entity == null) {
            return null;
        }
        return getEntityHelperName(entity.getEntityName());
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#getEntityHelper(java.lang.String)
     */
    @Override
    public GenericHelper getEntityHelper(String entityName) throws GenericEntityException {
        GenericHelperInfo helperInfo = getEntityHelperInfo(entityName);

        if (helperInfo != null) {
            return GenericHelperFactory.getHelper(helperInfo);
        } else {
            throw new GenericEntityException("There is no datasource (Helper) configured for the entity-group [" + this.getEntityGroupName(entityName) + "]; was trying to find datasource (helper) for entity [" + entityName + "]");
        }
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#getEntityHelper(org.ofbiz.entity.model.ModelEntity)
     */
    @Override
    public GenericHelper getEntityHelper(ModelEntity entity) throws GenericEntityException {
        return getEntityHelper(entity.getEntityName());
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#getEntityFieldType(org.ofbiz.entity.model.ModelEntity, java.lang.String)
     */
    @Override
    public ModelFieldType getEntityFieldType(ModelEntity entity, String type) throws GenericEntityException {
        return this.getModelFieldTypeReader(entity).getModelFieldType(type);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#getModelFieldTypeReader(org.ofbiz.entity.model.ModelEntity)
     */
    @Override
    public ModelFieldTypeReader getModelFieldTypeReader(ModelEntity entity) {
        String helperName = getEntityHelperName(entity);
        if (helperName == null || helperName.length() <= 0) {
            return null;
        }
        ModelFieldTypeReader modelFieldTypeReader = ModelFieldTypeReader.getModelFieldTypeReader(helperName);
        if (modelFieldTypeReader == null) {
            throw new IllegalArgumentException("ModelFieldTypeReader not found for entity " + entity.getEntityName() + " with helper name " + helperName);
        }
        return modelFieldTypeReader;
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#getEntityFieldTypeNames(org.ofbiz.entity.model.ModelEntity)
     */
    @Override
    public Collection<String> getEntityFieldTypeNames(ModelEntity entity) throws GenericEntityException {
        String helperName = getEntityHelperName(entity);

        if (helperName == null || helperName.length() <= 0) {
            return null;
        }
        ModelFieldTypeReader modelFieldTypeReader = ModelFieldTypeReader.getModelFieldTypeReader(helperName);

        if (modelFieldTypeReader == null) {
            throw new GenericEntityException("ModelFieldTypeReader not found for entity " + entity.getEntityName() + " with helper name " + helperName);
        }
        return modelFieldTypeReader.getFieldTypeNames();
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#makeValue(java.lang.String)
     */
    @Override
    public GenericValue makeValue(String entityName) {
        ModelEntity entity = this.getModelEntity(entityName);
        if (entity == null) {
            throw new IllegalArgumentException("[GenericDelegator.makeValue] could not find entity for entityName: " + entityName);
        }
        GenericValue value = GenericValue.create(entity);
        value.setDelegator(this);
        return value;
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#makeValue(java.lang.String, java.lang.Object)
     */
    @Override
    public GenericValue makeValue(String entityName, Object... fields) {
        return makeValue(entityName, UtilMisc.<String, Object>toMap(fields));
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#makeValue(java.lang.String, java.util.Map)
     */
    @Override
    public GenericValue makeValue(String entityName, Map<String, ? extends Object> fields) {
        ModelEntity entity = this.getModelEntity(entityName);
        if (entity == null) {
            throw new IllegalArgumentException("[GenericDelegator.makeValue] could not find entity for entityName: " + entityName);
        }
        return GenericValue.create(this, entity, fields);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#makeValueSingle(java.lang.String, java.lang.Object)
     */
    @Override
    public GenericValue makeValueSingle(String entityName, Object singlePkValue) {
        ModelEntity entity = this.getModelEntity(entityName);
        if (entity == null) {
            throw new IllegalArgumentException("[GenericDelegator.makeValue] could not find entity for entityName: " + entityName);
        }
        return GenericValue.create(this, entity, singlePkValue);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#makeValidValue(java.lang.String, java.lang.Object)
     */
    @Override
    public GenericValue makeValidValue(String entityName, Object... fields) {
        return makeValidValue(entityName, UtilMisc.<String, Object>toMap(fields));
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#makeValidValue(java.lang.String, java.util.Map)
     */
    @Override
    public GenericValue makeValidValue(String entityName, Map<String, ? extends Object> fields) {
        ModelEntity entity = this.getModelEntity(entityName);
        if (entity == null) {
            throw new IllegalArgumentException("[GenericDelegator.makeValidValue] could not find entity for entityName: " + entityName);
        }
        GenericValue value = GenericValue.create(entity);
        value.setDelegator(this);
        value.setAllFields(fields, true, null, null);
        return value;
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#makePK(java.lang.String)
     */
    @Override
    public GenericPK makePK(String entityName) {
        return this.makePK(entityName, (Map<String, Object>) null);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#makePK(java.lang.String, java.lang.Object)
     */
    @Override
    public GenericPK makePK(String entityName, Object... fields) {
        return makePK(entityName, UtilMisc.<String, Object>toMap(fields));
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#makePK(java.lang.String, java.util.Map)
     */
    @Override
    public GenericPK makePK(String entityName, Map<String, ? extends Object> fields) {
        ModelEntity entity = this.getModelEntity(entityName);
        if (entity == null) {
            throw new IllegalArgumentException("[GenericDelegator.makePK] could not find entity for entityName: " + entityName);
        }
        return GenericPK.create(this, entity, fields);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#makePKSingle(java.lang.String, java.lang.Object)
     */
    @Override
    public GenericPK makePKSingle(String entityName, Object singlePkValue) {
        ModelEntity entity = this.getModelEntity(entityName);
        if (entity == null) {
            throw new IllegalArgumentException("[GenericDelegator.makePKSingle] could not find entity for entityName: " + entityName);
        }
        return GenericPK.create(this, entity, singlePkValue);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#create(org.ofbiz.entity.GenericPK)
     */
    @Override
    public GenericValue create(GenericPK primaryKey) throws GenericEntityException {
        return this.create(primaryKey, true);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#create(org.ofbiz.entity.GenericPK, boolean)
     * @deprecated use {@link #create(GenericPK primaryKey)}
     */
    @Override
    @Deprecated
    public GenericValue create(GenericPK primaryKey, boolean doCacheClear) throws GenericEntityException {
        if (primaryKey == null) {
            throw new GenericEntityException("Cannot create from a null primaryKey");
        }

        return this.create(GenericValue.create(primaryKey), doCacheClear);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#create(java.lang.String, java.lang.Object)
     */
    @Override
    public GenericValue create(String entityName, Object... fields) throws GenericEntityException {
        return create(entityName, UtilMisc.<String, Object>toMap(fields));
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#create(java.lang.String, java.util.Map)
     */
    @Override
    public GenericValue create(String entityName, Map<String, ? extends Object> fields) throws GenericEntityException {
        if (entityName == null || fields == null) {
            return null;
        }
        ModelEntity entity = this.getModelReader().getModelEntity(entityName);
        GenericValue genericValue = GenericValue.create(this, entity, fields);

        return this.create(genericValue, true);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#createSingle(java.lang.String, java.lang.Object)
     */
    @Override
    public GenericValue createSingle(String entityName, Object singlePkValue) throws GenericEntityException {
        if (entityName == null || singlePkValue == null) {
            return null;
        }
        ModelEntity entity = this.getModelReader().getModelEntity(entityName);
        GenericValue genericValue = GenericValue.create(this, entity, singlePkValue);

        return this.create(genericValue, true);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#create(org.ofbiz.entity.GenericValue)
     */
    @Override
    public GenericValue create(GenericValue value) throws GenericEntityException {
        return this.create(value, true);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#createSetNextSeqId(org.ofbiz.entity.GenericValue)
     */
    @Override
    public GenericValue createSetNextSeqId(GenericValue value) throws GenericEntityException {
        @Deprecated
        boolean doCacheClear = true;

        if (value == null) {
            throw new GenericEntityException("Cannot create a null value");
        }

        GenericHelper helper = getEntityHelper(value.getEntityName());
        // just make sure it is this delegator...
        value.setDelegator(this);
        // this will throw an IllegalArgumentException if the entity for the value does not have one pk field, or if it already has a value set for the one pk field
        value.setNextSeqId();

        boolean beganTransaction = false;
        try {
            if (alwaysUseTransaction) {
                beganTransaction = TransactionUtil.begin();
            }

            EntityEcaRuleRunner<?> ecaRunner = this.getEcaRuleRunner(value.getEntityName());
            ecaRunner.evalRules(EntityEcaHandler.EV_VALIDATE, EntityEcaHandler.OP_CREATE, value, false);

            ecaRunner.evalRules(EntityEcaHandler.EV_RUN, EntityEcaHandler.OP_CREATE, value, false);

            value.setDelegator(this);

            // if audit log on for any fields, save new value with no old value because it's a create
            if (value != null && value.getModelEntity().getHasFieldWithAuditLog()) {
                createEntityAuditLogAll(value, false, false);
            }

            try {
                value = helper.create(value);

                if (testMode) {
                    storeForTestRollback(new TestOperation(OperationType.INSERT, value));
                }
            } catch (GenericEntityException e) {
                // see if this was caused by an existing record before resetting the sequencer and trying again
                // NOTE: use the helper directly so ECA rules, etc won't be run

                GenericValue existingValue = null;
                try {
                    existingValue = helper.findByPrimaryKey(value.getPrimaryKey());
                } catch (GenericEntityException e1) {
                    // ignore this error, if not found it'll probably be a GenericEntityNotFoundException
                    // it is important to not let this get thrown because it will mask the original exception
                }
                if (existingValue == null) {
                    throw e;
                } else {
                    if (Debug.infoOn()) {
                        Debug.logInfo("Error creating entity record with a sequenced value [" + value.getPrimaryKey() + "], trying again about to refresh bank for entity [" + value.getEntityName() + "]", module);
                    }

                    // found an existing value... was probably a duplicate key, so clean things up and try again
                    this.AtomicRefSequencer.get().forceBankRefresh(value.getEntityName(), 1);

                    value.setNextSeqId();
                    value = helper.create(value);
                    if (Debug.infoOn()) {
                        Debug.logInfo("Successfully created new entity record on retry with a sequenced value [" + value.getPrimaryKey() + "], after getting refreshed bank for entity [" + value.getEntityName() + "]", module);
                    }

                    if (testMode) {
                        storeForTestRollback(new TestOperation(OperationType.INSERT, value));
                    }
                }
            }

            if (value != null) {
                value.setDelegator(this);
                if (value.lockEnabled()) {
                    refresh(value, doCacheClear);
                } else {
                    if (doCacheClear) {
                        ecaRunner.evalRules(EntityEcaHandler.EV_CACHE_CLEAR, EntityEcaHandler.OP_CREATE, value, false);
                        this.clearCacheLine(value);
                    }
                }
            }

            ecaRunner.evalRules(EntityEcaHandler.EV_RETURN, EntityEcaHandler.OP_CREATE, value, false);
            TransactionUtil.commit(beganTransaction);
            return value;
        } catch (Exception e) {
            String errMsg = "Failure in createSetNextSeqId operation for entity [" + value.getEntityName() + "]: " + e.toString() + ". Rolling back transaction.";
            Debug.logError(e, errMsg, module);
            TransactionUtil.rollback(beganTransaction, errMsg, e);
            throw new GenericEntityException(e);
        }
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#create(org.ofbiz.entity.GenericValue, boolean)
     * @deprecated use {@link #create(GenericValue value)}
     */
    @Override
    @Deprecated
    public GenericValue create(GenericValue value, boolean doCacheClear) throws GenericEntityException {
        boolean beganTransaction = false;
        try {
            if (alwaysUseTransaction) {
                beganTransaction = TransactionUtil.begin();
            }

            if (value == null) {
                throw new GenericEntityException("Cannot create a null value");
            }

            EntityEcaRuleRunner<?> ecaRunner = this.getEcaRuleRunner(value.getEntityName());
            ecaRunner.evalRules(EntityEcaHandler.EV_VALIDATE, EntityEcaHandler.OP_CREATE, value, false);

            GenericHelper helper = getEntityHelper(value.getEntityName());

            ecaRunner.evalRules(EntityEcaHandler.EV_RUN, EntityEcaHandler.OP_CREATE, value, false);

            value.setDelegator(this);

            // if audit log on for any fields, save new value with no old value because it's a create
            if (value != null && value.getModelEntity().getHasFieldWithAuditLog()) {
                createEntityAuditLogAll(value, false, false);
            }

            value = helper.create(value);

            if (testMode) {
                storeForTestRollback(new TestOperation(OperationType.INSERT, value));
            }
            if (value != null) {
                value.setDelegator(this);
                if (value.lockEnabled()) {
                    refresh(value, doCacheClear);
                } else {
                    if (doCacheClear) {
                        ecaRunner.evalRules(EntityEcaHandler.EV_CACHE_CLEAR, EntityEcaHandler.OP_CREATE, value, false);
                        this.clearCacheLine(value);
                    }
                }
            }

            ecaRunner.evalRules(EntityEcaHandler.EV_RETURN, EntityEcaHandler.OP_CREATE, value, false);
            TransactionUtil.commit(beganTransaction);
            return value;
        } catch (Exception e) {
            String errMsg = "Failure in create operation for entity [" + (value != null ? value.getEntityName() : "null") + "]: " + e.toString() + ". Rolling back transaction.";
            Debug.logError(errMsg, module);
            TransactionUtil.rollback(beganTransaction, errMsg, e);
            throw new GenericEntityException(e);
        }
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#createOrStore(org.ofbiz.entity.GenericValue, boolean)
     * @deprecated use {@link #createOrStore(GenericValue value)}
     */
    @Override
    @Deprecated
    public GenericValue createOrStore(GenericValue value, boolean doCacheClear) throws GenericEntityException {
        boolean beganTransaction = false;
        try {
            if (alwaysUseTransaction) {
                beganTransaction = TransactionUtil.begin();
            }

            GenericValue checkValue = this.findOne(value.getEntityName(), value.getPrimaryKey(), false);
            if (checkValue != null) {
                this.store(value, doCacheClear);
            } else {
                this.create(value, doCacheClear);
            }
            if (value.lockEnabled()) {
                this.refresh(value);
            }
            TransactionUtil.commit(beganTransaction);
            return value;
        } catch (Exception e) {
            String errMsg = "Failure in createOrStore operation for entity [" + value.getEntityName() + "]: " + e.toString() + ". Rolling back transaction.";
            Debug.logError(e, errMsg, module);
            TransactionUtil.rollback(beganTransaction, errMsg, e);
            throw new GenericEntityException(e);
        }
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#createOrStore(org.ofbiz.entity.GenericValue)
     */
    @Override
    public GenericValue createOrStore(GenericValue value) throws GenericEntityException {
        return createOrStore(value, true);
    }

    protected void saveEntitySyncRemoveInfo(GenericEntity dummyPK) throws GenericEntityException {
        // don't store remove info on entities where it is disabled
        if (dummyPK.getModelEntity().getNoAutoStamp() || this.testRollbackInProgress) {
            return;
        }

        // don't store remove info on things removed on an entity sync
        if (dummyPK.getIsFromEntitySync()) {
            return;
        }

        String serializedPK = null;
        try {
            serializedPK = XmlSerializer.serialize(dummyPK);
        } catch (SerializeException e) {
            Debug.logError(e, "Could not serialize primary key to save EntitySyncRemove", module);
        } catch (FileNotFoundException e) {
            Debug.logError(e, "Could not serialize primary key to save EntitySyncRemove", module);
        } catch (IOException e) {
            Debug.logError(e, "Could not serialize primary key to save EntitySyncRemove", module);
        }

        if (serializedPK != null) {
            GenericValue entitySyncRemove = this.makeValue("EntitySyncRemove");
            entitySyncRemove.set("primaryKeyRemoved", serializedPK);
            this.createSetNextSeqId(entitySyncRemove);
        }
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#removeByPrimaryKey(org.ofbiz.entity.GenericPK)
     */
    @Override
    public int removeByPrimaryKey(GenericPK primaryKey) throws GenericEntityException {
        int retVal = this.removeByPrimaryKey(primaryKey, true);
        return retVal;
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#removeByPrimaryKey(org.ofbiz.entity.GenericPK, boolean)
     * @deprecated use {@link #removeByPrimaryKey(GenericPK primaryKey)}
     */
    @Override
    @Deprecated
    public int removeByPrimaryKey(GenericPK primaryKey, boolean doCacheClear) throws GenericEntityException {
        boolean beganTransaction = false;
        try {
            if (alwaysUseTransaction) {
                beganTransaction = TransactionUtil.begin();
            }

            EntityEcaRuleRunner<?> ecaRunner = this.getEcaRuleRunner(primaryKey.getEntityName());
            ecaRunner.evalRules(EntityEcaHandler.EV_VALIDATE, EntityEcaHandler.OP_REMOVE, primaryKey, false);

            GenericHelper helper = getEntityHelper(primaryKey.getEntityName());

            ecaRunner.evalRules(EntityEcaHandler.EV_RUN, EntityEcaHandler.OP_REMOVE, primaryKey, false);

            // if audit log on for any fields, save old value before removing so it's still there
            if (primaryKey.getModelEntity().getHasFieldWithAuditLog()) {
                createEntityAuditLogAll(this.findOne(primaryKey.getEntityName(), primaryKey, false), true, true);
            }

            GenericValue removedEntity = null;
            if (testMode) {
                removedEntity = this.findOne(primaryKey.getEntityName(), primaryKey, false);
            }
            int num = helper.removeByPrimaryKey(primaryKey);
            if (doCacheClear) {
                ecaRunner.evalRules(EntityEcaHandler.EV_CACHE_CLEAR, EntityEcaHandler.OP_REMOVE, primaryKey, false);
                this.clearCacheLine(primaryKey);
            }

            this.saveEntitySyncRemoveInfo(primaryKey);

            if (testMode) {
                if (removedEntity != null) {
                    storeForTestRollback(new TestOperation(OperationType.DELETE, removedEntity));
                }
            }

            ecaRunner.evalRules(EntityEcaHandler.EV_RETURN, EntityEcaHandler.OP_REMOVE, primaryKey, false);
            TransactionUtil.commit(beganTransaction);
            return num;
        } catch (Exception e) {
            String errMsg = "Failure in removeByPrimaryKey operation for entity [" + primaryKey.getEntityName() + "]: " + e.toString() + ". Rolling back transaction.";
            Debug.logError(e, errMsg, module);
            TransactionUtil.rollback(beganTransaction, errMsg, e);
            throw new GenericEntityException(e);
        }
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#removeValue(org.ofbiz.entity.GenericValue)
     */
    @Override
    public int removeValue(GenericValue value) throws GenericEntityException {
        return this.removeValue(value, true);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#removeValue(org.ofbiz.entity.GenericValue, boolean)
     * @deprecated use {@link #removeValue(GenericValue value)}
     */
    @Override
    @Deprecated
    public int removeValue(GenericValue value, boolean doCacheClear) throws GenericEntityException {
        // NOTE: this does not call the GenericDelegator.removeByPrimaryKey method because it has more information to pass to the ECA rule hander
        boolean beganTransaction = false;
        try {
            if (alwaysUseTransaction) {
                beganTransaction = TransactionUtil.begin();
            }

            EntityEcaRuleRunner<?> ecaRunner = this.getEcaRuleRunner(value.getEntityName());
            ecaRunner.evalRules(EntityEcaHandler.EV_VALIDATE, EntityEcaHandler.OP_REMOVE, value, false);

            GenericHelper helper = getEntityHelper(value.getEntityName());

            ecaRunner.evalRules(EntityEcaHandler.EV_RUN, EntityEcaHandler.OP_REMOVE, value, false);

            // if audit log on for any fields, save old value before actual remove
            if (value.getModelEntity().getHasFieldWithAuditLog()) {
                createEntityAuditLogAll(value, true, true);
            }

            GenericValue removedValue = null;
            if (testMode) {
                removedValue = this.findOne(value.getEntityName(), value.getPrimaryKey(), false);
            }

            int num = helper.removeByPrimaryKey(value.getPrimaryKey());
            // Need to call removedFromDatasource() here because the helper calls removedFromDatasource() on the PK instead of the GenericEntity.
            value.removedFromDatasource();
            if (doCacheClear) {
                ecaRunner.evalRules(EntityEcaHandler.EV_CACHE_CLEAR, EntityEcaHandler.OP_REMOVE, value, false);
                this.clearCacheLine(value);
            }


            if (testMode) {
                if (removedValue != null) {
                    storeForTestRollback(new TestOperation(OperationType.DELETE, removedValue));
                }
            }

            this.saveEntitySyncRemoveInfo(value.getPrimaryKey());

            ecaRunner.evalRules(EntityEcaHandler.EV_RETURN, EntityEcaHandler.OP_REMOVE, value, false);
            TransactionUtil.commit(beganTransaction);
            return num;
        } catch (Exception e) {
            String errMsg = "Failure in removeValue operation for entity [" + value.getEntityName() + "]: " + e.toString() + ". Rolling back transaction.";
            Debug.logError(e, errMsg, module);
            TransactionUtil.rollback(beganTransaction, errMsg, e);
            throw new GenericEntityException(e);
        }
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#removeByAnd(java.lang.String, java.lang.Object)
     */
    @Override
    public int removeByAnd(String entityName, Object... fields) throws GenericEntityException {
        return removeByAnd(entityName, UtilMisc.<String, Object>toMap(fields));
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#removeByAnd(java.lang.String, java.util.Map)
     */
    @Override
    public int removeByAnd(String entityName, Map<String, ? extends Object> fields) throws GenericEntityException {
        return this.removeByAnd(entityName, fields, true);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#removeByAnd(java.lang.String, boolean, java.lang.Object)
     * @deprecated use {@link #removeByAnd(String entityName, Object... fields)}
     */
    @Override
    @Deprecated
    public int removeByAnd(String entityName, boolean doCacheClear, Object... fields) throws GenericEntityException {
        return removeByAnd(entityName, UtilMisc.<String, Object>toMap(fields), doCacheClear);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#removeByAnd(java.lang.String, java.util.Map, boolean)
     * @deprecated use {@link #removeByAnd(String entityName, Map<String, ? extends Object> fields)}}
     */
    @Override
    @Deprecated
    public int removeByAnd(String entityName, Map<String, ? extends Object> fields, boolean doCacheClear) throws GenericEntityException {
        EntityCondition ecl = EntityCondition.makeCondition(fields);
        return removeByCondition(entityName, ecl, doCacheClear);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#removeByCondition(java.lang.String, org.ofbiz.entity.condition.EntityCondition)
     */
    @Override
    public int removeByCondition(String entityName, EntityCondition condition) throws GenericEntityException {
        return this.removeByCondition(entityName, condition, true);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#removeByCondition(java.lang.String, org.ofbiz.entity.condition.EntityCondition, boolean)
     * @deprecated use {@link #removeByCondition(String entityName, EntityCondition condition)}
     */
    @Override
    @Deprecated
    public int removeByCondition(String entityName, EntityCondition condition, boolean doCacheClear) throws GenericEntityException {
        boolean beganTransaction = false;
        try {
            if (alwaysUseTransaction) {
                beganTransaction = TransactionUtil.begin();
            }

            ModelEntity modelEntity = getModelReader().getModelEntity(entityName);
            GenericHelper helper = getEntityHelper(entityName);

            List<GenericValue> removedEntities = null;
            if (testMode) {
                removedEntities = this.findList(entityName, condition, null, null, null, false);
            }

            int rowsAffected = helper.removeByCondition(this, modelEntity, condition);
            if (rowsAffected > 0 && doCacheClear) {
                this.clearCacheLine(entityName);
            }

            if (testMode) {
                for (GenericValue entity : removedEntities) {
                    storeForTestRollback(new TestOperation(OperationType.DELETE, entity));
                }
            }
            TransactionUtil.commit(beganTransaction);
            return rowsAffected;
        } catch (Exception e) {
            String errMsg = "Failure in removeByCondition operation for entity [" + entityName + "]: " + e.toString() + ". Rolling back transaction.";
            Debug.logError(e, errMsg, module);
            TransactionUtil.rollback(beganTransaction, errMsg, e);
            throw new GenericEntityException(e);
        }
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#removeRelated(java.lang.String, org.ofbiz.entity.GenericValue)
     */
    @Override
    public int removeRelated(String relationName, GenericValue value) throws GenericEntityException {
        return this.removeRelated(relationName, value, true);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#removeRelated(java.lang.String, org.ofbiz.entity.GenericValue, boolean)
     * @deprecated use {@link #removeRelated(String relationName, GenericValue value)}
     */
    @Override
    @Deprecated
    public int removeRelated(String relationName, GenericValue value, boolean doCacheClear) throws GenericEntityException {
        ModelEntity modelEntity = value.getModelEntity();
        ModelRelation relation = modelEntity.getRelation(relationName);

        if (relation == null) {
            throw new GenericModelException("Could not find relation for relationName: " + relationName + " for value " + value);
        }

        Map<String, Object> fields = new HashMap<String, Object>();
        for (ModelKeyMap keyMap : relation.getKeyMaps()) {
            fields.put(keyMap.getRelFieldName(), value.get(keyMap.getFieldName()));
        }

        return this.removeByAnd(relation.getRelEntityName(), fields, doCacheClear);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#refresh(org.ofbiz.entity.GenericValue)
     */
    @Override
    public void refresh(GenericValue value) throws GenericEntityException {
        this.refresh(value, true);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#refresh(org.ofbiz.entity.GenericValue, boolean)
     * @deprecated use {@link #refresh(GenericValue value)}
     */
    @Override
    @Deprecated
    public void refresh(GenericValue value, boolean doCacheClear) throws GenericEntityException {
        if (doCacheClear) {
            // always clear cache before the operation
            clearCacheLine(value);
        }
        GenericPK pk = value.getPrimaryKey();
        GenericValue newValue = this.findOne(pk.getEntityName(), pk, false);
        value.refreshFromValue(newValue);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#refreshFromCache(org.ofbiz.entity.GenericValue)
     */
    @Override
    public void refreshFromCache(GenericValue value) throws GenericEntityException {
        GenericPK pk = value.getPrimaryKey();
        GenericValue newValue = findOne(pk.getEntityName(), pk, true);
        value.refreshFromValue(newValue);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#storeByCondition(java.lang.String, java.util.Map, org.ofbiz.entity.condition.EntityCondition)
     */
    @Override
    public int storeByCondition(String entityName, Map<String, ? extends Object> fieldsToSet, EntityCondition condition) throws GenericEntityException {
        return storeByCondition(entityName, fieldsToSet, condition, true);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#storeByCondition(java.lang.String, java.util.Map, org.ofbiz.entity.condition.EntityCondition, boolean)
     * @deprecated use {@link #storeByCondition(String entityName, Map<String, ? extends Object> fieldsToSet, EntityCondition condition)}
     */
    @Override
    @Deprecated
    public int storeByCondition(String entityName, Map<String, ? extends Object> fieldsToSet, EntityCondition condition, boolean doCacheClear) throws GenericEntityException {
        boolean beganTransaction = false;
        try {
            if (alwaysUseTransaction) {
                beganTransaction = TransactionUtil.begin();
            }

            ModelEntity modelEntity = getModelReader().getModelEntity(entityName);
            GenericHelper helper = getEntityHelper(entityName);

            List<GenericValue> updatedEntities = null;
            if (testMode) {
                updatedEntities = this.findList(entityName, condition, null, null, null, false);
            }

            int rowsAffected =  helper.storeByCondition(this, modelEntity, fieldsToSet, condition);
            if (rowsAffected > 0 && doCacheClear) {
                this.clearCacheLine(entityName);
            }

            if (testMode) {
                for (GenericValue entity : updatedEntities) {
                    storeForTestRollback(new TestOperation(OperationType.UPDATE, entity));
                }
            }
            TransactionUtil.commit(beganTransaction);
            return rowsAffected;
        } catch (Exception e) {
            String errMsg = "Failure in storeByCondition operation for entity [" + entityName + "]: " + e.toString() + ". Rolling back transaction.";
            Debug.logError(e, errMsg, module);
            TransactionUtil.rollback(beganTransaction, errMsg, e);
            throw new GenericEntityException(e);
        }
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#store(org.ofbiz.entity.GenericValue)
     */
    @Override
    public int store(GenericValue value) throws GenericEntityException {
        return this.store(value, true);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#store(org.ofbiz.entity.GenericValue, boolean)
     * @deprecated use {@link #store(GenericValue value)}
     */
    @Override
    @Deprecated
    public int store(GenericValue value, boolean doCacheClear) throws GenericEntityException {
        boolean beganTransaction = false;
        try {
            if (alwaysUseTransaction) {
                beganTransaction = TransactionUtil.begin();
            }

            EntityEcaRuleRunner<?> ecaRunner = this.getEcaRuleRunner(value.getEntityName());
            ecaRunner.evalRules(EntityEcaHandler.EV_VALIDATE, EntityEcaHandler.OP_STORE, value, false);
            GenericHelper helper = getEntityHelper(value.getEntityName());

            ecaRunner.evalRules(EntityEcaHandler.EV_RUN, EntityEcaHandler.OP_STORE, value, false);

            // if audit log on for any fields, save old value before the update so we still have both
            if (value.getModelEntity().getHasFieldWithAuditLog()) {
                createEntityAuditLogAll(value, true, false);
            }

            GenericValue updatedEntity = null;

            if (testMode) {
                updatedEntity = this.findOne(value.getEntityName(), value.getPrimaryKey(), false);
            }

            int retVal = helper.store(value);
            if (doCacheClear) {
                ecaRunner.evalRules(EntityEcaHandler.EV_CACHE_CLEAR, EntityEcaHandler.OP_STORE, value, false);
                this.clearCacheLine(value);
            }

            if (testMode) {
                storeForTestRollback(new TestOperation(OperationType.UPDATE, updatedEntity));
            }
            // refresh the valueObject to get the new version
            if (value.lockEnabled()) {
                refresh(value, doCacheClear);
            }

            ecaRunner.evalRules(EntityEcaHandler.EV_RETURN, EntityEcaHandler.OP_STORE, value, false);
            TransactionUtil.commit(beganTransaction);
            return retVal;
        } catch (Exception e) {
            String errMsg = "Failure in store operation for entity [" + value.getEntityName() + "]: " + e.toString() + ". Rolling back transaction.";
            Debug.logError(e, errMsg, module);
            TransactionUtil.rollback(beganTransaction, errMsg, e);
            throw new GenericEntityException(e);
        }
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#storeAll(java.util.List)
     */
    @Override
    public int storeAll(List<GenericValue> values) throws GenericEntityException {
        return this.storeAll(values, true);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#storeAll(java.util.List, boolean)
     * @deprecated use {@link #storeAll(List<GenericValue> values)}
     * TODO: JLR 2013-09-19 - doCacheClear refactoring: to be removed and replaced by  storeAll(List<GenericValue> values, boolean createDummyFks)
     */
    @Override
    @Deprecated
    public int storeAll(List<GenericValue> values, boolean doCacheClear) throws GenericEntityException {
        return this.storeAll(values, doCacheClear, false);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#storeAll(java.util.List, boolean, boolean)
     * TODO: JLR 2013-09-19 - doCacheClear refactoring: to be changed to storeAll(List<GenericValue> values, boolean createDummyFks)
     */
    @Override
    public int storeAll(List<GenericValue> values, boolean doCacheClear, boolean createDummyFks) throws GenericEntityException {
        if (values == null) {
            return 0;
        }

        int numberChanged = 0;

        boolean beganTransaction = false;
        try {
            beganTransaction = TransactionUtil.begin();

            for (GenericValue value: values) {
                String entityName = value.getEntityName();
                GenericPK primaryKey = value.getPrimaryKey();
                GenericHelper helper = getEntityHelper(entityName);

                // exists?
                // NOTE: don't use findByPrimaryKey because we don't want to the ECA events to fire and such
                if (!primaryKey.isPrimaryKey()) {
                    throw new GenericModelException("[GenericDelegator.storeAll] One of the passed primary keys is not a valid primary key: " + primaryKey);
                }
                GenericValue existing = null;
                try {
                    existing = helper.findByPrimaryKey(primaryKey);
                } catch (GenericEntityNotFoundException e) {
                    existing = null;
                }

                if (existing == null) {
                    if (createDummyFks) {
                        value.checkFks(true);
                    }
                    this.create(value, doCacheClear);
                    numberChanged++;
                } else {
                    // don't send fields that are the same, and if no fields have changed, update nothing
                    ModelEntity modelEntity = value.getModelEntity();
                    GenericValue toStore = GenericValue.create(this, modelEntity, value.getPrimaryKey());
                    boolean atLeastOneField = false;
                    Iterator<ModelField> nonPksIter = modelEntity.getNopksIterator();
                    while (nonPksIter.hasNext()) {
                        ModelField modelField = nonPksIter.next();
                        String fieldName = modelField.getName();
                        if (value.containsKey(fieldName)) {
                            Object fieldValue = value.get(fieldName);
                            Object oldValue = existing.get(fieldName);
                            if (!UtilObject.equalsHelper(oldValue, fieldValue)) {
                                toStore.put(fieldName, fieldValue);
                                atLeastOneField = true;
                            }
                        }
                    }

                    if (atLeastOneField) {
                        if (createDummyFks) {
                            value.checkFks(true);
                        }
                        numberChanged += this.store(toStore, doCacheClear);
                    }
                }
            }
            TransactionUtil.commit(beganTransaction);
            return numberChanged;
        } catch (Exception e) {
            String errMsg = "Failure in storeAll operation: " + e.toString() + ". Rolling back transaction.";
            Debug.logError(e, errMsg, module);
            TransactionUtil.rollback(beganTransaction, errMsg, e);
            throw new GenericEntityException(e);
        }
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#removeAll(java.lang.String)
     */
    @Override
    public int removeAll(String entityName) throws GenericEntityException {
        return removeByAnd(entityName, (Map<String, Object>) null);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#removeAll(java.util.List)
     */
    @Override
    public int removeAll(List<? extends GenericEntity> dummyPKs) throws GenericEntityException {
        return this.removeAll(dummyPKs, true);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#removeAll(java.util.List, boolean)
     * @deprecated use {@link #removeAll(List<? extends GenericEntity> dummyPKs)}
     */
    @Override
    @Deprecated
    public int removeAll(List<? extends GenericEntity> dummyPKs, boolean doCacheClear) throws GenericEntityException {
        if (dummyPKs == null) {
            return 0;
        }

        boolean beganTransaction = false;
        int numRemoved = 0;

        try {
            for (GenericEntity value: dummyPKs) {
                if (value.containsPrimaryKey()) {
                    numRemoved += this.removeByPrimaryKey(value.getPrimaryKey(), doCacheClear);
                } else {
                    numRemoved += this.removeByAnd(value.getEntityName(), value.getAllFields(), doCacheClear);
                }
            }
            TransactionUtil.commit(beganTransaction);
            return numRemoved;
        } catch (Exception e) {
            String errMsg = "Failure in removeAll operation: " + e.toString() + ". Rolling back transaction.";
            Debug.logError(e, errMsg, module);
            TransactionUtil.rollback(beganTransaction, errMsg, e);
            throw new GenericEntityException(e);
        }
    }

    // ======================================
    // ======= Find Methods =================
    // ======================================

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#findOne(java.lang.String, boolean, java.lang.Object)
     */
    @Override
    public GenericValue findOne(String entityName, boolean useCache, Object... fields) throws GenericEntityException {
        return findOne(entityName, UtilMisc.toMap(fields), useCache);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#findOne(java.lang.String, java.util.Map, boolean)
     */
    @Override
    public GenericValue findOne(String entityName, Map<String, ? extends Object> fields, boolean useCache) throws GenericEntityException {
        GenericPK primaryKey = this.makePK(entityName, fields);
        if (!primaryKey.isPrimaryKey()) {
            throw new GenericModelException("[GenericDelegator.findOne] Passed primary key is not a valid primary key: " + primaryKey);
        }
        EntityEcaRuleRunner<?> ecaRunner = this.getEcaRuleRunner(entityName);
        if (useCache) {
            ecaRunner.evalRules(EntityEcaHandler.EV_CACHE_CHECK, EntityEcaHandler.OP_FIND, primaryKey, false);
            GenericValue value = cache.get(primaryKey);
            if (value == GenericValue.NULL_VALUE) {
                return null;
            }
            if (value != null) {
                return value;
            }
        }

        boolean beganTransaction = false;
        try {
            if (alwaysUseTransaction) {
                beganTransaction = TransactionUtil.begin();
            }

            ecaRunner.evalRules(EntityEcaHandler.EV_VALIDATE, EntityEcaHandler.OP_FIND, primaryKey, false);

            GenericHelper helper = getEntityHelper(entityName);
            GenericValue value = null;

            ecaRunner.evalRules(EntityEcaHandler.EV_RUN, EntityEcaHandler.OP_FIND, primaryKey, false);
            try {
                value = helper.findByPrimaryKey(primaryKey);
            } catch (GenericEntityNotFoundException e) {
            }
            if (value != null) {
                value.setDelegator(this);
            }

            if (useCache) {
                if (value != null) {
                    ecaRunner.evalRules(EntityEcaHandler.EV_CACHE_PUT, EntityEcaHandler.OP_FIND, value, false);
                    this.putInPrimaryKeyCache(primaryKey, value);
                } else {
                    this.putInPrimaryKeyCache(primaryKey, GenericValue.NULL_VALUE);
                }
            }

            ecaRunner.evalRules(EntityEcaHandler.EV_RETURN, EntityEcaHandler.OP_FIND, (value == null ? primaryKey : value), false);
            TransactionUtil.commit(beganTransaction);
            return value;
        } catch (Exception e) {
            String errMsg = "Failure in findOne operation for entity [" + entityName + "]: " + e.toString() + ". Rolling back transaction.";
            Debug.logError(e, errMsg, module);
            TransactionUtil.rollback(beganTransaction, errMsg, e);
            throw new GenericEntityException(e);
        }
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#findByPrimaryKey(java.lang.String, java.util.Map)
     * @deprecated use {@link #findOne(String, Map, boolean)}
     */
    @Override
    @Deprecated
    public GenericValue findByPrimaryKey(String entityName, Map<String, ? extends Object> fields) throws GenericEntityException {
        return findOne(entityName, fields, false);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#findByPrimaryKeyCache(java.lang.String, java.lang.Object)
     * @deprecated use {@link #findOne(String, boolean, Object...)}
     */
    @Override
    @Deprecated
    public GenericValue findByPrimaryKeyCache(String entityName, Object... fields) throws GenericEntityException {
        return findByPrimaryKeyCache(entityName, UtilMisc.<String, Object>toMap(fields));
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#findByPrimaryKeyCache(java.lang.String, java.util.Map)
     * @deprecated use {@link #findOne(String, Map, boolean)}
     */
    @Override
    @Deprecated
    public GenericValue findByPrimaryKeyCache(String entityName, Map<String, ? extends Object> fields) throws GenericEntityException {
        return findOne(entityName, fields, true);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#findByPrimaryKeyPartial(org.ofbiz.entity.GenericPK, java.util.Set)
     */
    @Override
    public GenericValue findByPrimaryKeyPartial(GenericPK primaryKey, Set<String> keys) throws GenericEntityException {
        boolean beganTransaction = false;
        try {
            if (alwaysUseTransaction) {
                beganTransaction = TransactionUtil.begin();
            }

            EntityEcaRuleRunner<?> ecaRunner = this.getEcaRuleRunner(primaryKey.getEntityName());
            ecaRunner.evalRules(EntityEcaHandler.EV_VALIDATE, EntityEcaHandler.OP_FIND, primaryKey, false);

            GenericHelper helper = getEntityHelper(primaryKey.getEntityName());
            GenericValue value = null;

            if (!primaryKey.isPrimaryKey()) {
                throw new GenericModelException("[GenericDelegator.findByPrimaryKey] Passed primary key is not a valid primary key: " + primaryKey);
            }

            ecaRunner.evalRules(EntityEcaHandler.EV_RUN, EntityEcaHandler.OP_FIND, primaryKey, false);
            try {
                value = helper.findByPrimaryKeyPartial(primaryKey, keys);
            } catch (GenericEntityNotFoundException e) {
            }
            if (value != null) value.setDelegator(this);

            ecaRunner.evalRules(EntityEcaHandler.EV_RETURN, EntityEcaHandler.OP_FIND, primaryKey, false);
            TransactionUtil.commit(beganTransaction);
            return value;
        } catch (Exception e) {
            String errMsg = "Failure in findByPrimaryKeyPartial operation for entity [" + primaryKey.getEntityName() + "]: " + e.toString() + ". Rolling back transaction.";
            Debug.logError(e, errMsg, module);
            TransactionUtil.rollback(beganTransaction, errMsg, e);
            throw new GenericEntityException(e);
        }
    }

    /** Finds all Generic entities
     *@param entityName The Name of the Entity as defined in the entity XML file
     * @see org.ofbiz.entity.Delegator#findAll(java.lang.String, boolean)
     */
    @Override
    public List<GenericValue> findAll(String entityName, boolean useCache) throws GenericEntityException {
        return this.findList(entityName, null, null, null, null, useCache);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#findByAnd(java.lang.String, java.lang.Object)
     * @deprecated use {@link #findByAnd(String, Map, List, boolean)}
     */
    @Override
    @Deprecated
    public List<GenericValue> findByAnd(String entityName, Object... fields) throws GenericEntityException {
        EntityCondition ecl = EntityCondition.makeCondition(UtilMisc.<String, Object>toMap(fields));
        return this.findList(entityName, ecl, null, null, null, false);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#findByAnd(java.lang.String, java.util.Map)
     * @deprecated use {@link #findByAnd(String, Map, List, boolean)}
     */
    @Override
    @Deprecated
    public List<GenericValue> findByAnd(String entityName, Map<String, ? extends Object> fields) throws GenericEntityException {
        EntityCondition ecl = EntityCondition.makeCondition(fields);
        return this.findList(entityName, ecl, null, null, null, false);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#findByAnd(java.lang.String, java.util.Map, java.util.List)
     * @deprecated use {@link #findByAnd(String, Map, List, boolean)}
     */
    @Override
    @Deprecated
    public List<GenericValue> findByAnd(String entityName, Map<String, ? extends Object> fields, List<String> orderBy) throws GenericEntityException {
        EntityCondition ecl = EntityCondition.makeCondition(fields);
        return this.findList(entityName, ecl, null, orderBy, null, false);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#findByAndCache(java.lang.String, java.util.Map)
     * @deprecated use {@link #findByAnd(String, Map, List, boolean)}
     */
    @Override
    @Deprecated
    public List<GenericValue> findByAndCache(String entityName, Map<String, ? extends Object> fields) throws GenericEntityException {
        return this.findList(entityName, EntityCondition.makeCondition(fields), null, null, null, true);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#findByAndCache(java.lang.String, java.util.Map, java.util.List)
     * @deprecated use {@link #findByAnd(String, Map, List, boolean)}
     */
    @Override
    @Deprecated
    public List<GenericValue> findByAndCache(String entityName, Map<String, ? extends Object> fields, List<String> orderBy) throws GenericEntityException {
        return this.findList(entityName, EntityCondition.makeCondition(fields), null, orderBy, null, true);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#findByAnd(java.lang.String, java.util.Map, java.util.List, boolean)
     */
    @Override
    public List<GenericValue> findByAnd(String entityName, Map<String, ? extends Object> fields, List<String> orderBy, boolean useCache) throws GenericEntityException {
        return this.findList(entityName, EntityCondition.makeCondition(fields), null, orderBy, null, useCache);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#find(java.lang.String, org.ofbiz.entity.condition.EntityCondition, org.ofbiz.entity.condition.EntityCondition, java.util.Set, java.util.List, org.ofbiz.entity.util.EntityFindOptions)
     */
    @Override
    public EntityListIterator find(String entityName, EntityCondition whereEntityCondition, EntityCondition havingEntityCondition, Set<String> fieldsToSelect, List<String> orderBy, EntityFindOptions findOptions) throws GenericEntityException {

        // if there is no transaction throw an exception, we don't want to create a transaction here since closing it would mess up the ELI
        if (!TransactionUtil.isTransactionInPlace()) {
            //throw new GenericEntityException("ERROR: Cannot do a find that returns an EntityListIterator with no transaction in place. Wrap this call in a transaction.");

            //throwing an exception is a little harsh for now, just display a really big error message since we want to get all of these fixed...
            Exception newE = new Exception("Stack Trace");
            Debug.logError(newE, "ERROR: Cannot do a find that returns an EntityListIterator with no transaction in place. Wrap this call in a transaction.", module);
        }

        ModelEntity modelEntity = getModelReader().getModelEntity(entityName);
        GenericValue dummyValue = GenericValue.create(modelEntity);
        EntityEcaRuleRunner<?> ecaRunner = this.getEcaRuleRunner(modelEntity.getEntityName());
        ecaRunner.evalRules(EntityEcaHandler.EV_VALIDATE, EntityEcaHandler.OP_FIND, dummyValue, false);

        if (whereEntityCondition != null) {
            whereEntityCondition.checkCondition(modelEntity);
        }
        if (havingEntityCondition != null) {
            havingEntityCondition.checkCondition(modelEntity);
        }

        ecaRunner.evalRules(EntityEcaHandler.EV_RUN, EntityEcaHandler.OP_FIND, dummyValue, false);
        GenericHelper helper = getEntityHelper(modelEntity.getEntityName());
        EntityListIterator eli = helper.findListIteratorByCondition(this, modelEntity, whereEntityCondition, havingEntityCondition, fieldsToSelect, orderBy, findOptions);
        eli.setDelegator(this);

        ecaRunner.evalRules(EntityEcaHandler.EV_RETURN, EntityEcaHandler.OP_FIND, dummyValue, false);
        return eli;
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#findList(java.lang.String, org.ofbiz.entity.condition.EntityCondition, java.util.Set, java.util.List, org.ofbiz.entity.util.EntityFindOptions, boolean)
     */
    @Override
    public List<GenericValue> findList(String entityName, EntityCondition entityCondition, Set<String> fieldsToSelect, List<String> orderBy, EntityFindOptions findOptions, boolean useCache) throws GenericEntityException {

        EntityEcaRuleRunner<?> ecaRunner = null;
        GenericValue dummyValue = null;
        if (useCache) {
            ecaRunner = this.getEcaRuleRunner(entityName);
            ModelEntity modelEntity = getModelReader().getModelEntity(entityName);
            dummyValue = GenericValue.create(modelEntity);
            ecaRunner.evalRules(EntityEcaHandler.EV_CACHE_CHECK, EntityEcaHandler.OP_FIND, dummyValue, false);

            List<GenericValue> cacheList = this.cache.get(entityName, entityCondition, orderBy);
            if (cacheList != null) {
                return cacheList;
            }
        }

        boolean beganTransaction = false;
        try {
            if (alwaysUseTransaction) {
                beganTransaction = TransactionUtil.begin();
            }

            EntityListIterator eli = this.find(entityName, entityCondition, null, fieldsToSelect, orderBy, findOptions);
            eli.setDelegator(this);
            List<GenericValue> list = eli.getCompleteList();
            eli.close();

            if (useCache) {
                ecaRunner.evalRules(EntityEcaHandler.EV_CACHE_PUT, EntityEcaHandler.OP_FIND, dummyValue, false);
                this.cache.put(entityName, entityCondition, orderBy, list);
            }
            TransactionUtil.commit(beganTransaction);
            return list;
        } catch (Exception e) {
            String errMsg = "Failure in findByCondition operation for entity [" + entityName + "]: " + e.toString() + ". Rolling back transaction.";
            Debug.logError(e, errMsg, module);
            TransactionUtil.rollback(beganTransaction, errMsg, e);
            throw new GenericEntityException(e);
        }
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#findListIteratorByCondition(org.ofbiz.entity.model.DynamicViewEntity, org.ofbiz.entity.condition.EntityCondition, org.ofbiz.entity.condition.EntityCondition, java.util.Collection, java.util.List, org.ofbiz.entity.util.EntityFindOptions)
     */
    @Override
    public EntityListIterator findListIteratorByCondition(DynamicViewEntity dynamicViewEntity, EntityCondition whereEntityCondition, EntityCondition havingEntityCondition, Collection<String> fieldsToSelect, List<String> orderBy, EntityFindOptions findOptions) throws GenericEntityException {

        // if there is no transaction throw an exception, we don't want to create a transaction here since closing it would mess up the ELI
        if (!TransactionUtil.isTransactionInPlace()) {
            //throw new GenericEntityException("ERROR: Cannot do a find that returns an EntityListIterator with no transaction in place. Wrap this call in a transaction.");

            //throwing an exception is a little harsh for now, just display a really big error message since we want to get all of these fixed...
            Exception newE = new Exception("Stack Trace");
            Debug.logError(newE, "ERROR: Cannot do a find that returns an EntityListIterator with no transaction in place. Wrap this call in a transaction.", module);
        }

        ModelViewEntity modelViewEntity = dynamicViewEntity.makeModelViewEntity(this);
        if (whereEntityCondition != null) whereEntityCondition.checkCondition(modelViewEntity);
        if (havingEntityCondition != null) havingEntityCondition.checkCondition(modelViewEntity);

        GenericHelper helper = getEntityHelper(dynamicViewEntity.getOneRealEntityName());
        EntityListIterator eli = helper.findListIteratorByCondition(this, modelViewEntity, whereEntityCondition,
                havingEntityCondition, fieldsToSelect, orderBy, findOptions);
        eli.setDelegator(this);
        //TODO: add decrypt fields
        return eli;
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#findCountByCondition(java.lang.String, org.ofbiz.entity.condition.EntityCondition, org.ofbiz.entity.condition.EntityCondition, org.ofbiz.entity.util.EntityFindOptions)
     */
    @Override
    public long findCountByCondition(String entityName, EntityCondition whereEntityCondition,
            EntityCondition havingEntityCondition, EntityFindOptions findOptions) throws GenericEntityException {

        boolean beganTransaction = false;
        try {
            if (alwaysUseTransaction) {
                beganTransaction = TransactionUtil.begin();
            }

            ModelEntity modelEntity = getModelReader().getModelEntity(entityName);
            GenericValue dummyValue = GenericValue.create(modelEntity);
            EntityEcaRuleRunner<?> ecaRunner = this.getEcaRuleRunner(modelEntity.getEntityName());
            ecaRunner.evalRules(EntityEcaHandler.EV_VALIDATE, EntityEcaHandler.OP_FIND, dummyValue, false);

            if (whereEntityCondition != null) {
                whereEntityCondition.checkCondition(modelEntity);
            }
            if (havingEntityCondition != null) {
                havingEntityCondition.checkCondition(modelEntity);
            }

            ecaRunner.evalRules(EntityEcaHandler.EV_RUN, EntityEcaHandler.OP_FIND, dummyValue, false);
            GenericHelper helper = getEntityHelper(modelEntity.getEntityName());
            long count = helper.findCountByCondition(this, modelEntity, whereEntityCondition, havingEntityCondition, findOptions);

            ecaRunner.evalRules(EntityEcaHandler.EV_RETURN, EntityEcaHandler.OP_FIND, dummyValue, false);
            TransactionUtil.commit(beganTransaction);
            return count;
        } catch (Exception e) {
            String errMsg = "Failure in findListIteratorByCondition operation for entity [DynamicView]: " + e.toString() + ". Rolling back transaction.";
            Debug.logError(e, errMsg, module);
            TransactionUtil.rollback(beganTransaction, errMsg, e);
            throw new GenericEntityException(e);
        }
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#getMultiRelation(org.ofbiz.entity.GenericValue, java.lang.String, java.lang.String, java.util.List)
     */
    @Override
    public List<GenericValue> getMultiRelation(GenericValue value, String relationNameOne, String relationNameTwo, List<String> orderBy) throws GenericEntityException {
        boolean beganTransaction = false;
        try {
            if (alwaysUseTransaction) {
                beganTransaction = TransactionUtil.begin();
            }

            //TODO: add eca eval calls
            // traverse the relationships
            ModelEntity modelEntity = value.getModelEntity();
            ModelRelation modelRelationOne = modelEntity.getRelation(relationNameOne);
            ModelEntity modelEntityOne = getModelEntity(modelRelationOne.getRelEntityName());
            ModelRelation modelRelationTwo = modelEntityOne.getRelation(relationNameTwo);
            ModelEntity modelEntityTwo = getModelEntity(modelRelationTwo.getRelEntityName());

            GenericHelper helper = getEntityHelper(modelEntity);
            List<GenericValue> result = helper.findByMultiRelation(value, modelRelationOne, modelEntityOne, modelRelationTwo, modelEntityTwo, orderBy);
            TransactionUtil.commit(beganTransaction);
            return result;
        } catch (Exception e) {
            String errMsg = "Failure in getMultiRelation operation for entity [" + value.getEntityName() + "]: " + e.toString() + ". Rolling back transaction.";
            Debug.logError(e, errMsg, module);
            TransactionUtil.rollback(beganTransaction, errMsg, e);
            throw new GenericEntityException(e);
        }
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#getRelated(java.lang.String, java.util.Map, java.util.List, org.ofbiz.entity.GenericValue)
     * @deprecated use {@link #getRelated(String, Map, List, GenericValue, boolean)}
     */
    @Override
    @Deprecated
    public List<GenericValue> getRelated(String relationName, Map<String, ? extends Object> byAndFields, List<String> orderBy, GenericValue value) throws GenericEntityException {
        return getRelated(relationName, byAndFields, orderBy, value, false);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#getRelated(java.lang.String, java.util.Map, java.util.List, org.ofbiz.entity.GenericValue, boolean)
     */
    @Override
    public List<GenericValue> getRelated(String relationName, Map<String, ? extends Object> byAndFields, List<String> orderBy, GenericValue value, boolean useCache) throws GenericEntityException {
        ModelEntity modelEntity = value.getModelEntity();
        ModelRelation relation = modelEntity.getRelation(relationName);

        if (relation == null) {
            throw new GenericModelException("Could not find relation for relationName: " + relationName + " for value " + value);
        }

        // put the byAndFields (if not null) into the hash map first,
        // they will be overridden by value's fields if over-specified this is important for security and cleanliness
        Map<String, Object> fields = new HashMap<String, Object>();
        if (byAndFields != null) {
            fields.putAll(byAndFields);
        }
        for (ModelKeyMap keyMap : relation.getKeyMaps()) {
            fields.put(keyMap.getRelFieldName(), value.get(keyMap.getFieldName()));
        }

        return this.findByAnd(relation.getRelEntityName(), fields, orderBy, useCache);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#getRelatedDummyPK(java.lang.String, java.util.Map, org.ofbiz.entity.GenericValue)
     */
    @Override
    public GenericPK getRelatedDummyPK(String relationName, Map<String, ? extends Object> byAndFields, GenericValue value) throws GenericEntityException {
        ModelEntity modelEntity = value.getModelEntity();
        ModelRelation relation = modelEntity.getRelation(relationName);

        if (relation == null) {
            throw new GenericModelException("Could not find relation for relationName: " + relationName + " for value " + value);
        }
        ModelEntity relatedEntity = getModelReader().getModelEntity(relation.getRelEntityName());

        // put the byAndFields (if not null) into the hash map first,
        // they will be overridden by value's fields if over-specified this is important for security and cleanliness
        Map<String, Object> fields = new HashMap<String, Object>();
        if (byAndFields != null) {
            fields.putAll(byAndFields);
        }
        for (ModelKeyMap keyMap : relation.getKeyMaps()) {
            fields.put(keyMap.getRelFieldName(), value.get(keyMap.getFieldName()));
        }

        return GenericPK.create(this, relatedEntity, fields);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#getRelatedCache(java.lang.String, org.ofbiz.entity.GenericValue)
     * @deprecated use {@link #getRelated(String, Map, List, GenericValue, boolean)}
     */
    @Override
    @Deprecated
    public List<GenericValue> getRelatedCache(String relationName, GenericValue value) throws GenericEntityException {
        return getRelated(relationName, null, null, value, true);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#getRelatedOne(java.lang.String, org.ofbiz.entity.GenericValue, boolean)
     * @deprecated use {@link #getRelatedOne(String, GenericValue, boolean)}
     */
    @Override
    @Deprecated
    public GenericValue getRelatedOne(String relationName, GenericValue value) throws GenericEntityException {
        return this.getRelatedOne(relationName, value, false);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#getRelatedOneCache(java.lang.String, org.ofbiz.entity.GenericValue, boolean)
     * @deprecated use {@link #getRelatedOne(String, GenericValue, boolean)}
     */
    @Override
    @Deprecated
    public GenericValue getRelatedOneCache(String relationName, GenericValue value) throws GenericEntityException {
        return this.getRelatedOne(relationName, value, true);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#getRelatedOne(java.lang.String, org.ofbiz.entity.GenericValue, boolean)
     */
    @Override
    public GenericValue getRelatedOne(String relationName, GenericValue value, boolean useCache) throws GenericEntityException {
        ModelRelation relation = value.getModelEntity().getRelation(relationName);

        if (relation == null) {
            throw new GenericModelException("Could not find relation for relationName: " + relationName + " for value " + value);
        }
        if (!"one".equals(relation.getType()) && !"one-nofk".equals(relation.getType())) {
            throw new GenericModelException("Relation is not a 'one' or a 'one-nofk' relation: " + relationName + " of entity " + value.getEntityName());
        }

        Map<String, Object> fields = new HashMap<String, Object>();
        for (ModelKeyMap keyMap : relation.getKeyMaps()) {
            fields.put(keyMap.getRelFieldName(), value.get(keyMap.getFieldName()));
        }

        return this.findOne(relation.getRelEntityName(), fields, useCache);
    }


    // ======================================
    // ======= Cache Related Methods ========
    // ======================================

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#clearAllCaches()
     */
    @Override
    public void clearAllCaches() {
        this.clearAllCaches(true);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#clearAllCaches(boolean)
     */
    @Override
    public void clearAllCaches(boolean distribute) {
        cache.clear();

        if (!distribute) {
            return;
        }
        DistributedCacheClear dcc = getDistributedCacheClear();
        if (dcc != null) {
            dcc.clearAllCaches();
        }
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#clearCacheLine(java.lang.String)
     */
    @Override
    public void clearCacheLine(String entityName) {
        cache.remove(entityName);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#clearCacheLine(java.lang.String, java.lang.Object)
     */
    @Override
    public void clearCacheLine(String entityName, Object... fields) {
        clearCacheLine(entityName, UtilMisc.<String, Object>toMap(fields));
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#clearCacheLine(java.lang.String, java.util.Map)
     */
    @Override
    public void clearCacheLine(String entityName, Map<String, ? extends Object> fields) {
        // if no fields passed, do the all cache quickly and return
        if (fields == null) {
            cache.remove(entityName);
            return;
        }

        ModelEntity entity = this.getModelEntity(entityName);
        if (entity == null) {
            throw new IllegalArgumentException("[GenericDelegator.clearCacheLine] could not find entity for entityName: " + entityName);
        }
        //if never cached, then don't bother clearing
        if (entity.getNeverCache()) {
            return;
        }

        GenericValue dummyValue = GenericValue.create(this, entity, fields);
        this.clearCacheLineFlexible(dummyValue);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#clearCacheLineFlexible(org.ofbiz.entity.GenericEntity)
     */
    @Override
    public void clearCacheLineFlexible(GenericEntity dummyPK) {
        this.clearCacheLineFlexible(dummyPK, true);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#clearCacheLineFlexible(org.ofbiz.entity.GenericEntity, boolean)
     */
    @Override
    public void clearCacheLineFlexible(GenericEntity dummyPK, boolean distribute) {
        if (dummyPK != null) {
            //if never cached, then don't bother clearing
            if (dummyPK.getModelEntity().getNeverCache()) return;

            cache.remove(dummyPK);

            if (!distribute) {
                return;
            }

            DistributedCacheClear dcc = getDistributedCacheClear();
            if (dcc != null) {
                dcc.distributedClearCacheLineFlexible(dummyPK);
            }
        }
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#clearCacheLineByCondition(java.lang.String, org.ofbiz.entity.condition.EntityCondition)
     */
    @Override
    public void clearCacheLineByCondition(String entityName, EntityCondition condition) {
        clearCacheLineByCondition(entityName, condition, true);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#clearCacheLineByCondition(java.lang.String, org.ofbiz.entity.condition.EntityCondition, boolean)
     */
    @Override
    public void clearCacheLineByCondition(String entityName, EntityCondition condition, boolean distribute) {
        if (entityName != null) {
            //if never cached, then don't bother clearing
            if (getModelEntity(entityName).getNeverCache()) {
                return;
            }

            cache.remove(entityName, condition);

            if (!distribute) {
                return;
            }

            DistributedCacheClear dcc = getDistributedCacheClear();
            if (dcc != null) {
                dcc.distributedClearCacheLineByCondition(entityName, condition);
            }
        }
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#clearCacheLine(org.ofbiz.entity.GenericPK)
     */
    @Override
    public void clearCacheLine(GenericPK primaryKey) {
        this.clearCacheLine(primaryKey, true);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#clearCacheLine(org.ofbiz.entity.GenericPK, boolean)
     */
    @Override
    public void clearCacheLine(GenericPK primaryKey, boolean distribute) {
        if (primaryKey == null) {
            return;
        }

        //if never cached, then don't bother clearing
        if (primaryKey.getModelEntity().getNeverCache()) {
            return;
        }

        cache.remove(primaryKey);

        if (!distribute) {
            return;
        }

        DistributedCacheClear dcc = getDistributedCacheClear();
        if (dcc != null) {
            dcc.distributedClearCacheLine(primaryKey);
        }
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#clearCacheLine(org.ofbiz.entity.GenericValue)
     */
    @Override
    public void clearCacheLine(GenericValue value) {
        this.clearCacheLine(value, true);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#clearCacheLine(org.ofbiz.entity.GenericValue, boolean)
     */
    @Override
    public void clearCacheLine(GenericValue value, boolean distribute) {
        // Debug.logInfo("running clearCacheLine for value: " + value + ", distribute: " + distribute, module);
        if (value == null) {
            return;
        }

        //if never cached, then don't bother clearing
        if (value.getModelEntity().getNeverCache()) {
            return;
        }

        cache.remove(value);

        if (!distribute) {
            return;
        }

        DistributedCacheClear dcc = getDistributedCacheClear();
        if (dcc != null) {
            dcc.distributedClearCacheLine(value);
        }
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#clearAllCacheLinesByDummyPK(java.util.Collection)
     */
    @Override
    public void clearAllCacheLinesByDummyPK(Collection<GenericPK> dummyPKs) {
        if (dummyPKs == null) {
            return;
        }
        for (GenericEntity entity: dummyPKs) {
            this.clearCacheLineFlexible(entity);
        }
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#clearAllCacheLinesByValue(java.util.Collection)
     */
    @Override
    public void clearAllCacheLinesByValue(Collection<GenericValue> values) {
        if (values == null) {
            return;
        }
        for (GenericValue value: values) {
            this.clearCacheLine(value);
        }
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#getFromPrimaryKeyCache(org.ofbiz.entity.GenericPK)
     */
    @Override
    public GenericValue getFromPrimaryKeyCache(GenericPK primaryKey) {
        if (primaryKey == null) {
            return null;
        }
        GenericValue value = cache.get(primaryKey);
        if (value == GenericValue.NULL_VALUE) {
            return null;
        }
        return value;
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#putInPrimaryKeyCache(org.ofbiz.entity.GenericPK, org.ofbiz.entity.GenericValue)
     */
    @Override
    public void putInPrimaryKeyCache(GenericPK primaryKey, GenericValue value) {
        if (primaryKey == null) {
            return;
        }

        if (primaryKey.getModelEntity().getNeverCache()) {
            if (Debug.warningOn()) {
                Debug.logWarning("Tried to put a value of the " + value.getEntityName() + " entity in the BY PRIMARY KEY cache but this entity has never-cache set to true, not caching.", module);
            }
            return;
        }

        // before going into the cache, make this value immutable
        value.setImmutable();
        cache.put(primaryKey, value);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#putAllInPrimaryKeyCache(java.util.List)
     */
    @Override
    public void putAllInPrimaryKeyCache(List<GenericValue> values) {
        if (values == null) {
            return;
        }
        for (GenericValue value: values) {
            this.putInPrimaryKeyCache(value.getPrimaryKey(), value);
        }
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#setDistributedCacheClear(org.ofbiz.entity.util.DistributedCacheClear)
     */
    @Override
    public void setDistributedCacheClear(DistributedCacheClear distributedCacheClear) {
        this.distributedCacheClear.set(new ConstantFuture<DistributedCacheClear>(distributedCacheClear));
    }

    // ======= XML Related Methods ========
    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#readXmlDocument(java.net.URL)
     */
    @Override
    public List<GenericValue> readXmlDocument(URL url) throws SAXException, ParserConfigurationException, java.io.IOException {
        if (url == null) {
            return null;
        }
        return this.makeValues(UtilXml.readXmlDocument(url, false));
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#makeValues(org.w3c.dom.Document)
     */
    @Override
    public List<GenericValue> makeValues(Document document) {
        if (document == null) {
            return null;
        }
        List<GenericValue> values = new LinkedList<GenericValue>();

        Element docElement = document.getDocumentElement();

        if (docElement == null) {
            return null;
        }
        if (!"entity-engine-xml".equals(docElement.getTagName())) {
            Debug.logError("[GenericDelegator.makeValues] Root node was not <entity-engine-xml>", module);
            throw new java.lang.IllegalArgumentException("Root node was not <entity-engine-xml>");
        }
        docElement.normalize();
        Node curChild = docElement.getFirstChild();

        if (curChild != null) {
            do {
                if (curChild.getNodeType() == Node.ELEMENT_NODE) {
                    Element element = (Element) curChild;
                    GenericValue value = this.makeValue(element);

                    if (value != null) {
                        values.add(value);
                    }
                }
            } while ((curChild = curChild.getNextSibling()) != null);
        } else {
            Debug.logWarning("[GenericDelegator.makeValues] No child nodes found in document.", module);
        }

        return values;
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#makePK(org.w3c.dom.Element)
     */
    @Override
    public GenericPK makePK(Element element) {
        GenericValue value = makeValue(element);

        return value.getPrimaryKey();
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#makeValue(org.w3c.dom.Element)
     */
    @Override
    public GenericValue makeValue(Element element) {
        if (element == null) {
            return null;
        }
        String entityName = element.getTagName();

        // if a dash or colon is in the tag name, grab what is after it
        if (entityName.indexOf('-') > 0) {
            entityName = entityName.substring(entityName.indexOf('-') + 1);
        }
        if (entityName.indexOf(':') > 0) {
            entityName = entityName.substring(entityName.indexOf(':') + 1);
        }
        GenericValue value = this.makeValue(entityName);

        ModelEntity modelEntity = value.getModelEntity();

        Iterator<ModelField> modelFields = modelEntity.getFieldsIterator();

        while (modelFields.hasNext()) {
            ModelField modelField = modelFields.next();
            String name = modelField.getName();
            String attr = element.getAttribute(name);

            if (UtilValidate.isNotEmpty(attr)) {
                // GenericEntity.makeXmlElement() sets null values to GenericEntity.NULL_FIELD.toString(), so look for
                //     that and treat it as null
                if (GenericEntity.NULL_FIELD.toString().equals(attr)) {
                    value.set(name, null);
                } else {
                    value.setString(name, attr);
                }
            } else {
                // if no attribute try a subelement
                Element subElement = UtilXml.firstChildElement(element, name);

                if (subElement != null) {
                    value.setString(name, UtilXml.elementValue(subElement));
                }
            }
        }

        return value;
    }

    // ======= Misc Methods ========

    protected static class EntityEcaRuleRunner<T> {
        protected EntityEcaHandler<T> entityEcaHandler;
        protected Map<String, List<T>> eventMap;

        protected EntityEcaRuleRunner(EntityEcaHandler<T> entityEcaHandler, Map<String, List<T>> eventMap) {
            this.entityEcaHandler = entityEcaHandler;
            this.eventMap = eventMap;
        }

        protected void evalRules(String event, String currentOperation, GenericEntity value, boolean isError) throws GenericEntityException {
            if (entityEcaHandler == null) {
                return;
            }
            //if (!"find".equals(currentOperation)) {
            //    Debug.logWarning("evalRules for entity " + value.getEntityName() + ", currentOperation " + currentOperation + ", event " + event, module);
            //}
            entityEcaHandler.evalRules(currentOperation, eventMap, event, value, isError);
        }
    }

    protected EntityEcaRuleRunner<?> getEcaRuleRunner(String entityName) {
        if (this.testRollbackInProgress) {
            return createEntityEcaRuleRunner(null, null);
        }
        return createEntityEcaRuleRunner(getEntityEcaHandler(), entityName);
    }

    protected static <T> EntityEcaRuleRunner<T> createEntityEcaRuleRunner(EntityEcaHandler<T> entityEcaHandler, String entityName) {
        return new EntityEcaRuleRunner<T>(entityEcaHandler, entityEcaHandler != null ? entityEcaHandler.getEntityEventMap(entityName) : null);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#setEntityEcaHandler(org.ofbiz.entity.eca.EntityEcaHandler)
     */
    @Override
    public <T> void setEntityEcaHandler(EntityEcaHandler<T> entityEcaHandler) {
        this.entityEcaHandler.set(new ConstantFuture<EntityEcaHandler<?>>(entityEcaHandler));
        this.warnNoEcaHandler = false;
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#getEntityEcaHandler()
     */
    @Override
    public <T> EntityEcaHandler<T> getEntityEcaHandler() {
        Future<EntityEcaHandler<?>> future = this.entityEcaHandler.get();
        try {
            return UtilGenerics.cast(future != null ? future.get() : null);
        } catch (ExecutionException e) {
            Debug.logError(e, "Could not fetch EntityEcaHandler from the asynchronous instantiation", module);
        } catch (InterruptedException e) {
            Debug.logError(e, "Could not fetch EntityEcaHandler from the asynchronous instantiation", module);
        }
        return null;
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#getNextSeqId(java.lang.String)
     */
    @Override
    public String getNextSeqId(String seqName) {
        return this.getNextSeqId(seqName, 1);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#getNextSeqId(java.lang.String, long)
     */
    @Override
    public String getNextSeqId(String seqName, long staggerMax) {
        Long nextSeqLong = this.getNextSeqIdLong(seqName, staggerMax);

        if (nextSeqLong == null) {
            // NOTE: the getNextSeqIdLong method SHOULD throw a runtime exception when no sequence value is found, which means we should never see it get here
            throw new IllegalArgumentException("Could not get next sequenced ID for sequence name: " + seqName);
        }

        if (UtilValidate.isNotEmpty(this.delegatorInfo.getSequencedIdPrefix())) {
            return this.delegatorInfo.getSequencedIdPrefix() + nextSeqLong.toString();
        } else {
            return nextSeqLong.toString();
        }
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#getNextSeqIdLong(java.lang.String)
     */
    @Override
    public Long getNextSeqIdLong(String seqName) {
        return this.getNextSeqIdLong(seqName, 1);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#getNextSeqIdLong(java.lang.String, long)
     */
    public Long getNextSeqIdLong(String seqName, long staggerMax) {
        try {
            SequenceUtil sequencer = this.AtomicRefSequencer.get();
            if (sequencer == null) {
                ModelEntity seqEntity = this.getModelEntity("SequenceValueItem");
                sequencer = new SequenceUtil(this.getEntityHelperInfo("SequenceValueItem"), seqEntity, "seqName", "seqId");
                if (!AtomicRefSequencer.compareAndSet(null, sequencer)) {
                    sequencer = this.AtomicRefSequencer.get();
                }
            }
            ModelEntity seqModelEntity = null;
            try {
                seqModelEntity = getModelReader().getModelEntity(seqName);
            } catch (GenericEntityException e) {
                Debug.logInfo("Entity definition not found for sequence name " + seqName, module);
            }
            Long newSeqId = sequencer == null ? null : sequencer.getNextSeqId(seqName, staggerMax, seqModelEntity);
            return newSeqId;
        } catch (Exception e) {
            String errMsg = "Failure in getNextSeqIdLong operation for seqName [" + seqName + "]: " + e.toString() + ". Rolling back transaction.";
            Debug.logError(e, errMsg, module);
            throw new GeneralRuntimeException(errMsg, e);
        }
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#setSequencer(org.ofbiz.entity.util.SequenceUtil)
     */
    @Override
    public void setSequencer(SequenceUtil sequencer) {
        this.AtomicRefSequencer.set(sequencer);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#refreshSequencer()
     */
    @Override
    public void refreshSequencer() {
        this.AtomicRefSequencer.set(null);
    }


    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#setNextSubSeqId(org.ofbiz.entity.GenericValue, java.lang.String, int, int)
     */
    @Override
    public void setNextSubSeqId(GenericValue value, String seqFieldName, int numericPadding, int incrementBy) {
        if (value != null && UtilValidate.isEmpty(value.getString(seqFieldName))) {
            String sequencedIdPrefix = this.delegatorInfo.getSequencedIdPrefix();

            value.remove(seqFieldName);
            GenericValue lookupValue = this.makeValue(value.getEntityName());
            lookupValue.setPKFields(value);

            boolean beganTransaction = false;
            try {
                if (alwaysUseTransaction) {
                    beganTransaction = TransactionUtil.begin();
                }

                // get values in whatever order, we will go through all of them to find the highest value
                List<GenericValue> allValues = this.findByAnd(value.getEntityName(), lookupValue, null, false);
                //Debug.logInfo("Get existing values from entity " + value.getEntityName() + " with lookupValue: " + lookupValue + ", and the seqFieldName: " + seqFieldName + ", and the results are: " + allValues, module);
                Integer highestSeqVal = null;
                for (GenericValue curValue: allValues) {
                    String currentSeqId = curValue.getString(seqFieldName);
                    if (currentSeqId != null) {
                        if (UtilValidate.isNotEmpty(sequencedIdPrefix)) {
                            if (currentSeqId.startsWith(sequencedIdPrefix)) {
                                currentSeqId = currentSeqId.substring(sequencedIdPrefix.length());
                            } else {
                                continue;
                            }
                        }
                        try {
                            int seqVal = Integer.parseInt(currentSeqId);
                            if (highestSeqVal == null || seqVal > highestSeqVal.intValue()) {
                                highestSeqVal = Integer.valueOf(seqVal);
                            }
                        } catch (Exception e) {
                            Debug.logWarning("Error in make-next-seq-id converting SeqId [" + currentSeqId + "] in field: " + seqFieldName + " from entity: " + value.getEntityName() + " to a number: " + e.toString(), module);
                        }
                    }
                }

                int seqValToUse = (highestSeqVal == null ? 1 : highestSeqVal.intValue() + incrementBy);
                String newSeqId = sequencedIdPrefix + UtilFormatOut.formatPaddedNumber(seqValToUse, numericPadding);
                value.set(seqFieldName, newSeqId);

                // only commit the transaction if we started one...
                TransactionUtil.commit(beganTransaction);
            } catch (Exception e) {
                String errMsg = "Failure in setNextSubSeqId operation for entity [" + value.getEntityName() + "]: " + e.toString() + ". Rolling back transaction.";
                Debug.logError(e, errMsg, module);
                try {
                    // only rollback the transaction if we started one...
                    TransactionUtil.rollback(beganTransaction, errMsg, e);
                } catch (GenericEntityException e2) {
                    Debug.logError(e2, "[GenericDelegator] Could not rollback transaction: " + e2.toString(), module);
                }
                Debug.logError(e, "Error making next seqId", module);
            }
        }
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#encryptFields(java.util.List)
     */
    @Override
    @Deprecated
    public void encryptFields(List<? extends GenericEntity> entities) throws GenericEntityException {
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#encryptFields(org.ofbiz.entity.GenericEntity)
     */
    @Override
    @Deprecated
    public void encryptFields(GenericEntity entity) throws GenericEntityException {
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#encryptFieldValue(java.lang.String, java.lang.Object)
     */
    @Override
    @Deprecated
    public Object encryptFieldValue(String entityName, Object fieldValue) throws EntityCryptoException {
        return encryptFieldValue(entityName, null, fieldValue);
    }

    @Override
    public Object encryptFieldValue(String entityName, ModelField.EncryptMethod encryptMethod, Object fieldValue) throws EntityCryptoException {
        if (encryptMethod == null) {
            encryptMethod = ModelField.EncryptMethod.TRUE;
        }
        if (fieldValue != null) {
            if (fieldValue instanceof String && UtilValidate.isEmpty(fieldValue)) {
                return fieldValue;
            }
            return this.crypto.encrypt(entityName, encryptMethod, fieldValue);
        }
        return fieldValue;
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#encryptFieldValue(java.lang.String, java.lang.Object)
     */
    @Override
    public Object decryptFieldValue(String entityName, String encValue) throws EntityCryptoException {
        if (UtilValidate.isNotEmpty(encValue)) {
            return this.crypto.decrypt(entityName, encValue);
        }
        return null;
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#decryptFields(java.util.List)
     */
    @Override
    @Deprecated
    public void decryptFields(List<? extends GenericEntity> entities) throws GenericEntityException {
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#decryptFields(org.ofbiz.entity.GenericEntity)
     */
    @Override
    @Deprecated
    public void decryptFields(GenericEntity entity) throws GenericEntityException {
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#setEntityCrypto(org.ofbiz.entity.util.EntityCrypto)
     */
    @Override
    public void setEntityCrypto(EntityCrypto crypto) {
        this.crypto = crypto;
    }

    protected void absorbList(List<GenericValue> lst) {
        if (lst == null) {
            return;
        }
        for (GenericValue value: lst) {
            value.setDelegator(this);
        }
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#getCache()
     */
    @Override
    public Cache getCache() {
        return cache;
    }

    protected void createEntityAuditLogAll(GenericValue value, boolean isUpdate, boolean isRemove) throws GenericEntityException {
        Timestamp nowTimestamp = UtilDateTime.nowTimestamp();
        for (ModelField mf: value.getModelEntity().getFieldsUnmodifiable()) {
            if (mf.getEnableAuditLog()) {
                createEntityAuditLogSingle(value, mf, isUpdate, isRemove, nowTimestamp);
            }
        }
    }

    protected void createEntityAuditLogSingle(GenericValue value, ModelField mf, boolean isUpdate, boolean isRemove, Timestamp nowTimestamp) throws GenericEntityException {
        if (value == null || mf == null || !mf.getEnableAuditLog() || this.testRollbackInProgress) {
            return;
        }

        String newValueText = null;
        String oldValueText = null;

        GenericValue oldGv = null;
        if (isUpdate) {
            // it's an update, get it from the database
            oldGv = this.findOne(value.getEntityName(), value.getPrimaryKey(), false);
        } else if (isRemove) {
            oldGv = value;
        }
        if (oldGv == null) {
            if (isUpdate || isRemove) {
                oldValueText = "[ERROR] Old value not found even though it was an update or remove";
            }
        } else {
            // lookup old value
            Object oldValue = oldGv.get(mf.getName());
            if (oldValue != null) {
                oldValueText = oldValue.toString();
                if (oldValueText.length() > 250) {
                    oldValueText = oldValueText.substring(0, 250);
                }
            }
        }

        if (!isRemove) {
            Object newValue = value.get(mf.getName());
            if (newValue != null) {
                newValueText = newValue.toString();
                if (newValueText.length() > 250) {
                    newValueText = newValueText.substring(0, 250);
                }
            }
        }

        if (!(newValueText == null ? "" : newValueText).equals((oldValueText == null ? "" : oldValueText))) {
            // only save changed values
            GenericValue entityAuditLog = this.makeValue("EntityAuditLog");
            entityAuditLog.set("auditHistorySeqId", this.getNextSeqId("EntityAuditLog"));
            entityAuditLog.set("changedEntityName", value.getEntityName());
            entityAuditLog.set("changedFieldName", mf.getName());

            String pkCombinedValueText = value.getPkShortValueString();
            if (pkCombinedValueText.length() > 250) {
                // uh-oh, the string is too long!
                pkCombinedValueText = pkCombinedValueText.substring(0, 250);
            }
            entityAuditLog.set("pkCombinedValueText", pkCombinedValueText);
            entityAuditLog.set("newValueText", newValueText);
            entityAuditLog.set("oldValueText", oldValueText);
            entityAuditLog.set("changedDate", nowTimestamp);
            entityAuditLog.set("changedByInfo", getCurrentUserIdentifier());
            entityAuditLog.set("changedSessionInfo", getCurrentSessionIdentifier());
            this.create(entityAuditLog);
        }
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#cloneDelegator(java.lang.String)
     */
    @Override
    public Delegator cloneDelegator(String delegatorFullName) {
        // creates an exact clone of the delegator; except for the sequencer
        // note that this will not be cached and should be used only when
        // needed to change something for single instance (use).
        GenericDelegator newDelegator = new GenericDelegator();
        newDelegator.modelReader = this.modelReader;
        newDelegator.modelGroupReader = this.modelGroupReader;
        newDelegator.setDelegatorNames(UtilValidate.isNotEmpty(delegatorFullName) ? delegatorFullName : this.delegatorFullName);
        // set the delegatorBaseName to be the same so that configuration settings all work the same as the current
        //   delegator, allowing the new delegatorFullName to not match a delegator name in the entityengine.xml file
        newDelegator.delegatorBaseName = this.delegatorBaseName;
        newDelegator.delegatorInfo = this.delegatorInfo;
        newDelegator.cache = this.cache;
        newDelegator.distributedCacheClear.set(this.distributedCacheClear.get());
        newDelegator.originalDelegatorName = getOriginalDelegatorName();
        newDelegator.entityEcaHandler.set(this.entityEcaHandler.get());
        newDelegator.crypto = this.crypto;
        // In case this delegator is in testMode give it a reference to
        // the rollback list
        newDelegator.testMode = this.testMode;
        testOperationsUpdater.set(newDelegator, this.testOperations);
        // not setting the sequencer so that we have unique sequences.

        return newDelegator;
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#cloneDelegator()
     */
    @Override
    public Delegator cloneDelegator() {
        return this.cloneDelegator(this.delegatorFullName);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#makeTestDelegator(java.lang.String)
     */
    @Override
    public Delegator makeTestDelegator(String delegatorName) {
        GenericDelegator testDelegator = (GenericDelegator) this.cloneDelegator(delegatorName);
        testDelegator.entityEcaHandler.set(null);
        testDelegator.initEntityEcaHandler();
        testDelegator.setTestMode(true);
        return testDelegator;
    }

    private void setTestMode(boolean testMode) {
        this.testMode = testMode;
        if (testMode) {
            testOperationsUpdater.set(this, new LinkedBlockingDeque<TestOperation>());
        } else {
            this.testOperations.clear();
        }
    }

    private void storeForTestRollback(TestOperation testOperation) {
        if (!this.testMode || this.testRollbackInProgress) {
            throw new IllegalStateException("An attempt was made to store a TestOperation during rollback or outside of test mode");
        }
        this.testOperations.add(testOperation);
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#rollback()
     */
    @Override
    public void rollback() {
        if (!this.testMode) {
            Debug.logError("Rollback requested outside of testmode", module);
        }
        this.testMode = false;
        this.testRollbackInProgress = true;
        if (Debug.infoOn()) {
            Debug.logInfo("Rolling back " + testOperations.size() + " entity operations", module);
        }
        while (!this.testOperations.isEmpty()) {
            TestOperation testOperation = this.testOperations.pollLast();
            if (testOperation == null) {
                break;
            }
            try {
                if (testOperation.getOperation().equals(OperationType.INSERT)) {
                    this.removeValue(testOperation.getValue());
                } else if (testOperation.getOperation().equals(OperationType.UPDATE)) {
                    this.store(testOperation.getValue());
                } else if (testOperation.getOperation().equals(OperationType.DELETE)) {
                    this.create(testOperation.getValue());
                }
            } catch (GenericEntityException e) {
                Debug.logWarning(e.toString(), module);
            }
        }
        this.testOperations.clear();
        this.testRollbackInProgress = false;
        this.testMode = true;
    }

    public final class TestOperation {
        private final OperationType operation;
        private final GenericValue value;

        public TestOperation(OperationType operation, GenericValue value) {
            this.operation = operation;
            this.value = value;
        }

        public OperationType getOperation() {
            return operation;
        }

        public GenericValue getValue() {
            return value;
        }
    }

    /* (non-Javadoc)
     * @see org.ofbiz.entity.Delegator#initDistributedCacheClear()
     */
    @Override
    public void initDistributedCacheClear() {
        // Nothing to do if already assigned: the class loader has already been called, the class instantiated and casted to DistributedCacheClear
        if (this.distributedCacheClear.get() != null) {
            return;
        }

        Callable<DistributedCacheClear> creator = new Callable<DistributedCacheClear>() {
            public DistributedCacheClear call() {
                return createDistributedCacheClear();
            }
        };
        FutureTask<DistributedCacheClear> futureTask = new FutureTask<DistributedCacheClear>(creator);
        if (distributedCacheClear.compareAndSet(null, futureTask)) {
            ExecutionPool.GLOBAL_BATCH.submit(futureTask);
        }
    }

    protected DistributedCacheClear createDistributedCacheClear() {
        // If useDistributedCacheClear is false do nothing: the distributedCacheClear member field with a null value would cause dcc code to do nothing
        if (useDistributedCacheClear()) {
            //time to do some tricks with manual class loading that resolves circular dependencies, like calling services
            ClassLoader loader = Thread.currentThread().getContextClassLoader();
            // initialize the distributedCacheClear mechanism
            String distributedCacheClearClassName = this.delegatorInfo.getDistributedCacheClearClassName();

            try {
                Class<?> dccClass = loader.loadClass(distributedCacheClearClassName);
                DistributedCacheClear distributedCacheClear = UtilGenerics.cast(dccClass.newInstance());
                distributedCacheClear.setDelegator(this, this.delegatorInfo.getDistributedCacheClearUserLoginId());
                return distributedCacheClear;
            } catch (ClassNotFoundException e) {
                Debug.logWarning(e, "DistributedCacheClear class with name " + distributedCacheClearClassName + " was not found, distributed cache clearing will be disabled", module);
            } catch (InstantiationException e) {
                Debug.logWarning(e, "DistributedCacheClear class with name " + distributedCacheClearClassName + " could not be instantiated, distributed cache clearing will be disabled", module);
            } catch (IllegalAccessException e) {
                Debug.logWarning(e, "DistributedCacheClear class with name " + distributedCacheClearClassName + " could not be accessed (illegal), distributed cache clearing will be disabled", module);
            } catch (ClassCastException e) {
                Debug.logWarning(e, "DistributedCacheClear class with name " + distributedCacheClearClassName + " does not implement the DistributedCacheClear interface, distributed cache clearing will be disabled", module);
            }
        } else {
            Debug.logVerbose("Distributed Cache Clear System disabled for delegator [" + delegatorFullName + "]", module);
        }
        return null;
    }

    protected DistributedCacheClear getDistributedCacheClear() {
        Future<DistributedCacheClear> future = this.distributedCacheClear.get();
        try {
            return future != null ? future.get() : null;
        } catch (ExecutionException e) {
            Debug.logError(e, "Could not fetch DistributedCacheClear from the asynchronous instantiation", module);
        } catch (InterruptedException e) {
            Debug.logError(e, "Could not fetch DistributedCacheClear from the asynchronous instantiation", module);
        }
        return null;
    }

    @Override
    public boolean useDistributedCacheClear() {
        return this.delegatorInfo.getDistributedCacheClearEnabled();
    }

    @Override
    public String getCurrentSessionIdentifier() {
        List<String> curValList = getSessionIdentifierStack();
        return curValList.size() > 0 ? curValList.get(0) : null;
    }

    @Override
    public String getCurrentUserIdentifier() {
        List<String> curValList = getUserIdentifierStack();
        return curValList.size() > 0 ? curValList.get(0) : null;
    }
}
