/*******************************************************************************
 * 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.model;

import java.io.Serializable;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
import java.util.Set;

import org.ofbiz.base.util.Debug;
import org.ofbiz.base.util.StringUtil;
import org.ofbiz.base.util.UtilFormatOut;
import org.ofbiz.base.util.UtilTimer;
import org.ofbiz.base.util.UtilValidate;
import org.ofbiz.base.util.UtilXml;
import org.ofbiz.entity.condition.EntityComparisonOperator;
import org.ofbiz.entity.condition.EntityCondition;
import org.ofbiz.entity.condition.EntityConditionValue;
import org.ofbiz.entity.condition.EntityFieldValue;
import org.ofbiz.entity.condition.EntityFunction;
import org.ofbiz.entity.condition.EntityJoinOperator;
import org.ofbiz.entity.condition.EntityOperator;
import org.ofbiz.entity.jdbc.SqlJdbcUtil;
import org.ofbiz.entity.util.EntityUtil;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

/**
 * This class extends ModelEntity and provides additional information appropriate to view entities
 */
@SuppressWarnings("serial")
public class ModelViewEntity extends ModelEntity {
    public static final String module = ModelViewEntity.class.getName();

    private static final Map<String, String> functionPrefixMap = new HashMap<String, String>();
    private static final Set<String> numericFunctionsSet = new HashSet<String>(); // names of functions that return a numeric type
    static {
        functionPrefixMap.put("min", "MIN(");
        functionPrefixMap.put("max", "MAX(");
        functionPrefixMap.put("sum", "SUM(");
        functionPrefixMap.put("avg", "AVG(");
        functionPrefixMap.put("count", "COUNT(");
        functionPrefixMap.put("count-distinct", "COUNT(DISTINCT ");
        functionPrefixMap.put("upper", "UPPER(");
        functionPrefixMap.put("lower", "LOWER(");
        functionPrefixMap.put("extract-year", "EXTRACT(YEAR FROM ");
        functionPrefixMap.put("extract-month", "EXTRACT(MONTH FROM ");
        functionPrefixMap.put("extract-day", "EXTRACT(DAY FROM ");
        numericFunctionsSet.add("count");
        numericFunctionsSet.add("count-distinct");
        numericFunctionsSet.add("extract-year");
        numericFunctionsSet.add("extract-month");
        numericFunctionsSet.add("extract-day");
    }

    /** Contains member-entity alias name definitions: key is alias, value is ModelMemberEntity */
    protected Map<String, ModelMemberEntity> memberModelMemberEntities = new HashMap<String, ModelMemberEntity>();

    /** A list of all ModelMemberEntity entries; this is mainly used to preserve the original order of member entities from the XML file */
    protected List<ModelMemberEntity> allModelMemberEntities = new LinkedList<ModelMemberEntity>();

    /** Contains member-entity ModelEntities: key is alias, value is ModelEntity; populated with fields */
    protected Map<String, String> memberModelEntities = new HashMap<String, String>();

    /** List of alias-alls which act as a shortcut for easily pulling over member entity fields */
    protected List<ModelAliasAll> aliasAlls = new LinkedList<ModelAliasAll>();

    /** List of aliases with information in addition to what is in the standard field list */
    protected List<ModelAlias> aliases = new LinkedList<ModelAlias>();

    /** List of view links to define how entities are connected (or "joined") */
    protected List<ModelViewLink> viewLinks = new LinkedList<ModelViewLink>();

    /** A List of the Field objects for the View Entity, one for each GROUP BY field */
    protected List<ModelField> groupBys = new LinkedList<ModelField>();

    /** List of field names to group by */
    protected List<String> groupByFields = new LinkedList<String>();

    protected Map<String, ModelConversion[]> conversions = new HashMap<String, ModelConversion[]>();

    protected ViewEntityCondition viewEntityCondition = null;

    public ModelViewEntity(ModelReader reader, Element entityElement, UtilTimer utilTimer, ModelInfo def) {
        super(reader, entityElement, def);

        if (utilTimer != null) utilTimer.timerString("  createModelViewEntity: before general/basic info");
        this.populateBasicInfo(entityElement);

        if (utilTimer != null) utilTimer.timerString("  createModelViewEntity: before \"member-entity\"s");
        for (Element memberEntityElement: UtilXml.childElementList(entityElement, "member-entity")) {
            String alias = UtilXml.checkEmpty(memberEntityElement.getAttribute("entity-alias")).intern();
            String name = UtilXml.checkEmpty(memberEntityElement.getAttribute("entity-name")).intern();
            if (name.length() <= 0 || alias.length() <= 0) {
                Debug.logError("[new ModelViewEntity]: entity-alias or entity-name missing on member-entity element of the view-entity " + this.entityName, module);
            } else {
                ModelMemberEntity modelMemberEntity = new ModelMemberEntity(alias, name);
                this.addMemberModelMemberEntity(modelMemberEntity);
            }
        }

        // when reading aliases and alias-alls, just read them into the alias list, there will be a pass
        // after loading all entities to go back and fill in all of the ModelField entries
        for (Element aliasElement: UtilXml.childElementList(entityElement, "alias-all")) {
            ModelViewEntity.ModelAliasAll aliasAll = new ModelAliasAll(aliasElement);
            this.aliasAlls.add(aliasAll);
        }

        if (utilTimer != null) utilTimer.timerString("  createModelViewEntity: before aliases");
        for (Element aliasElement: UtilXml.childElementList(entityElement, "alias")) {
            ModelViewEntity.ModelAlias alias = new ModelAlias(aliasElement);
            this.aliases.add(alias);
        }

        for (Element viewLinkElement: UtilXml.childElementList(entityElement, "view-link")) {
            ModelViewLink viewLink = new ModelViewLink(this, viewLinkElement);
            this.addViewLink(viewLink);
        }

        if (utilTimer != null) utilTimer.timerString("  createModelEntity: before relations");
        this.populateRelated(reader, entityElement);

        Element entityConditionElement = UtilXml.firstChildElement(entityElement, "entity-condition");
        if (entityConditionElement != null) {
            this.viewEntityCondition = new ViewEntityCondition(this, null, entityConditionElement);
        }

        // before finishing, make sure the table name is null, this should help bring up errors early...
        this.tableName = null;
    }

    public ModelViewEntity(DynamicViewEntity dynamicViewEntity, ModelReader modelReader) {
        super(modelReader, new ModelInfo(
                dynamicViewEntity.getTitle(),
                ModelInfo.DEFAULT.getDescription(),
                ModelInfo.DEFAULT.getCopyright(),
                ModelInfo.DEFAULT.getAuthor(),
                ModelInfo.DEFAULT.getVersion(),
                dynamicViewEntity.getDefaultResourceName()));
        this.entityName = dynamicViewEntity.getEntityName();
        this.packageName = dynamicViewEntity.getPackageName();

        // member-entities
        Iterator<Map.Entry<String, ModelMemberEntity>> modelMemberEntitiesEntryIter = dynamicViewEntity.getModelMemberEntitiesEntryIter();
        while (modelMemberEntitiesEntryIter.hasNext()) {
            Map.Entry<String, ModelMemberEntity> entry = modelMemberEntitiesEntryIter.next();
            this.addMemberModelMemberEntity(entry.getValue());
        }

        // alias-alls
        dynamicViewEntity.addAllAliasAllsToList(this.aliasAlls);

        // aliases
        dynamicViewEntity.addAllAliasesToList(this.aliases);

        // view-links
        dynamicViewEntity.addAllViewLinksToList(this.viewLinks);

        // relations
        dynamicViewEntity.addAllRelationsToList(this.relations);

        dynamicViewEntity.addAllGroupByFieldsToList(this.groupByFields);

        // finalize stuff
        // note that this doesn't result in a call to populateReverseLinks because a DynamicViewEntity should never be cached anyway, and will blow up when attempting to make the reverse links to the DynamicViewEntity
        this.populateFieldsBasic(modelReader);
    }

    public Map<String, ModelMemberEntity> getMemberModelMemberEntities() {
        return this.memberModelMemberEntities;
    }

    public List<ModelMemberEntity> getAllModelMemberEntities() {
        return this.allModelMemberEntities;
    }

    public ModelMemberEntity getMemberModelMemberEntity(String alias) {
        return this.memberModelMemberEntities.get(alias);
    }

    public ModelEntity getMemberModelEntity(String alias) {
        String entityName = this.memberModelEntities.get(alias);
        return entityName != null ? this.getModelReader().getModelEntityNoCheck(entityName) : null;
    }

    public void addMemberModelMemberEntity(ModelMemberEntity modelMemberEntity) {
        this.memberModelMemberEntities.put(modelMemberEntity.getEntityAlias(), modelMemberEntity);
        this.allModelMemberEntities.add(modelMemberEntity);
    }

    public void removeMemberModelMemberEntity(String alias) {
        ModelMemberEntity modelMemberEntity = this.memberModelMemberEntities.remove(alias);

        if (modelMemberEntity == null) return;
        this.allModelMemberEntities.remove(modelMemberEntity);
    }

    /** The col-name of the Field, the alias of the field if this is on a view-entity */
    @Override
    public String getColNameOrAlias(String fieldName) {
        ModelField modelField = this.getField(fieldName);
        String fieldString = modelField.getColName();
        ModelViewEntity.ModelAlias alias = getAlias(fieldName);
        if (alias != null) {
            fieldString = alias.getColAlias();
        }
        return fieldString;
    }

    /** List of aliases with information in addition to what is in the standard field list */
    public ModelAlias getAlias(int index) {
        return this.aliases.get(index);
    }

    public ModelAlias getAlias(String name) {
        Iterator<ModelAlias> aliasIter = getAliasesIterator();
        while (aliasIter.hasNext()) {
            ModelAlias alias = aliasIter.next();
            if (alias.name.equals(name)) {
                return alias;
            }
        }
        return null;
    }

    public int getAliasesSize() {
        return this.aliases.size();
    }

    public Iterator<ModelAlias> getAliasesIterator() {
        return this.aliases.iterator();
    }

    public List<ModelAlias> getAliasesCopy() {
        List<ModelAlias> newList = new ArrayList<ModelAlias>(this.aliases);
        return newList;
    }

    public int getGroupBysSize() {
        return this.groupBys.size();
    }

    public List<ModelField> getGroupBysCopy() {
        return getGroupBysCopy(null);
    }

    public List<ModelField> getGroupBysCopy(List<ModelField> selectFields) {
        List<ModelField> newList = new ArrayList<ModelField>(this.groupBys.size());
        if (UtilValidate.isEmpty(selectFields)) {
            newList.addAll(this.groupBys);
        } else {
            for (ModelField groupByField: this.groupBys) {
                if (selectFields.contains(groupByField)) {
                    newList.add(groupByField);
                }
            }
        }
        return newList;
    }

    /** List of view links to define how entities are connected (or "joined") */
    public ModelViewLink getViewLink(int index) {
        return this.viewLinks.get(index);
    }

    public int getViewLinksSize() {
        return this.viewLinks.size();
    }

    public Iterator<ModelViewLink> getViewLinksIterator() {
        return this.viewLinks.iterator();
    }

    public List<ModelViewLink> getViewLinksCopy() {
        List<ModelViewLink> newList = new ArrayList<ModelViewLink>(this.viewLinks);
        return newList;
    }

    public void addViewLink(ModelViewLink viewLink) {
        this.viewLinks.add(viewLink);
    }

    public void populateViewEntityConditionInformation(ModelFieldTypeReader modelFieldTypeReader, List<EntityCondition> whereConditions, List<EntityCondition> havingConditions, List<String> orderByList, List<String> entityAliasStack) {
        if (entityAliasStack == null) {
            entityAliasStack = new LinkedList<String>();
        }

        if (this.viewEntityCondition != null) {
            EntityCondition whereCondition = this.viewEntityCondition.getWhereCondition(modelFieldTypeReader, entityAliasStack);
            if (whereCondition != null) {
                whereConditions.add(whereCondition);
            }

            EntityCondition havingCondition = this.viewEntityCondition.getHavingCondition(modelFieldTypeReader, entityAliasStack);
            if (havingCondition != null) {
                havingConditions.add(havingCondition);
            }

            // add the current one first so it overrides the lower level ones
            List<String> currentOrderByList = this.viewEntityCondition.getOrderByList();
            if (currentOrderByList != null) {
                orderByList.addAll(currentOrderByList);
            }
        }
    }

    @Deprecated @Override
    public String colNameString(String separator, String afterLast, boolean alias, ModelField... flds) {
        return colNameString(Arrays.asList(flds), separator, afterLast, alias);
    }

    @Override
    public StringBuilder colNameString(StringBuilder sb, String prefix, String separator, String afterLast, boolean alias, ModelField... flds) {
        return colNameString(Arrays.asList(flds), sb, prefix, separator, afterLast, alias);
    }

    @Deprecated @Override
    public String colNameString(List<ModelField> flds, String separator, String afterLast, boolean alias) {
        return colNameString(flds, new StringBuilder(), "", separator, afterLast, alias).toString();
    }

    @Override
    public StringBuilder colNameString(List<ModelField> flds, StringBuilder sb, String prefix, String separator, String afterLast, boolean alias) {
        if (flds.size() < 1) {
            return sb;
        }

        sb.append(prefix);
        Iterator<ModelField> fldsIt = flds.iterator();
        while (fldsIt.hasNext()) {
            ModelField field = fldsIt.next();
            sb.append(field.getColValue());
            if (alias) {
                ModelAlias modelAlias = this.getAlias(field.getName());
                if (modelAlias != null) {
                    sb.append(" AS ").append(modelAlias.getColAlias());
                }
            }
            if (fldsIt.hasNext()) {
                sb.append(separator);
            }
        }

        sb.append(afterLast);
        return sb;
    }

    protected ModelEntity aliasedModelEntity = new ModelEntity();

    public ModelEntity getAliasedModelEntity() {
        return this.aliasedModelEntity;
    }

    public ModelEntity getAliasedEntity(String entityAlias, ModelReader modelReader) {
        ModelMemberEntity modelMemberEntity = this.memberModelMemberEntities.get(entityAlias);
        if (modelMemberEntity == null) {
            Debug.logError("[" + this.getEntityName() + "]: No member entity with alias " + entityAlias + " found; this view-entity will NOT be usable...", module);
            return null;
        }

        String aliasedEntityName = modelMemberEntity.getEntityName();
        ModelEntity aliasedEntity = modelReader.getModelEntityNoCheck(aliasedEntityName);
        if (aliasedEntity == null) {
            Debug.logError("[" + this.getEntityName() + "]: [ModelViewEntity.populateFields] ERROR: could not find ModelEntity for entity name: " + aliasedEntityName, module);
            return null;
        }

        return aliasedEntity;
    }

    public ModelField getAliasedField(ModelEntity aliasedEntity, String field, ModelReader modelReader) {
        ModelField aliasedField = aliasedEntity.getField(field);
        if (aliasedField == null) {
            Debug.logError("[" + this.getEntityName() + "]: [ModelViewEntity.populateFields] ERROR: could not find ModelField for entity name: " + aliasedEntity.getEntityName() + " and field: " + field, module);
            return null;
        }
        return aliasedField;
    }

    public void populateFields(ModelReader modelReader) {
        populateFieldsBasic(modelReader);
        populateReverseLinks();
    }

    public void populateFieldsBasic(ModelReader modelReader) {
        for (Map.Entry<String, ModelMemberEntity> entry: memberModelMemberEntities.entrySet()) {

            ModelMemberEntity modelMemberEntity = entry.getValue();
            String aliasedEntityName = modelMemberEntity.getEntityName();
            ModelEntity aliasedEntity = modelReader.getModelEntityNoCheck(aliasedEntityName);
            if (aliasedEntity == null) {
                continue;
            }
            memberModelEntities.put(entry.getKey(), aliasedEntityName);
            Iterator<ModelField> aliasedFieldIterator = aliasedEntity.getFieldsIterator();
            while (aliasedFieldIterator.hasNext()) {
                ModelField aliasedModelField = aliasedFieldIterator.next();
                ModelField newModelField = ModelField.create(this, aliasedModelField.getDescription(), modelMemberEntity.getEntityAlias() + "." + aliasedModelField.getName(),
                        aliasedModelField.getType(), modelMemberEntity.getEntityAlias() + "." + aliasedModelField.getColName(), null, null, false, false, false, false,
                        false, aliasedModelField.getValidators());
                aliasedModelEntity.addField(newModelField);
            }
        }

        expandAllAliasAlls(modelReader);

        for (ModelAlias alias: aliases) {
            // show a warning if function is specified and groupBy is true
            if (UtilValidate.isNotEmpty(alias.function) && alias.groupBy) {
                Debug.logWarning("[" + this.getEntityName() + "]: The view-entity alias with name=" + alias.name + " has a function value and is specified as a group-by field; this may be an error, but is not necessarily.", module);
            }
            String description = alias.description;
            String name = alias.name;
            String type = "";
            String colName = "";
            String colValue = "";
            String fieldSet = "";
            boolean isNotNull = false;
            boolean isPk = false;
            ModelField.EncryptMethod encryptMethod = ModelField.EncryptMethod.FALSE;
            boolean isAutoCreatedInternal = false;
            boolean enableAuditLog = false;
            List<String> validators = null;
            if (alias.isComplexAlias()) {
                // if this is a complex alias, make a complex column name...
                StringBuilder colNameBuffer = new StringBuilder();
                StringBuilder fieldTypeBuffer = new StringBuilder();
                alias.makeAliasColName(colNameBuffer, fieldTypeBuffer, this, modelReader);
                colValue = colNameBuffer.toString();
                colName = ModelUtil.javaNameToDbName(alias.name);
                type = fieldTypeBuffer.toString();
                isPk = false;
                fieldSet = alias.getFieldSet();
            } else {
                ModelEntity aliasedEntity = getAliasedEntity(alias.entityAlias, modelReader);
                ModelField aliasedField = getAliasedField(aliasedEntity, alias.field, modelReader);
                if (aliasedField == null) {
                    Debug.logError("[" + this.getEntityName() + "]: [populateFields] ERROR: could not find ModelField for field name \"" +
                        alias.field + "\" on entity with name: " + aliasedEntity.getEntityName(), module);
                    continue;
                }
                if (alias.isPk != null) {
                    isPk = alias.isPk.booleanValue();
                } else {
                    isPk = aliasedField.getIsPk();
                }
                encryptMethod = aliasedField.getEncryptMethod();
                type = aliasedField.getType();
                validators = aliasedField.getValidators();
                colValue = alias.entityAlias + "." + SqlJdbcUtil.filterColName(aliasedField.getColName());
                colName = SqlJdbcUtil.filterColName(colValue);
                if (description.isEmpty()) {
                    description = aliasedField.getDescription();
                }
                if (alias.getFieldSet().isEmpty()) {
                    String aliasedFieldSet = aliasedField.getFieldSet();
                    if (!aliasedFieldSet.isEmpty()) {
                        StringBuilder fieldSetBuffer = new StringBuilder(alias.entityAlias);
                        fieldSetBuffer.append("_");
                        fieldSetBuffer.append(Character.toUpperCase(aliasedFieldSet.charAt(0)));
                        fieldSetBuffer.append(aliasedFieldSet.substring(1));
                        fieldSet = fieldSetBuffer.toString().intern();
                        Debug.logInfo("[" + this.getEntityName() + "]: copied field set on [" + name + "]: " + fieldSet, module);
                    }
                } else {
                    fieldSet = alias.getFieldSet();
                }
            }
            if (numericFunctionsSet.contains(alias.function)) {
                // if we have a numeric function we have to change the type
                type = "numeric";
            }
            if (UtilValidate.isNotEmpty(alias.function)) {
                String prefix = functionPrefixMap.get(alias.function);
                if (prefix == null) {
                    Debug.logWarning("[" + this.getEntityName() + "]: Specified alias function [" + alias.function + "] not valid; must be: min, max, sum, avg, count or count-distinct; using a column name with no function function", module);
                } else {
                    colValue = prefix + colValue + ")";
                }
            }
            ModelField field = ModelField.create(this, description, name, type, colName, colValue, fieldSet, isNotNull, isPk, encryptMethod, isAutoCreatedInternal, enableAuditLog, validators);
            // if this is a groupBy field, add it to the groupBys list
            if (alias.groupBy || groupByFields.contains(alias.name)) {
                this.groupBys.add(field);
            }
            addField(field);
        }
    }

    protected ModelConversion getOrCreateModelConversion(String aliasName) {
        ModelEntity member = getMemberModelEntity(aliasName);
        if (member == null) {
            String errMsg = "No member found for aliasName - " + aliasName;
            Debug.logWarning("[" + this.getEntityName() + "]: " + errMsg, module);
            throw new RuntimeException("[" + this.getEntityName() + "]: Cannot create View Entity: " + errMsg);
        }

        ModelConversion[] allConversions = conversions.get(member.getEntityName());
        if (allConversions == null) {
            ModelConversion conversion = new ModelConversion(aliasName, member);
            conversions.put(member.getEntityName(), new ModelConversion[] {conversion});
            return conversion;
        }
        for (ModelConversion conversion: allConversions) {
            if (conversion.aliasName.equals(aliasName)) {
                return conversion;
            }
        }
        ModelConversion[] newConversions = new ModelConversion[allConversions.length + 1];
        System.arraycopy(allConversions, 0, newConversions, 0, allConversions.length);
        ModelConversion conversion = new ModelConversion(aliasName, member);
        newConversions[allConversions.length] = conversion;
        conversions.put(member.getEntityName(), newConversions);
        return conversion;
    }

    public void populateReverseLinks() {
        Map<String, List<String>> containedModelFields = new HashMap<String, List<String>>();
        Iterator<ModelAlias> it = getAliasesIterator();
        while (it.hasNext()) {
            ModelViewEntity.ModelAlias alias = it.next();
            if (alias.isComplexAlias()) {
                // TODO: conversion for complex-alias needs to be implemented for cache and in-memory eval stuff to work correctly
                Debug.logWarning("[" + this.getEntityName() + "]: Conversion for complex-alias needs to be implemented for cache and in-memory eval stuff to work correctly, will not work for alias: " + alias.getName(), module);
            } else {
                ModelConversion conversion = getOrCreateModelConversion(alias.getEntityAlias());
                conversion.addConversion(alias.getField(), alias.getName());
            }

            List<String> aliases = containedModelFields.get(alias.getField());
            if (aliases == null) {
                aliases = new LinkedList<String>();
                containedModelFields.put(alias.getField(), aliases);
            }
            aliases.add(alias.getName());
        }

        Iterator<ModelViewLink> it2 = getViewLinksIterator();
        while (it2.hasNext()) {
            ModelViewEntity.ModelViewLink link = it2.next();

            String leftAlias = link.getEntityAlias();
            String rightAlias = link.getRelEntityAlias();
            ModelConversion leftConversion = getOrCreateModelConversion(leftAlias);
            ModelConversion rightConversion = getOrCreateModelConversion(rightAlias);
            Iterator<ModelKeyMap> it3 = link.getKeyMapsIterator();
            Debug.logVerbose(leftAlias + "<->" + rightAlias, module);
            while (it3.hasNext()) {
                ModelKeyMap mkm = it3.next();
                String leftFieldName = mkm.getFieldName();
                String rightFieldName = mkm.getRelFieldName();
                rightConversion.addAllAliasConversions(containedModelFields.get(leftFieldName), rightFieldName);
                leftConversion.addAllAliasConversions(containedModelFields.get(rightFieldName), leftFieldName);
            }
        }
        int[] currentIndex = new int[conversions.size()];
        int[] maxIndex = new int[conversions.size()];
        ModelConversion[][] allConversions = new ModelConversion[conversions.size()][];
        int i = 0;
        for (ModelConversion[] aliasConversions: conversions.values()) {
            currentIndex[i] = 0;
            maxIndex[i] = aliasConversions.length;
            allConversions[i] = new ModelConversion[aliasConversions.length];
            System.arraycopy(aliasConversions, 0, allConversions[i], 0, aliasConversions.length);
            i++;
        }
        int ptr = 0;
        ModelConversion[] currentConversions = new ModelConversion[conversions.size()];
        for (int j = 0, k; j < currentIndex.length; j++) {
            for (int l = 0; l < maxIndex[ j ]; l++) {
                while (true) {
                    for (i = 0, k = 0; i < currentIndex.length; i++) {
                        if (i == j && currentIndex[i] == l) continue;
                        currentConversions[k++] = allConversions[i][currentIndex[i]];
                    }
                    Debug.logVerbose(j + "," + l + ":" + Arrays.asList(currentConversions), module);
                    while (ptr < currentIndex.length && ++currentIndex[ptr] == maxIndex[ptr]) {
                        currentIndex[ptr] = 0;
                        ptr++;
                    }
                    if (ptr == currentIndex.length) break;
                    ptr = 0;
                }
            }
        }
        Debug.logVerbose(this + ":" + conversions, module);
    }

    public List<Map<String, Object>> convert(String fromEntityName, Map<String, ? extends Object> data) {
        ModelConversion[] conversions = this.conversions.get(fromEntityName);
        if (conversions == null) return null;
        List<Map<String, Object>> values = new LinkedList<Map<String, Object>>();
        for (ModelConversion conversion: conversions) {
            conversion.convert(values, data);
        }
        return values;
    }

    /**
     * Go through all aliasAlls and create an alias for each field of each member entity
     */
    private void expandAllAliasAlls(ModelReader modelReader) {
        for (ModelAliasAll aliasAll: aliasAlls) {
            String entityAlias = aliasAll.getEntityAlias();
            String prefix = aliasAll.getPrefix();
            String function = aliasAll.getFunction();
            boolean groupBy = aliasAll.getGroupBy();
            String aliasAllFieldSet = aliasAll.getFieldSet();

            ModelMemberEntity modelMemberEntity = memberModelMemberEntities.get(entityAlias);
            if (modelMemberEntity == null) {
                Debug.logError("[" + this.getEntityName() + "]: Member entity referred to in alias-all not found, ignoring: " + entityAlias, module);
                continue;
            }

            String aliasedEntityName = modelMemberEntity.getEntityName();
            ModelEntity aliasedEntity = modelReader.getModelEntityNoCheck(aliasedEntityName);
            if (aliasedEntity == null) {
                Debug.logError("[" + this.getEntityName() + "]: Entity referred to in member-entity " + entityAlias + " not found, ignoring: " + aliasedEntityName, module);
                continue;
            }

            List<String> entFieldList = aliasedEntity.getAllFieldNames();
            if (entFieldList == null) {
                Debug.logError("[" + this.getEntityName() + "]: Entity referred to in member-entity " + entityAlias + " has no fields, ignoring: " + aliasedEntityName, module);
                continue;
            }

            for (String fieldName: entFieldList) {
                // now merge the lists, leaving out any that duplicate an existing alias name
                String aliasName = fieldName;
                ModelField modelField = aliasedEntity.getField(fieldName);
                if (modelField.getIsAutoCreatedInternal()) {
                    // never auto-alias these
                    continue;
                }
                if (aliasAll.shouldExclude(fieldName)) {
                    // if specified as excluded, leave it out
                    continue;
                }

                if (UtilValidate.isNotEmpty(prefix)) {
                    StringBuilder newAliasBuffer = new StringBuilder(prefix);
                    //make sure the first letter is uppercase to delineate the field name
                    newAliasBuffer.append(Character.toUpperCase(aliasName.charAt(0)));
                    newAliasBuffer.append(aliasName.substring(1));
                    aliasName = newAliasBuffer.toString();
                }
                String fieldSet;
                if (UtilValidate.isEmpty(aliasAllFieldSet)) {
                    String aliasedFieldSet = modelField.getFieldSet();
                    if (UtilValidate.isNotEmpty(aliasedFieldSet)) {
                        StringBuilder fieldSetBuffer = new StringBuilder(entityAlias);
                        if (UtilValidate.isNotEmpty(prefix)) {
                            fieldSetBuffer.append(Character.toUpperCase(prefix.charAt(0)));
                            fieldSetBuffer.append(prefix.substring(1));
                        }
                        fieldSetBuffer.append(Character.toUpperCase(aliasedFieldSet.charAt(0)));
                        fieldSetBuffer.append(aliasedFieldSet.substring(1));
                        fieldSet = fieldSetBuffer.toString();
                    } else {
                        fieldSet = "";
                    }
                } else {
                    fieldSet = aliasAllFieldSet;
                }
                if (UtilValidate.isNotEmpty(fieldSet)) {
                    Debug.logInfo("[" + this.getEntityName() + "]: set field-set on [" + aliasName + "]: " + fieldSet, module);
                }

                ModelAlias existingAlias = this.getAlias(aliasName);
                if (existingAlias != null) {
                    //log differently if this is part of a view-link key-map because that is a common case when a field will be auto-expanded multiple times
                    boolean isInViewLink = false;
                    Iterator<ModelViewLink> viewLinkIter = this.getViewLinksIterator();
                    while (viewLinkIter.hasNext() && !isInViewLink) {
                        ModelViewLink modelViewLink = viewLinkIter.next();
                        boolean isRel = false;
                        if (modelViewLink.getRelEntityAlias().equals(aliasAll.getEntityAlias())) {
                            isRel = true;
                        } else if (!modelViewLink.getEntityAlias().equals(aliasAll.getEntityAlias())) {
                            // not the rel-entity-alias or the entity-alias, so move along
                            continue;
                        }
                        Iterator<ModelKeyMap> keyMapIter = modelViewLink.getKeyMapsIterator();
                        while (keyMapIter.hasNext() && !isInViewLink) {
                            ModelKeyMap modelKeyMap = keyMapIter.next();
                            if (!isRel && modelKeyMap.getFieldName().equals(fieldName)) {
                                isInViewLink = true;
                            } else if (isRel && modelKeyMap.getRelFieldName().equals(fieldName)) {
                                isInViewLink = true;
                            }
                        }
                    }

                    //already exists, oh well... probably an override, but log just in case
                    String warnMsg = "[" + this.getEntityName() + "]: Throwing out field alias in view entity because one already exists with the alias name [" + aliasName + "] and field name [" + modelMemberEntity.getEntityAlias() + "(" + aliasedEntity.getEntityName() + ")." + fieldName + "], existing field name is [" + existingAlias.getEntityAlias() + "." + existingAlias.getField() + "]";
                    if (isInViewLink) {
                        Debug.logVerbose(warnMsg, module);
                    } else {
                        Debug.logInfo(warnMsg, module);
                    }
                    continue;
                }

                ModelAlias expandedAlias = new ModelAlias(aliasAll.getEntityAlias(), aliasName, fieldName, ModelUtil.javaNameToDbName(UtilXml.checkEmpty(aliasName)), null, groupBy, function, fieldSet, true);
                expandedAlias.setDescription(modelField.getDescription());

                aliases.add(expandedAlias);
            }
        }
    }

    @Override
    public String toString() {
        return "ModelViewEntity[" + getEntityName() + "]";
    }

    public static final class ModelMemberEntity implements Serializable {
        protected final String entityAlias;
        protected final String entityName;

        public ModelMemberEntity(String entityAlias, String entityName) {
            this.entityAlias = entityAlias;
            this.entityName = entityName;
        }

        public String getEntityAlias() {
            return this.entityAlias;
        }

        public String getEntityName() {
            return this.entityName;
        }
    }

    public static final class ModelAliasAll implements Serializable, Iterable<String> {
        protected final String entityAlias;
        protected final String prefix;
        protected final Set<String> fieldsToExclude;
        protected final boolean groupBy;
        // is specified this alias is a calculated value; can be: min, max, sum, avg, count, count-distinct
        protected final String function;
        protected final String fieldSet;

        @Deprecated
        public ModelAliasAll(String entityAlias, String prefix) {
            this(entityAlias, prefix, false, null, null, null);
        }

        @Deprecated
        public ModelAliasAll(String entityAlias, String prefix, boolean groupBy, String function, Collection<String> excludes) {
            this(entityAlias, prefix, groupBy, function, null, excludes);
        }

        public ModelAliasAll(String entityAlias, String prefix, boolean groupBy, String function, String fieldSet, Collection<String> excludes) {
            this.entityAlias = entityAlias;
            this.prefix = prefix;
            this.groupBy = groupBy;
            this.function = function;
            this.fieldSet = fieldSet;
            if (UtilValidate.isNotEmpty(excludes)) {
                this.fieldsToExclude = new HashSet<String>(excludes.size());
                this.fieldsToExclude.addAll(excludes);
            } else {
                this.fieldsToExclude = null;
            }
        }

        public ModelAliasAll(Element aliasAllElement) {
            this.entityAlias = UtilXml.checkEmpty(aliasAllElement.getAttribute("entity-alias")).intern();
            this.prefix = UtilXml.checkEmpty(aliasAllElement.getAttribute("prefix")).intern();
            this.groupBy = "true".equals(UtilXml.checkEmpty(aliasAllElement.getAttribute("group-by")));
            this.function = UtilXml.checkEmpty(aliasAllElement.getAttribute("function"));
            this.fieldSet = UtilXml.checkEmpty(aliasAllElement.getAttribute("field-set")).intern();

            List<? extends Element> excludes = UtilXml.childElementList(aliasAllElement, "exclude");
            if (UtilValidate.isNotEmpty(excludes)) {
                this.fieldsToExclude = new HashSet<String>();
                for (Element excludeElement: excludes) {
                    this.fieldsToExclude.add(excludeElement.getAttribute("field").intern());
                }
            } else {
                this.fieldsToExclude = null;
            }

        }

        public String getEntityAlias() {
            return this.entityAlias;
        }

        public String getPrefix() {
            return this.prefix;
        }

        public boolean getGroupBy() {
            return this.groupBy;
        }

        public String getFunction() {
            return this.function;
        }

        public String getFieldSet() {
            return this.fieldSet;
        }

        public boolean shouldExclude(String fieldName) {
            if (this.fieldsToExclude == null) {
                return false;
            } else {
                return this.fieldsToExclude.contains(fieldName);
            }
        }

        public Iterator<String> iterator() {
            if (this.fieldsToExclude == null) {
                return Collections.<String>emptySet().iterator();
            } else {
                return fieldsToExclude.iterator();
            }
        }
    }

    public static final class ModelAlias implements Serializable {
        protected final String entityAlias;
        protected final String name;
        protected final String field;
        protected final String colAlias;
        // this is a Boolean object for a tri-state: null, true or false
        protected final Boolean isPk;
        protected final boolean groupBy;
        // is specified this alias is a calculated value; can be: min, max, sum, avg, count, count-distinct
        protected final String function;
        protected final String fieldSet;
        protected final boolean isFromAliasAll;
        protected ComplexAliasMember complexAliasMember;
        // The description for documentation purposes
        protected String description = "";

        public ModelAlias(Element aliasElement) {
            this.entityAlias = UtilXml.checkEmpty(aliasElement.getAttribute("entity-alias")).intern();
            this.name = UtilXml.checkEmpty(aliasElement.getAttribute("name")).intern();
            this.field = UtilXml.checkEmpty(aliasElement.getAttribute("field"), this.name).intern();
            this.colAlias = UtilXml.checkEmpty(aliasElement.getAttribute("col-alias"), ModelUtil.javaNameToDbName(UtilXml.checkEmpty(this.name))).intern();
            String primKeyValue = UtilXml.checkEmpty(aliasElement.getAttribute("prim-key"));

            if (UtilValidate.isNotEmpty(primKeyValue)) {
                this.isPk = Boolean.valueOf("true".equals(primKeyValue));
            } else {
                this.isPk = null;
            }
            this.groupBy = "true".equals(UtilXml.checkEmpty(aliasElement.getAttribute("group-by")));
            this.function = UtilXml.checkEmpty(aliasElement.getAttribute("function")).intern();
            this.fieldSet = UtilXml.checkEmpty(aliasElement.getAttribute("field-set")).intern();
            this.isFromAliasAll = false;
            this.description = UtilXml.checkEmpty(UtilXml.childElementValue(aliasElement, "description")).intern();

            Element complexAliasElement = UtilXml.firstChildElement(aliasElement, "complex-alias");
            if (complexAliasElement != null) {
                complexAliasMember = new ComplexAlias(complexAliasElement);
            }
        }

        @Deprecated
        public ModelAlias(String entityAlias, String name, String field, String colAlias, Boolean isPk, Boolean groupBy, String function) {
            this(entityAlias, name, field, colAlias, isPk, groupBy, function, null, false);
        }

        public ModelAlias(String entityAlias, String name, String field, String colAlias, Boolean isPk, Boolean groupBy, String function, String fieldSet) {
            this(entityAlias, name, field, colAlias, isPk, groupBy, function, fieldSet, false);
        }

        protected ModelAlias(String entityAlias, String name, String field, String colAlias, Boolean isPk, Boolean groupBy, String function, String fieldSet, boolean isFromAliasAll) {
            this.entityAlias = entityAlias;
            this.name = name;
            this.field = UtilXml.checkEmpty(field, this.name);
            this.colAlias = UtilXml.checkEmpty(colAlias, ModelUtil.javaNameToDbName(UtilXml.checkEmpty(this.name)));
            this.isPk = isPk;
            if (groupBy != null) {
                this.groupBy = groupBy.booleanValue();
            } else {
                this.groupBy = false;
            }
            this.function = function;
            this.fieldSet = UtilXml.checkEmpty(fieldSet).intern();
            this.isFromAliasAll = isFromAliasAll;
        }

        public void setComplexAliasMember(ComplexAliasMember complexAliasMember) {
            this.complexAliasMember = complexAliasMember;
        }

        public boolean isComplexAlias() {
            return complexAliasMember != null;
        }

        public void makeAliasColName(StringBuilder colNameBuffer, StringBuilder fieldTypeBuffer, ModelViewEntity modelViewEntity, ModelReader modelReader) {
            if (complexAliasMember != null) {
                complexAliasMember.makeAliasColName(colNameBuffer, fieldTypeBuffer, modelViewEntity, modelReader);
            }
        }

        public String getEntityAlias() {
            return this.entityAlias;
        }

        public String getName() {
            return this.name;
        }

        public String getColAlias() {
            return this.colAlias;
        }

        public String getField() {
            return this.field;
        }

        public Boolean getIsPk() {
            return this.isPk;
        }

        public boolean getGroupBy() {
            return this.groupBy;
        }

        public String getFunction() {
            return this.function;
        }

        public String getFieldSet() {
            return fieldSet;
        }

        public String getDescription() {
            return this.description;
        }

        public void setDescription(String description) {
            this.description = description;
        }

        public boolean getIsFromAliasAll() {
            return this.isFromAliasAll;
        }
    }

    public static interface ComplexAliasMember extends Serializable {
        public void makeAliasColName(StringBuilder colNameBuffer, StringBuilder fieldTypeBuffer, ModelViewEntity modelViewEntity, ModelReader modelReader);
    }

    public static final class ComplexAlias implements ComplexAliasMember {
        protected final List<ComplexAliasMember> complexAliasMembers = new LinkedList<ComplexAliasMember>();
        protected final String operator;

        public ComplexAlias(String operator) {
            this.operator = operator;
        }

        public ComplexAlias(Element complexAliasElement) {
            this.operator = complexAliasElement.getAttribute("operator").intern();
            // handle all complex-alias and complex-alias-field sub-elements
            for (Element subElement: UtilXml.childElementList(complexAliasElement)) {
                String nodeName = subElement.getNodeName();
                if ("complex-alias".equals(nodeName)) {
                    this.addComplexAliasMember(new ComplexAlias(subElement));
                } else if ("complex-alias-field".equals(nodeName)) {
                    this.addComplexAliasMember(new ComplexAliasField(subElement));
                }
            }
        }

        public void addComplexAliasMember(ComplexAliasMember complexAliasMember) {
            this.complexAliasMembers.add(complexAliasMember);
        }

        public void addAllComplexAliasMembers(List<ComplexAliasMember> complexAliasMembers) {
            this.complexAliasMembers.addAll(complexAliasMembers);
        }

        public void makeAliasColName(StringBuilder colNameBuffer, StringBuilder fieldTypeBuffer, ModelViewEntity modelViewEntity, ModelReader modelReader) {
            if (complexAliasMembers.size() == 0) {
                return;
            } else if (complexAliasMembers.size() == 1) {
                ComplexAliasMember complexAliasMember = complexAliasMembers.iterator().next();
                complexAliasMember.makeAliasColName(colNameBuffer, fieldTypeBuffer, modelViewEntity, modelReader);
            } else {
                colNameBuffer.append('(');
                Iterator<ComplexAliasMember> complexAliasMemberIter = complexAliasMembers.iterator();
                while (complexAliasMemberIter.hasNext()) {
                    ComplexAliasMember complexAliasMember = complexAliasMemberIter.next();
                    complexAliasMember.makeAliasColName(colNameBuffer, fieldTypeBuffer, modelViewEntity, modelReader);
                    if (complexAliasMemberIter.hasNext()) {
                        colNameBuffer.append(' ');
                        colNameBuffer.append(this.operator);
                        colNameBuffer.append(' ');
                    }
                }
                colNameBuffer.append(')');
            }
        }
    }

    public static final class ComplexAliasField implements ComplexAliasMember {
        protected final String entityAlias;
        protected final String field;
        protected final String defaultValue;
        protected final String function;
        protected final String value;

        public ComplexAliasField(Element complexAliasFieldElement) {
            this.entityAlias = complexAliasFieldElement.getAttribute("entity-alias").intern();
            this.field = complexAliasFieldElement.getAttribute("field").intern();
            this.defaultValue = complexAliasFieldElement.getAttribute("default-value").intern();
            this.function = complexAliasFieldElement.getAttribute("function").intern();
            this.value = complexAliasFieldElement.getAttribute("value").intern();
        }

        public ComplexAliasField(String entityAlias, String field, String defaultValue, String function) {
            this.entityAlias = entityAlias;
            this.field = field;
            this.defaultValue = defaultValue;
            this.function = function;
            this.value = null;
        }
        public ComplexAliasField(String entityAlias, String field, String defaultValue, String function, String value) {
            this.entityAlias = entityAlias;
            this.field = field;
            this.defaultValue = defaultValue;
            this.function = function;
            this.value = value;
        }

        /**
         * Make the alias as follows: function(coalesce(entityAlias.field, defaultValue))
         */
        public void makeAliasColName(StringBuilder colNameBuffer, StringBuilder fieldTypeBuffer, ModelViewEntity modelViewEntity, ModelReader modelReader) {
            if(UtilValidate.isEmpty(entityAlias) 
                    && UtilValidate.isEmpty(field) 
                    && UtilValidate.isNotEmpty(value)){
                colNameBuffer.append(value);
            }
            else {
                ModelEntity modelEntity = modelViewEntity.getAliasedEntity(entityAlias, modelReader);
                ModelField modelField = modelViewEntity.getAliasedField(modelEntity, field, modelReader);
                String colName = entityAlias + "." + modelField.getColName();
    
                if (UtilValidate.isNotEmpty(defaultValue)) {
                    colName = "COALESCE(" + colName + "," + defaultValue + ")";
                }
    
                if (UtilValidate.isNotEmpty(function)) {
                    String prefix = functionPrefixMap.get(function);
                    if (prefix == null) {
                        Debug.logWarning("[" + modelViewEntity.getEntityName() + "]: Specified alias function [" + function + "] not valid; must be: min, max, sum, avg, count or count-distinct; using a column name with no function function", module);
                    } else {
                        colName = prefix + colName + ")";
                    }
                }
    
                colNameBuffer.append(colName);
                //set fieldTypeBuffer if not already set
                if (fieldTypeBuffer.length() == 0) {
                    fieldTypeBuffer.append(modelField.getType());
                }
            }
        }
    }

    public static final class ModelViewLink implements Serializable, Iterable<ModelKeyMap> {
        protected final String entityAlias;
        protected final String relEntityAlias;
        protected final boolean relOptional;
        protected final List<ModelKeyMap> keyMaps = new LinkedList<ModelKeyMap>();
        protected final ViewEntityCondition viewEntityCondition;

        public ModelViewLink(ModelViewEntity modelViewEntity, Element viewLinkElement) {
            this.entityAlias = UtilXml.checkEmpty(viewLinkElement.getAttribute("entity-alias")).intern();
            this.relEntityAlias = UtilXml.checkEmpty(viewLinkElement.getAttribute("rel-entity-alias")).intern();
            // if anything but true will be false; ie defaults to false
            this.relOptional = "true".equals(viewLinkElement.getAttribute("rel-optional"));

            NodeList keyMapList = viewLinkElement.getElementsByTagName("key-map");
            for (int j = 0; j < keyMapList.getLength(); j++) {
                Element keyMapElement = (Element) keyMapList.item(j);
                ModelKeyMap keyMap = new ModelKeyMap(keyMapElement);

                if (keyMap != null) keyMaps.add(keyMap);
            }

            Element entityConditionElement = UtilXml.firstChildElement(viewLinkElement, "entity-condition");
            if (entityConditionElement != null) {
                this.viewEntityCondition = new ViewEntityCondition(modelViewEntity, this, entityConditionElement);
            } else {
                this.viewEntityCondition = null;
            }
        }

        @Deprecated
        public ModelViewLink(String entityAlias, String relEntityAlias, Boolean relOptional, ModelKeyMap... keyMaps) {
            this(entityAlias, relEntityAlias, relOptional, null, Arrays.asList(keyMaps));
        }

        @Deprecated
        public ModelViewLink(String entityAlias, String relEntityAlias, Boolean relOptional, List<ModelKeyMap> keyMaps) {
            this(entityAlias, relEntityAlias, relOptional, null, keyMaps);
        }

        public ModelViewLink(String entityAlias, String relEntityAlias, Boolean relOptional, ViewEntityCondition viewEntityCondition, ModelKeyMap... keyMaps) {
            this(entityAlias, relEntityAlias, relOptional, viewEntityCondition, Arrays.asList(keyMaps));
        }

        public ModelViewLink(String entityAlias, String relEntityAlias, Boolean relOptional, ViewEntityCondition viewEntityCondition, List<ModelKeyMap> keyMaps) {
            this.entityAlias = entityAlias;
            this.relEntityAlias = relEntityAlias;
            if (relOptional != null) {
                this.relOptional = relOptional.booleanValue();
            } else {
                this.relOptional = false;
            }
            this.keyMaps.addAll(keyMaps);
            this.viewEntityCondition = viewEntityCondition;
        }

        public String getEntityAlias() {
            return this.entityAlias;
        }

        public String getRelEntityAlias() {
            return this.relEntityAlias;
        }

        public boolean isRelOptional() {
            return this.relOptional;
        }

        public ModelKeyMap getKeyMap(int index) {
            return this.keyMaps.get(index);
        }

        public int getKeyMapsSize() {
            return this.keyMaps.size();
        }

        public Iterator<ModelKeyMap> getKeyMapsIterator() {
            return this.keyMaps.iterator();
        }

        public Iterator<ModelKeyMap> iterator() {
            return this.keyMaps.iterator();
        }

        public List<ModelKeyMap> getKeyMapsCopy() {
            List<ModelKeyMap> newList = new ArrayList<ModelKeyMap>(this.keyMaps);
            return newList;
        }

        public ViewEntityCondition getViewEntityCondition() {
            return this.viewEntityCondition;
        }
    }

    public final class ModelConversion implements Serializable {
        protected final String aliasName;
        protected final ModelEntity fromModelEntity;
        protected final Map<String, String> fieldMap = new HashMap<String, String>();
        protected final Set<String> wildcards = new HashSet<String>();

        public ModelConversion(String aliasName, ModelEntity fromModelEntity) {
            this.aliasName = aliasName;
            this.fromModelEntity = fromModelEntity;
            Iterator<ModelField> it = getFieldsIterator();
            while (it.hasNext()) {
                ModelField field = it.next();
                wildcards.add(field.getName());
            }
        }

        @Override
        public int hashCode() {
            return fromModelEntity.hashCode();
        }

        @Override
        public boolean equals(Object obj) {
            if (!(obj instanceof ModelConversion)) return false;
            ModelConversion other = (ModelConversion) obj;
            return fromModelEntity.equals(other.fromModelEntity);
        }

        public void addConversion(String fromFieldName, String toFieldName) {
            wildcards.remove(toFieldName);
            fieldMap.put(fromFieldName, toFieldName);
        }

        @Override
        public String toString() {
            //return fromModelEntity.getEntityName() + ":" + fieldMap + ":" + wildcards;
            return aliasName + "(" + fromModelEntity.getEntityName() + ")";
        }

        public void convert(List<Map<String, Object>> values, Map<String, ? extends Object> value) {
            Map<String, Object> newValue = new HashMap<String, Object>();
            for (Map.Entry<String, String> entry: fieldMap.entrySet()) {
                newValue.put(entry.getValue(), value.get(entry.getKey()));
            }
            for (String key: wildcards) {
                newValue.put(key, EntityOperator.WILDCARD);
            }
            values.add(newValue);
        }

        public void addAllAliasConversions(String fieldName, String... aliases) {
            addAllAliasConversions(Arrays.asList(aliases), fieldName);
        }

        public void addAllAliasConversions(List<String> aliases, String fieldName) {
            if (aliases != null) {
                for (String alias: aliases) {
                    addConversion(fieldName, alias);
                }
            }
        }
    }

    public static final class ViewEntityCondition {
        protected final ModelViewEntity modelViewEntity;
        protected final ModelViewLink modelViewLink;
        protected final boolean filterByDate;
        protected final boolean distinct;
        protected final List<String> orderByList;
        protected final ViewCondition whereCondition;
        protected final ViewCondition havingCondition;

        // TODO: add programatic constructor
        public ViewEntityCondition(ModelViewEntity modelViewEntity, ModelViewLink modelViewLink, Element element) {
            this.modelViewEntity = modelViewEntity;
            this.modelViewLink = modelViewLink;
            this.filterByDate = "true".equals(element.getAttribute("filter-by-date"));
            this.distinct = "true".equals(element.getAttribute("distinct"));
            // process order-by
            List<? extends Element> orderByElementList = UtilXml.childElementList(element, "order-by");
            if (orderByElementList.size() > 0) {
                orderByList = new ArrayList<String>(orderByElementList.size());
                for (Element orderByElement: orderByElementList) {
                    orderByList.add(orderByElement.getAttribute("field-name"));
                }
            } else {
                orderByList = null;
            }

            Element conditionExprElement = UtilXml.firstChildElement(element, "condition-expr");
            Element conditionListElement = UtilXml.firstChildElement(element, "condition-list");
            if (conditionExprElement != null) {
                this.whereCondition = new ViewConditionExpr(this, conditionExprElement);
            } else if (conditionListElement != null) {
                this.whereCondition = new ViewConditionList(this, conditionListElement);
            } else {
                this.whereCondition = null;
            }

            Element havingConditionListElement = UtilXml.firstChildElement(element, "having-condition-list");
            if (havingConditionListElement != null) {
                this.havingCondition = new ViewConditionList(this, havingConditionListElement);
            } else {
                this.havingCondition = null;
            }
        }

        public List<String> getOrderByList() {
            return this.orderByList;
        }

        public EntityCondition getWhereCondition(ModelFieldTypeReader modelFieldTypeReader, List<String> entityAliasStack) {

            List<EntityCondition> conditionList = new LinkedList<EntityCondition>();
            if(this.filterByDate) {
                conditionList.add(EntityUtil.getFilterByDateExpr());
            }
            if (this.whereCondition != null) {
                conditionList.add(whereCondition.createCondition(modelFieldTypeReader, entityAliasStack));
            }

            return EntityCondition.makeCondition(conditionList, EntityOperator.AND);
        }

        public EntityCondition getHavingCondition(ModelFieldTypeReader modelFieldTypeReader, List<String> entityAliasStack) {
            if (this.havingCondition != null) {
                return this.havingCondition.createCondition(modelFieldTypeReader, entityAliasStack);
            } else {
                return null;
            }
        }
    }

    public static interface ViewCondition extends Serializable {
        public EntityCondition createCondition(ModelFieldTypeReader modelFieldTypeReader, List<String> entityAliasStack);
    }

    public static final class ViewConditionExpr implements ViewCondition {
        protected final ViewEntityCondition viewEntityCondition;
        protected final String entityAlias;
        protected final String fieldName;
        protected final EntityComparisonOperator<?, ?> operator;
        protected final String relEntityAlias;
        protected final String relFieldName;
        protected final Object value;
        protected final boolean ignoreCase;

        // TODO: add programatic constructor
        public ViewConditionExpr(ViewEntityCondition viewEntityCondition, Element conditionExprElement) {
            this.viewEntityCondition = viewEntityCondition;
            String entityAlias = conditionExprElement.getAttribute("entity-alias");
            this.fieldName = conditionExprElement.getAttribute("field-name");

            String operator = UtilFormatOut.checkEmpty(conditionExprElement.getAttribute("operator"), "equals");
            try {
                this.operator = EntityOperator.lookupComparison(operator);
            } catch (IllegalArgumentException e) {
                throw new IllegalArgumentException("[" + this.viewEntityCondition.modelViewEntity.getEntityName() + "]: Could not find an entity operator for the name: " + operator);
            }
            String relEntityAlias = conditionExprElement.getAttribute("rel-entity-alias");
            String relFieldNameStr = conditionExprElement.getAttribute("rel-field-name");
            if (UtilValidate.isEmpty(relFieldNameStr)) {
                this.relFieldName = null;
            } else {
                this.relFieldName = relFieldNameStr;
            }
            String valueStr = conditionExprElement.getAttribute("value");
            if (UtilValidate.isEmpty(valueStr)) {
                this.value = null;
            } else {
                this.value = valueStr;
            }
            this.ignoreCase = "true".equals(conditionExprElement.getAttribute("ignore-case"));

            // if we are in a view-link, default to the entity-alias and rel-entity-alias there
            if (this.viewEntityCondition.modelViewLink != null) {
                if (UtilValidate.isEmpty(entityAlias)) {
                    entityAlias = this.viewEntityCondition.modelViewLink.getEntityAlias();
                }
                if (UtilValidate.isEmpty(relEntityAlias)) {
                    relEntityAlias = this.viewEntityCondition.modelViewLink.getRelEntityAlias();
                }
            }
            this.entityAlias = entityAlias;
            this.relEntityAlias = relEntityAlias;
        }

        public EntityCondition createCondition(ModelFieldTypeReader modelFieldTypeReader, List<String> entityAliasStack) {
            Object value = this.value;
            // If IN or BETWEEN operator, see if value is a literal list and split it
            if ((this.operator == EntityOperator.IN || this.operator == EntityOperator.BETWEEN)
                    && value instanceof String) {
                String delim = null;
                if (((String)value).indexOf("|") >= 0) {
                    delim = "|";
                } else if (((String)value).indexOf(",") >= 0) {
                    delim = ",";
                }
                if (UtilValidate.isNotEmpty(delim)) {
                    value = StringUtil.split((String) value, delim);
                }
            }

            EntityConditionValue lhs = EntityFieldValue.makeFieldValue(this.fieldName, this.entityAlias, entityAliasStack, this.viewEntityCondition.modelViewEntity);
            ModelField lhsField = lhs.getModelField(this.viewEntityCondition.modelViewEntity);
            if (lhsField == null) {
                throw new IllegalArgumentException("[" + this.viewEntityCondition.modelViewEntity.getEntityName() + "]: Error in Entity Find: could not find field [" + fieldName + "]");
            }

            // don't convert the field to the desired type if this is an IN or BETWEEN operator and we have a Collection
            if (!((this.operator == EntityOperator.IN || this.operator == EntityOperator.BETWEEN)
                    && value instanceof Collection<?>)) {
                // now to a type conversion for the target fieldName
                value = this.viewEntityCondition.modelViewEntity.convertFieldValue(lhsField, value, modelFieldTypeReader, new HashMap<String, Object>());
            }

            if (Debug.verboseOn()) Debug.logVerbose("[" + this.viewEntityCondition.modelViewEntity.getEntityName() + "]: Got value for fieldName [" + fieldName + "]: " + value, module);

            Object rhs = null;
            if (value != null) {
                rhs = value;
            } else {
                rhs = EntityFieldValue.makeFieldValue(this.relFieldName, this.relEntityAlias, entityAliasStack, this.viewEntityCondition.modelViewEntity);
            }

            EntityCondition entityCondition;

            if (this.operator == EntityOperator.NOT_EQUAL && value != null) {
                // since some databases don't consider nulls in != comparisons, explicitly include them
                // this makes more sense logically, but if anyone ever needs it to not behave this way we should add an "or-null" attribute that is true by default
                if (ignoreCase) {
                    entityCondition = EntityCondition.makeCondition(
                            EntityCondition.makeCondition(EntityFunction.UPPER(lhs), this.operator, EntityFunction.UPPER(rhs)),
                            EntityOperator.OR,
                            EntityCondition.makeCondition(lhs, EntityOperator.EQUALS, null));
                } else {
                    entityCondition = EntityCondition.makeCondition(
                            EntityCondition.makeCondition(lhs, this.operator, rhs),
                            EntityOperator.OR,
                            EntityCondition.makeCondition(lhs, EntityOperator.EQUALS, null));
                }
            } else if ( value == null && this.relFieldName == null && (this.operator == EntityOperator.EQUALS || this.operator == EntityOperator.NOT_EQUAL)) {
                entityCondition = EntityCondition.makeCondition(lhs, this.operator, null);
            } else {
                if (ignoreCase) {
                    // use the stuff to upper case both sides
                    entityCondition = EntityCondition.makeCondition(EntityFunction.UPPER(lhs), this.operator, EntityFunction.UPPER(rhs));
                } else {
                    entityCondition = EntityCondition.makeCondition(lhs, this.operator, rhs);
                }
            }

            if(this.viewEntityCondition.filterByDate) {
                List<EntityCondition> conditionList = new LinkedList<EntityCondition>();
                conditionList.add(entityCondition);
                conditionList.add(EntityUtil.getFilterByDateExpr());
                return EntityCondition.makeCondition(conditionList, EntityOperator.AND);
            } else {
                return entityCondition;
            }

        }
    }

    public static final class ViewConditionList implements ViewCondition {
        protected final ViewEntityCondition viewEntityCondition;
        protected final List<ViewCondition> conditionList = new LinkedList<ViewCondition>();
        protected final EntityJoinOperator operator;

        public ViewConditionList(ViewEntityCondition viewEntityCondition, Element conditionListElement) {
            this.viewEntityCondition = viewEntityCondition;
            String combine = conditionListElement.getAttribute("combine");
            try {
                this.operator = EntityOperator.lookupJoin(combine);
            } catch (IllegalArgumentException e) {
                throw new IllegalArgumentException("[" + this.viewEntityCondition.modelViewEntity.getEntityName() + "]: Could not find an entity operator for the name: " + combine);
            }

            List<? extends Element> subElements = UtilXml.childElementList(conditionListElement);
            for (Element subElement: subElements) {
                if ("condition-expr".equals(subElement.getNodeName())) {
                    conditionList.add(new ViewConditionExpr(this.viewEntityCondition, subElement));
                } else if ("condition-list".equals(subElement.getNodeName())) {
                    conditionList.add(new ViewConditionList(this.viewEntityCondition, subElement));
                } else {
                    throw new IllegalArgumentException("[" + this.viewEntityCondition.modelViewEntity.getEntityName() + "]: Invalid element with name [" + subElement.getNodeName() + "] found under a condition-list element.");
                }
            }
        }

        public ViewConditionList(ViewEntityCondition viewEntityCondition, String combine, List<ViewCondition> conditionList) {
            this.viewEntityCondition = viewEntityCondition;
            try {
                this.operator = EntityOperator.lookupJoin(combine);
            } catch (IllegalArgumentException e) {
                throw new IllegalArgumentException("[" + this.viewEntityCondition.modelViewEntity.getEntityName() + "]: Could not find an entity operator for the name: " + combine);
            }
            if (UtilValidate.isNotEmpty(conditionList)) {
                this.conditionList.addAll(conditionList);
            }
        }

        public EntityCondition createCondition(ModelFieldTypeReader modelFieldTypeReader, List<String> entityAliasStack) {
            if (this.conditionList.size() == 0) {
                return null;
            }
            if (this.conditionList.size() == 1) {
                ViewCondition condition = this.conditionList.get(0);
                return condition.createCondition(modelFieldTypeReader, entityAliasStack);
            }

            List<EntityCondition> entityConditionList = new LinkedList<EntityCondition>();
            for (ViewCondition curCondition: conditionList) {
                EntityCondition econd = curCondition.createCondition(modelFieldTypeReader, entityAliasStack);
                if (econd != null) {
                    entityConditionList.add(econd);
                }
            }

            if(this.viewEntityCondition.filterByDate) {
                entityConditionList.add(EntityUtil.getFilterByDateExpr());
            }

            if(this.viewEntityCondition.filterByDate) {
                entityConditionList.add(EntityUtil.getFilterByDateExpr());
            }

            return EntityCondition.makeCondition(entityConditionList, this.operator);
        }
    }
}
