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