/*******************************************************************************
 * 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.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import org.ofbiz.base.component.ComponentConfig;
import org.ofbiz.base.config.GenericConfigException;
import org.ofbiz.base.config.MainResourceHandler;
import org.ofbiz.base.config.ResourceHandler;
import org.ofbiz.base.util.Debug;
import org.ofbiz.base.util.UtilTimer;
import org.ofbiz.base.util.UtilValidate;
import org.ofbiz.base.util.UtilXml;
import org.ofbiz.base.util.cache.Cache;
import org.ofbiz.base.util.cache.UtilCache;
import org.ofbiz.entity.GenericEntityConfException;
import org.ofbiz.entity.GenericEntityException;
import org.ofbiz.entity.GenericModelException;
import org.ofbiz.entity.config.model.DelegatorElement;
import org.ofbiz.entity.config.model.EntityConfig;
import org.ofbiz.entity.config.model.EntityModelReader;
import org.ofbiz.entity.config.model.Resource;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

/**
 * Generic Entity - Entity Definition Reader
 *
 */
@SuppressWarnings("serial")
public class ModelReader implements Serializable {

    public static final String module = ModelReader.class.getName();
    private static final Cache<String, ModelReader> readers = UtilCache.createUtilCache("entity.ModelReader", 0, 0);

    protected Map<String, ModelEntity> entityCache = null;

    protected int numEntities = 0;
    protected int numViewEntities = 0;
    protected int numFields = 0;
    protected int numRelations = 0;
    protected int numAutoRelations = 0;

    protected String modelName;

    /** collection of filenames for entity definitions */
    protected Collection<ResourceHandler> entityResourceHandlers;

    /** contains a collection of entity names for each ResourceHandler, populated as they are loaded */
    protected Map<ResourceHandler, Collection<String>> resourceHandlerEntities;

    /** for each entity contains a map to the ResourceHandler that the entity came from */
    protected Map<String, ResourceHandler> entityResourceHandlerMap;

    public static ModelReader getModelReader(String delegatorName) throws GenericEntityException {
        DelegatorElement delegatorInfo = EntityConfig.getInstance().getDelegator(delegatorName);

        if (delegatorInfo == null) {
            throw new GenericEntityConfException("Could not find a delegator with the name " + delegatorName);
        }

        String tempModelName = delegatorInfo.getEntityModelReader();
        ModelReader reader = readers.get(tempModelName);

        if (reader == null) {
            reader = new ModelReader(tempModelName);
            // preload caches...
            reader.getEntityCache();
            reader = readers.putIfAbsentAndGet(tempModelName, reader);
        }
        return reader;
    }

    private ModelReader(String modelName) throws GenericEntityException {
        this.modelName = modelName;
        entityResourceHandlers = new LinkedList<ResourceHandler>();
        resourceHandlerEntities = new HashMap<ResourceHandler, Collection<String>>();
        entityResourceHandlerMap = new HashMap<String, ResourceHandler>();

        EntityModelReader entityModelReaderInfo = EntityConfig.getInstance().getEntityModelReader(modelName);

        if (entityModelReaderInfo == null) {
            throw new GenericEntityConfException("Cound not find an entity-model-reader with the name " + modelName);
        }

        // get all of the main resource model stuff, ie specified in the entityengine.xml file
        for (Resource resourceElement : entityModelReaderInfo.getResourceList()) {
            ResourceHandler handler = new MainResourceHandler(EntityConfig.ENTITY_ENGINE_XML_FILENAME, resourceElement.getLoader(), resourceElement.getLocation());
            entityResourceHandlers.add(handler);
        }

        // get all of the component resource model stuff, ie specified in each ofbiz-component.xml file
        for (ComponentConfig.EntityResourceInfo componentResourceInfo: ComponentConfig.getAllEntityResourceInfos("model")) {
            if (modelName.equals(componentResourceInfo.readerName)) {
                entityResourceHandlers.add(componentResourceInfo.createResourceHandler());
            }
        }
    }

    private ModelEntity buildEntity(ResourceHandler entityResourceHandler, Element curEntityElement, int i, ModelInfo def) throws GenericEntityException {
        boolean isEntity = "entity".equals(curEntityElement.getNodeName());
        String entityName = UtilXml.checkEmpty(curEntityElement.getAttribute("entity-name")).intern();
        boolean redefinedEntity = "true".equals(curEntityElement.getAttribute("redefinition"));

        // add entityName to appropriate resourceHandlerEntities collection
        Collection<String> resourceHandlerEntityNames = resourceHandlerEntities.get(entityResourceHandler);

        if (resourceHandlerEntityNames == null) {
            resourceHandlerEntityNames = new LinkedList<String>();
            resourceHandlerEntities.put(entityResourceHandler, resourceHandlerEntityNames);
        }
        resourceHandlerEntityNames.add(entityName);

        // check to see if entity with same name has already been read
        if (entityCache.containsKey(entityName) && !redefinedEntity) {
            Debug.logWarning("Entity " + entityName +
                " is defined more than once, most recent will over-write " +
                "previous definition(s)", module);
            Debug.logWarning("Entity " + entityName + " was found in " +
                entityResourceHandler + ", but was already defined in " +
                entityResourceHandlerMap.get(entityName).toString(), module);
        }

        // add entityName, entityFileName pair to entityResourceHandlerMap map
        entityResourceHandlerMap.put(entityName, entityResourceHandler);

        // utilTimer.timerString("  After entityEntityName -- " + i + " --");
        // ModelEntity entity = createModelEntity(curEntity, utilTimer);

        ModelEntity modelEntity = null;
        if (isEntity) {
            modelEntity = createModelEntity(curEntityElement, null, def);
        } else {
            modelEntity = createModelViewEntity(curEntityElement, null, def);
        }

        String resourceLocation = entityResourceHandler.getLocation();
        try {
            resourceLocation = entityResourceHandler.getURL().toExternalForm();
        } catch (GenericConfigException e) {
            Debug.logError(e, "Could not get resource URL", module);
        }

        // utilTimer.timerString("  After createModelEntity -- " + i + " --");
        if (modelEntity != null) {
            modelEntity.setLocation(resourceLocation);
            // utilTimer.timerString("  After entityCache.put -- " + i + " --");
            if (isEntity) {
                if (Debug.verboseOn()) Debug.logVerbose("-- [Entity]: #" + i + ": " + entityName, module);
            } else {
                if (Debug.verboseOn()) Debug.logVerbose("-- [ViewEntity]: #" + i + ": " + entityName, module);
            }
        } else {
            Debug.logWarning("-- -- ENTITYGEN ERROR:getModelEntity: Could not create " +
                "entity for entityName: " + entityName, module);
        }
        return modelEntity;
    }

    public Map<String, ModelEntity> getEntityCache() throws GenericEntityException {
        if (entityCache == null) { // don't want to block here
            synchronized (ModelReader.class) {
                // must check if null again as one of the blocked threads can still enter
                if (entityCache == null) { // now it's safe
                    numEntities = 0;
                    numViewEntities = 0;
                    numFields = 0;
                    numRelations = 0;
                    numAutoRelations = 0;

                    entityCache = new HashMap<String, ModelEntity>();
                    List<ModelViewEntity> tempViewEntityList = new LinkedList<ModelViewEntity>();
                    List<Element> tempExtendEntityElementList = new LinkedList<Element>();

                    UtilTimer utilTimer = new UtilTimer();

                    for (ResourceHandler entityResourceHandler: entityResourceHandlers) {

                        // utilTimer.timerString("Before getDocument in file " + entityFileName);
                        Document document = null;

                        try {
                            document = entityResourceHandler.getDocument();
                        } catch (GenericConfigException e) {
                            throw new GenericEntityConfException("Error getting document from resource handler", e);
                        }
                        if (document == null) {
                            throw new GenericEntityConfException("Could not get document for " + entityResourceHandler.toString());
                        }

                        // utilTimer.timerString("Before getDocumentElement in " + entityResourceHandler.toString());
                        Element docElement = document.getDocumentElement();

                        if (docElement == null) {
                            return null;
                        }
                        docElement.normalize();
                        Node curChild = docElement.getFirstChild();

                        ModelInfo def = ModelInfo.createFromElements(ModelInfo.DEFAULT, docElement);
                        int i = 0;

                        if (curChild != null) {
                            utilTimer.timerString("Before start of entity loop in " + entityResourceHandler.toString());
                            do {
                                boolean isEntity = "entity".equals(curChild.getNodeName());
                                boolean isViewEntity = "view-entity".equals(curChild.getNodeName());
                                boolean isExtendEntity = "extend-entity".equals(curChild.getNodeName());

                                if ((isEntity || isViewEntity) && curChild.getNodeType() == Node.ELEMENT_NODE) {
                                    i++;
                                    ModelEntity modelEntity = buildEntity(entityResourceHandler, (Element) curChild, i, def);
                                    // put the view entity in a list to get ready for the second pass to populate fields...
                                    if (isViewEntity) {
                                        tempViewEntityList.add((ModelViewEntity) modelEntity);
                                    } else {
                                        entityCache.put(modelEntity.getEntityName(), modelEntity);
                                    }
                                } else if (isExtendEntity && curChild.getNodeType() == Node.ELEMENT_NODE) {
                                    tempExtendEntityElementList.add((Element) curChild);
                                }
                            } while ((curChild = curChild.getNextSibling()) != null);
                        } else {
                            Debug.logWarning("No child nodes found.", module);
                        }
                        utilTimer.timerString("Finished " + entityResourceHandler.toString() + " - Total Entities: " + i + " FINISHED");
                    }

                    // all entity elements in, now go through extend-entity elements and add their stuff
                    for (Element extendEntityElement: tempExtendEntityElementList) {
                        String entityName = UtilXml.checkEmpty(extendEntityElement.getAttribute("entity-name"));
                        ModelEntity modelEntity = entityCache.get(entityName);
                        if (modelEntity == null) throw new GenericEntityConfException("Entity to extend does not exist: " + entityName);
                        modelEntity.addExtendEntity(this, extendEntityElement);
                    }

                    // do a pass on all of the view entities now that all of the entities have
                    // loaded and populate the fields
                    while (!tempViewEntityList.isEmpty()) {
                        int startSize = tempViewEntityList.size();
                        Iterator<ModelViewEntity> mveIt = tempViewEntityList.iterator();
TEMP_VIEW_LOOP:
                        while (mveIt.hasNext()) {
                            ModelViewEntity curViewEntity = mveIt.next();
                            for (ModelViewEntity.ModelMemberEntity mve: curViewEntity.getAllModelMemberEntities()) {
                                if (!entityCache.containsKey(mve.getEntityName())) {
                                    continue TEMP_VIEW_LOOP;
                                }
                            }
                            mveIt.remove();
                            curViewEntity.populateFields(this);
                            for (ModelViewEntity.ModelMemberEntity mve: curViewEntity.getAllModelMemberEntities()) {
                                ModelEntity me = entityCache.get(mve.getEntityName());
                                me.addViewEntity(curViewEntity);
                            }
                            entityCache.put(curViewEntity.getEntityName(), curViewEntity);
                        }
                        if (tempViewEntityList.size() == startSize) {
                            // Oops, the remaining views reference other entities
                            // that can't be found, or they reference other views
                            // that have some reference problem.
                            break;
                        }
                    }
                    if (!tempViewEntityList.isEmpty()) {
                        StringBuilder sb = new StringBuilder("View entities reference non-existant members:\n");
                        Set<String> allViews = new HashSet<String>();
                        for (ModelViewEntity curViewEntity: tempViewEntityList) {
                            allViews.add(curViewEntity.getEntityName());
                        }
                        for (ModelViewEntity curViewEntity: tempViewEntityList) {
                            Set<String> perViewMissingEntities = new HashSet<String>();
                            Iterator<ModelViewEntity.ModelMemberEntity> mmeIt = curViewEntity.getAllModelMemberEntities().iterator();
                            while (mmeIt.hasNext()) {
                                ModelViewEntity.ModelMemberEntity mme = mmeIt.next();
                                String memberEntityName = mme.getEntityName();
                                if (!entityCache.containsKey(memberEntityName)) {
                                    // this member is not a real entity
                                    // check to see if it is a view
                                    if (!allViews.contains(memberEntityName)) {
                                        // not a view, it's a real missing entity
                                        perViewMissingEntities.add(memberEntityName);
                                    }
                                }
                            }
                            for (String perViewMissingEntity: perViewMissingEntities) {
                                sb.append("\t[").append(curViewEntity.getEntityName()).append("] missing member entity [").append(perViewMissingEntity).append("]\n");
                            }

                        }
                        throw new GenericEntityConfException(sb.toString());
                    }

                    // auto-create relationships
                    TreeSet<String> orderedMessages = new TreeSet<String>();
                    for (String curEntityName: new TreeSet<String>(this.getEntityNames())) {
                        ModelEntity curModelEntity = this.getModelEntity(curEntityName);
                        if (curModelEntity instanceof ModelViewEntity) {
                            // for view-entities auto-create relationships for all member-entity relationships that have all corresponding fields in the view-entity

                        } else {
                            // for entities auto-create many relationships for all type one relationships

                            // just in case we add a new relation to the same entity, keep in a separate list and add them at the end
                            List<ModelRelation> newSameEntityRelations = new LinkedList<ModelRelation>();

                            Iterator<ModelRelation> relationsIter = curModelEntity.getRelationsIterator();
                            while (relationsIter.hasNext()) {
                                ModelRelation modelRelation = relationsIter.next();
                                if (("one".equals(modelRelation.getType()) || "one-nofk".equals(modelRelation.getType())) && !modelRelation.isAutoRelation()) {
                                    ModelEntity relatedEnt = null;
                                    try {
                                        relatedEnt = this.getModelEntity(modelRelation.getRelEntityName());
                                    } catch (GenericModelException e) {
                                        throw new GenericModelException("Error getting related entity [" + modelRelation.getRelEntityName() + "] definition from entity [" + curEntityName + "]", e);
                                    }
                                    if (relatedEnt != null) {
                                        // create the new relationship even if one exists so we can show what we are looking for in the info message
                                        // don't do relationship to the same entity, unless title is "Parent", then do a "Child" automatically
                                        String title = modelRelation.getTitle();
                                        if (curModelEntity.getEntityName().equals(relatedEnt.getEntityName()) && "Parent".equals(title)) {
                                            title = "Child";
                                        }
                                        String description = "";
                                        String type = "";
                                        String relEntityName = curModelEntity.getEntityName();
                                        String fkName = "";
                                        ArrayList<ModelKeyMap> keyMaps = new ArrayList<ModelKeyMap>();
                                        boolean isAutoRelation = true;
                                        Set<String> curEntityKeyFields = new HashSet<String>();
                                        for (ModelKeyMap curkm : modelRelation.getKeyMaps()) {
                                            keyMaps.add(new ModelKeyMap(curkm.getRelFieldName(), curkm.getFieldName()));
                                            curEntityKeyFields.add(curkm.getFieldName());
                                        }
                                        keyMaps.trimToSize();
                                        // decide whether it should be one or many by seeing if the key map represents the complete pk of the relEntity
                                        if (curModelEntity.containsAllPkFieldNames(curEntityKeyFields)) {
                                            // always use one-nofk, we don't want auto-fks getting in for these automatic ones
                                            type = "one-nofk";
                                            // to keep it clean, remove any additional keys that aren't part of the PK
                                            List<String> curPkFieldNames = curModelEntity.getPkFieldNames();
                                            Iterator<ModelKeyMap> nrkmIter = keyMaps.iterator();
                                            while (nrkmIter.hasNext()) {
                                                ModelKeyMap nrkm =nrkmIter.next();
                                                String checkField = nrkm.getRelFieldName();
                                                if (!curPkFieldNames.contains(checkField)) {
                                                    nrkmIter.remove();
                                                }
                                            }
                                        } else {
                                            type= "many";
                                        }
                                        ModelRelation newRel = ModelRelation.create(relatedEnt, description, type, title, relEntityName, fkName, keyMaps, isAutoRelation);

                                        ModelRelation existingRelation = relatedEnt.getRelation(title + curModelEntity.getEntityName());
                                        if (existingRelation == null) {
                                            numAutoRelations++;
                                            if (curModelEntity.getEntityName().equals(relatedEnt.getEntityName())) {
                                                newSameEntityRelations.add(newRel);
                                            } else {
                                                relatedEnt.addRelation(newRel);
                                            }
                                        } else {
                                            if (newRel.equals(existingRelation)) {
                                                // don't warn if the target title+entity = current title+entity
                                                if (Debug.infoOn() && !(title + curModelEntity.getEntityName()).equals(modelRelation.getTitle() + modelRelation.getRelEntityName())) {
                                                    //String errorMsg = "Relation already exists to entity [] with title [" + targetTitle + "],from entity []";
                                                    String message = "Entity [" + relatedEnt.getPackageName() + ":" + relatedEnt.getEntityName() + "] already has identical relationship to entity [" +
                                                            curModelEntity.getEntityName() + "] title [" + title + "]; would auto-create: type [" +
                                                            newRel.getType() + "] and fields [" + newRel.keyMapString(",", "") + "]";
                                                    orderedMessages.add(message);
                                                }
                                            } else {
                                                String message = "Existing relationship with the same name, but different specs found from what would be auto-created for Entity [" + relatedEnt.getEntityName() + "] and relationship to entity [" +
                                                        curModelEntity.getEntityName() + "] title [" + title + "]; would auto-create: type [" +
                                                        newRel.getType() + "] and fields [" + newRel.keyMapString(",", "") + "]";
                                                Debug.logVerbose(message, module);
                                            }
                                        }
                                    } else {
                                        String errorMsg = "Could not find related entity ["
                                                + modelRelation.getRelEntityName() + "], no reverse relation added.";
                                        Debug.logWarning(errorMsg, module);
                                    }
                                }
                            }

                            if (newSameEntityRelations.size() > 0) {
                                for (ModelRelation newRel: newSameEntityRelations) {
                                    curModelEntity.addRelation(newRel);
                                }
                            }
                        }
                    }
                    if (Debug.infoOn()) {
                        for (String message : orderedMessages) {
                            Debug.logInfo(message, module);
                        }
                        Debug.logInfo("Finished loading entities; #Entities=" + numEntities + " #ViewEntities=" + numViewEntities + " #Fields=" + numFields + " #Relationships=" + numRelations + " #AutoRelationships=" + numAutoRelations, module);
                    }
                }
            }
        }
        return entityCache;
    }

    /** rebuilds the resourceHandlerEntities Map of Collections based on the current
     *  entityResourceHandlerMap Map, must be done whenever a manual change is made to the
     *  entityResourceHandlerMap Map after the initial load to make them consistent again.
     */
    public void rebuildResourceHandlerEntities() {
        resourceHandlerEntities = new HashMap<ResourceHandler, Collection<String>>();
        Iterator<Map.Entry<String, ResourceHandler>> entityResourceIter = entityResourceHandlerMap.entrySet().iterator();

        while (entityResourceIter.hasNext()) {
            Map.Entry<String, ResourceHandler> entry = entityResourceIter.next();
            // add entityName to appropriate resourceHandlerEntities collection
            Collection<String> resourceHandlerEntityNames = resourceHandlerEntities.get(entry.getValue());

            if (resourceHandlerEntityNames == null) {
                resourceHandlerEntityNames = new LinkedList<String>();
                resourceHandlerEntities.put(entry.getValue(), resourceHandlerEntityNames);
            }
            resourceHandlerEntityNames.add(entry.getKey());
        }
    }

    public Iterator<ResourceHandler> getResourceHandlerEntitiesKeyIterator() {
        if (resourceHandlerEntities == null) return null;
        return resourceHandlerEntities.keySet().iterator();
    }

    public Collection<String> getResourceHandlerEntities(ResourceHandler resourceHandler) {
        if (resourceHandlerEntities == null) return null;
        return resourceHandlerEntities.get(resourceHandler);
    }

    public void addEntityToResourceHandler(String entityName, String loaderName, String location) {
        entityResourceHandlerMap.put(entityName, new MainResourceHandler(EntityConfig.ENTITY_ENGINE_XML_FILENAME, loaderName, location));
    }

    public ResourceHandler getEntityResourceHandler(String entityName) {
        return entityResourceHandlerMap.get(entityName);
    }

    /** Gets an Entity object based on a definition from the specified XML Entity descriptor file.
     * @param entityName The entityName of the Entity definition to use.
     * @return An Entity object describing the specified entity of the specified descriptor file.
     */
    public ModelEntity getModelEntity(String entityName) throws GenericEntityException {
        if (entityName == null) {
            throw new IllegalArgumentException("Tried to find entity definition for a null entityName");
        }
        Map<String, ModelEntity> ec = getEntityCache();
        if (ec == null) {
            throw new GenericEntityConfException("ERROR: Unable to load Entity Cache");
        }
        ModelEntity modelEntity = ec.get(entityName);
        if (modelEntity == null) {
            String errMsg = "Could not find definition for entity name " + entityName;
            // Debug.logError(new Exception("Placeholder"), errMsg, module);
            throw new GenericModelException(errMsg);
        }
        return modelEntity;
    }

    public ModelEntity getModelEntityNoCheck(String entityName) {
        Map<String, ModelEntity> ec = null;
        try {
            ec = getEntityCache();
        } catch (GenericEntityException e) {
            Debug.logError(e, "Error getting entity cache", module);
        }
        if (ec == null) {
            return null;
        }
        ModelEntity modelEntity = ec.get(entityName);
        return modelEntity;
    }

    /** Creates a Iterator with the entityName of each Entity defined in the specified XML Entity Descriptor file.
     * @return A Iterator of entityName Strings
     */
    public Iterator<String> getEntityNamesIterator() throws GenericEntityException {
        Collection<String> collection = getEntityNames();
        if (collection != null) {
            return collection.iterator();
        } else {
            return null;
        }
    }

    /** Creates a Set with the entityName of each Entity defined in the specified XML Entity Descriptor file.
     * @return A Set of entityName Strings
     */
    public Set<String> getEntityNames() throws GenericEntityException {
        Map<String, ModelEntity> ec = getEntityCache();
        if (ec == null) {
            throw new GenericEntityConfException("ERROR: Unable to load Entity Cache");
        }
        return ec.keySet();
    }

    /** Get all entities, organized by package */
    public Map<String, TreeSet<String>> getEntitiesByPackage(Set<String> packageFilterSet, Set<String> entityFilterSet) throws GenericEntityException {
        Map<String, TreeSet<String>> entitiesByPackage = new HashMap<String, TreeSet<String>>();

        //put the entityNames TreeSets in a HashMap by packageName
        Iterator<String> ecIter = this.getEntityNames().iterator();
        while (ecIter.hasNext()) {
            String entityName = ecIter.next();
            ModelEntity entity = this.getModelEntity(entityName);
            String packageName = entity.getPackageName();

            if (UtilValidate.isNotEmpty(packageFilterSet)) {
                // does it match any of these?
                boolean foundMatch = false;
                for (String packageFilter: packageFilterSet) {
                    if (packageName.contains(packageFilter)) {
                        foundMatch = true;
                    }
                }
                if (!foundMatch) {
                    //Debug.logInfo("Not including entity " + entityName + " becuase it is not in the package set: " + packageFilterSet, module);
                    continue;
                }
            }
            if (UtilValidate.isNotEmpty(entityFilterSet) && !entityFilterSet.contains(entityName)) {
                //Debug.logInfo("Not including entity " + entityName + " because it is not in the entity set: " + entityFilterSet, module);
                continue;
            }

            TreeSet<String> entities = entitiesByPackage.get(entity.getPackageName());
            if (entities == null) {
                entities = new TreeSet<String>();
                entitiesByPackage.put(entity.getPackageName(), entities);
            }
            entities.add(entityName);
        }

        return entitiesByPackage;
    }

    /** Util method to validate an entity name; if no entity is found with the name,
     *  characters are stripped from the beginning of the name until a valid entity name is found.
     *  It is intended to be used to determine the entity name from a relation name.
     * @return A valid entityName or null
     */
    public String validateEntityName(String entityName) throws GenericEntityException {
        if (entityName == null) {
            return null;
        }
        Set<String> allEntities = this.getEntityNames();
        while (!allEntities.contains(entityName) && entityName.length() > 0) {
            entityName = entityName.substring(1);
        }
        return (entityName.length() > 0? entityName: null);
    }

    ModelEntity createModelEntity(Element entityElement, UtilTimer utilTimer, ModelInfo def) {
        if (entityElement == null) return null;
        this.numEntities++;
        ModelEntity entity = new ModelEntity(this, entityElement, utilTimer, def);
        return entity;
    }

    ModelEntity createModelViewEntity(Element entityElement, UtilTimer utilTimer, ModelInfo def) {
        if (entityElement == null) return null;
        this.numViewEntities++;
        ModelViewEntity entity = new ModelViewEntity(this, entityElement, utilTimer, def);
        return entity;
    }

    public ModelRelation createRelation(ModelEntity entity, Element relationElement) {
        this.numRelations++;
        ModelRelation relation = ModelRelation.create(entity, relationElement, false);
        return relation;
    }

    public void incrementFieldCount(int amount) {
        this.numFields += amount;
    }
}
