Package er.extensions.eof

Source Code of er.extensions.eof.ERXEntityFKConstraintOrder

package er.extensions.eof;

import java.util.Enumeration;

import org.apache.log4j.Logger;

import com.webobjects.eoaccess.EOEntity;
import com.webobjects.eoaccess.EOModelGroup;
import com.webobjects.eoaccess.EORelationship;
import com.webobjects.foundation.NSDictionary;
import com.webobjects.foundation.NSMutableDictionary;
import com.webobjects.foundation.NSMutableSet;

import er.extensions.foundation.ERXArrayUtilities;



/**
* Creates ordering based on foreign key dependencies.
*
* @author chill
*/
public class ERXEntityFKConstraintOrder extends ERXEntityOrder
{

    private static Logger logger = Logger.getLogger(ERXEntityFKConstraintOrder.class);


    /**
     * Designated constructor for implementing classes.
     *
     * @param modelGroup EOModelGroup to get list of all entities from
     */
    public ERXEntityFKConstraintOrder(EOModelGroup modelGroup)
    {
        super(modelGroup);
    }


    /**
     * Convenience constructor for implementing classes.  Uses <code>EOModelGroup.defaultGroup()</code>.
     */
    public ERXEntityFKConstraintOrder() {
        super();
    }


    /**
     * Processes the list of entities, creating the ordering dictionary based on foreign key constraints.
     *
     * @return a dictionary keyed on dependencyKeyFor(EOEntity)
     */
    @Override
    protected NSDictionary dependenciesByEntity() {
        logger.debug("Building dependency list");

        NSMutableDictionary dependencyList = new NSMutableDictionary(allEntities().count());
        for (Enumeration entityEnum = allEntities().objectEnumerator(); entityEnum.hasMoreElements();) {
            EOEntity entity = (EOEntity) entityEnum.nextElement();
            logger.trace("Finding dependencies of " + entity.name());

            for (Enumeration relationshipEnum = entity.relationships().objectEnumerator(); relationshipEnum.hasMoreElements();) {
                EORelationship relationship = (EORelationship) relationshipEnum.nextElement();

                if (hasForeignKeyConstraint(relationship)) {
                    EOEntity destinationEntity = relationship.destinationEntity();
                    logger.trace("Recording dependency on " + destinationEntity.name());
                    entitiesDependentOn(dependencyList, destinationEntity).addObject(entity.name());
                }
                else {
                    logger.trace("Ignoring, is not FK relationship or vertical inheritance parent");
                }
            }
        }
        logger.debug("Finished building dependency list");

        if (logger.isTraceEnabled()) {
            for (int i = 0; i < allEntities().count(); i++) {
                EOEntity entity = allEntities().objectAtIndex(i);
                logger.trace("Entity " + entity.name() + " is referenced by " + entitiesDependentOn(dependencyList, entity));
            }
        }

        return dependencyList;
    }


    /**
     * @param relationship EORelationship to test
     * @return <code>true</code> if relationship models a relation that will have a foreign key constraint in the database
     */
    protected boolean hasForeignKeyConstraint(EORelationship relationship) {
        logger.trace("Examining relationshp " + relationship.name());

        // Reflexive relationships (circular dependencies) can't be accommodated by entity ordering,
        // these require ordering within the operations for an entity. Check the externalName() rather than
        // entity name so that it will handle relationships to a super or subclass in a Single-Table inheritance structure
    if (relationship.entity().externalName() != null &&
      relationship.entity().externalName().equals(relationship.destinationEntity().externalName())) {
            logger.trace("Ignoring: reflexive relationship");
            return false;
        }

        if ( ! ERXArrayUtilities.arraysAreIdenticalSets(relationship.destinationAttributes(),
                                                        relationship.destinationEntity().primaryKeyAttributes()) ) {
            logger.trace("No FK constraint: found non-PK attributes in destination");
            return false;
        }
        // Primary key to primary key relationships are excluded.
        else if (ERXArrayUtilities.arraysAreIdenticalSets(relationship.sourceAttributes(),
                                                          relationship.entity().primaryKeyAttributes()) ) {
            // PK - PK relationships for vertical inheritance (child to parent) also need to be considered in ordering
            if (relationship.destinationEntity().equals(relationship.entity().parentEntity())) {
                logger.trace("Is vertical inheritance PK to PKconstraint");
                return true;
            }

            // Bug?  Do these need to be included?
            logger.trace("No FK constraint: Is PK to PK");
            return false;
        }

        logger.trace("Is FK constraint");
        return true;
    }


    /**
     * This implementation returns <code>entity.externalName()</code> as the dependcy is actually on tables not EOEntities
     * .
     * @param entity EOEntity to return key into dependency dictionary for
     *
     * @return key for <code>entity</code> into dependency dictionary returned by <code>dependenciesByEntity()</code>
     */
    @Override
    protected String dependencyKeyFor(EOEntity entity) {
        if (entity.externalName() == null) {
            return "Abstract Dummy Entity";
        }
        return entity.externalName();
    }


    /**
     * Returns the list of the names of the entities that reference (depend on)
     * this entity. This list is populated by <code>builddependencyList()</code>.
     * If <code>builddependencyList()</code> has not finished executing, the
     * list returned by this method may not be complete.
     *
     * @param dependencies
     *            list of dependencies being built by
     *            <code>builddependencyList()</code>
     * @param entity
     *            EOEntity to return list of referencing entities for
     * @return list of names of entities previously recorded as referencing this
     *         entity
     */
    protected NSMutableSet entitiesDependentOn(NSMutableDictionary dependencies, EOEntity entity) {
        NSMutableSet referencingEntities = (NSMutableSet) dependencies.objectForKey(dependencyKeyFor(entity));
        if (referencingEntities == null) {
            referencingEntities = new NSMutableSet();
            dependencies.setObjectForKey(referencingEntities, dependencyKeyFor(entity));
        }
        return referencingEntities;
    }

}
TOP

Related Classes of er.extensions.eof.ERXEntityFKConstraintOrder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.