com.quinsoft.zeidon.standardoe.EntityCursorImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.quinsoft.zeidon.standardoe.EntityCursorImpl.java

Source

/**
Zeidon JOE is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
    
Zeidon JOE is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.
    
You should have received a copy of the GNU Lesser General Public License
along with Zeidon JOE.  If not, see <http://www.gnu.org/licenses/>.
    
Copyright 2009-2015 QuinSoft
 */
package com.quinsoft.zeidon.standardoe;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.EnumSet;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;

import org.apache.commons.lang3.StringUtils;

import com.quinsoft.zeidon.AttributeInstance;
import com.quinsoft.zeidon.CompareEntityOptions;
import com.quinsoft.zeidon.CopyAttributesBuilder;
import com.quinsoft.zeidon.CreateEntityFlags;
import com.quinsoft.zeidon.CursorPosition;
import com.quinsoft.zeidon.CursorResult;
import com.quinsoft.zeidon.EntityConstraintType;
import com.quinsoft.zeidon.EntityCursor;
import com.quinsoft.zeidon.EntityInstance;
import com.quinsoft.zeidon.EntityIterator;
import com.quinsoft.zeidon.HiddenAttributeException;
import com.quinsoft.zeidon.HiddenCursorException;
import com.quinsoft.zeidon.IncludeFlags;
import com.quinsoft.zeidon.NullCursorException;
import com.quinsoft.zeidon.OutOfScopeException;
import com.quinsoft.zeidon.SetMatchingFlags;
import com.quinsoft.zeidon.ZeidonException;
import com.quinsoft.zeidon.objectdefinition.AttributeDef;
import com.quinsoft.zeidon.objectdefinition.DynamicAttributeDefConfiguration;
import com.quinsoft.zeidon.objectdefinition.EntityDef;
import com.quinsoft.zeidon.objectdefinition.LazyLoadConfig;
import com.quinsoft.zeidon.objectdefinition.LodDef;

/**
 * @author DG
 *
 */
class EntityCursorImpl implements EntityCursor {
    private final EntityDef entityDef;
    private final ViewCursor viewCursor;

    private EntityIterator<EntityInstanceImpl> currentIterator;

    /**
     * Used to keep track of most recent setFirst/setLast.
     */
    private boolean forwardDirection = true;

    /**
     * This points to the cursor's current entity instance.  It's a weak reference so
     * that if the entity is dropped then this cursor will release it.
     */
    private EntityInstanceImpl entityInstance;

    EntityCursorImpl(ViewCursor viewCursor, EntityDef entityDef) {
        this.viewCursor = viewCursor;
        this.entityDef = entityDef;
        setEntityInstance(null);
    }

    /**
     * Create a cursor and initialize it to point to the same entity as 'source'.
     *
     * @param viewCursor
     * @param source
     * @param parentCsr
     */
    EntityCursorImpl(ViewCursor viewCursor, EntityCursorImpl source) {
        this(viewCursor, source.getEntityDef());
        setEntityInstance(source.entityInstance);
        if (source.currentIterator != null)
            currentIterator = IteratorBuilder.build(source.currentIterator, this);
    }

    protected ObjectInstance getObjectInstance() {
        return viewCursor.getObjectInstance();
    }

    /**
     * Returns the current entity pointed to by this cursor or null.
     *
     * If the cursor is currently pointing to null then this logic will attempt to
     * re-establish the cursor by looking at parent cursor values.  Will return
     * an entity instance even if it's hidden.
     *
     * If necessary, this will lazy load an entity instance.
     */
    @Override
    public EntityInstanceImpl getEntityInstance() {
        return getEntityInstance(true);
    }

    /**
     * Attempts to get an entity instance.
     *
     * @param allowLazyLoad If false, then don't attempt to lazy load an instance.
     *
     * @return
     */
    private EntityInstanceImpl getEntityInstance(boolean allowLazyLoad) {
        // There are some edge cases with dropped entities.  Look to see if the current
        // entity is dropped and if it is set the cursor to null.
        // KJS 05/13/10 - Commenting out temporarily per DG request.
        //if ( entityInstance != null && entityInstance.isDropped() )
        //    setEntityInstance( null );

        // If it's null then we'll still try to re-establish the cursor because it's
        // possible that an entity was created using a different view.
        if (entityInstance == null) {
            if (entityDef.getParent() == null)
                entityInstance = getObjectInstance().getRootEntityInstance();
            else {
                // Try to get the entity instance for the parent.
                EntityCursorImpl parentCsr = viewCursor.getEntityCursor(entityDef.getParent());
                EntityInstanceImpl parentInstance = parentCsr.getEntityInstance(allowLazyLoad);

                // If the parent instance is null then this cursor must be null as well.
                if (parentInstance == null) {
                    entityInstance = null;
                    return null;
                }

                // Do some validity checking.  Parent shouldn't be higher in the hier structure
                // than the recursive root.
                if (viewCursor.getRecursiveRoot() != null
                        && viewCursor.getRecursiveRoot().getDepth() > parentInstance.getDepth()) {
                    viewCursor.getView().logObjectInstance();
                    throw new ZeidonException(
                            "Internal error: parent level for %s doesn't match " + "level for suboject root %s",
                            parentInstance, viewCursor.getRecursiveRoot());
                }

                // Check to see if we need to load a lazy child.
                if (allowLazyLoad)
                    parentInstance.lazyLoadChild(getView(), getEntityDef());

                EntityInstanceImpl searchInstance = null;

                // We need to find the first entityInstance under the parent.  The
                // quickest way is to find a previous sibling and search hier from there.
                EntityDef prevSibling = entityDef.getPrevSibling();
                if (prevSibling != null)
                    // Use getEntityInstance because its possible for the cursor to be null.
                    searchInstance = viewCursor.getEntityCursor(prevSibling).getEntityInstance(false);

                // No siblings were found so start the search from the parent.
                if (searchInstance == null)
                    searchInstance = parentInstance.getNextHier();

                // Find the first entity instance under the parent that:
                //    1) Has the same entityDef for the cursor we're trying to set.
                //    2) Has the same instance level for the entityDef + recursive diff.
                //       Checking for instance level will skip over recursive suboject
                //       instances with the same LodDef.
                int level = entityDef.getDepth() + viewCursor.getRecursiveDiff();
                for (; searchInstance != null; searchInstance = searchInstance.getNextHier()) {
                    // If the searchInstance level is less than the parent then there is no
                    // entity that matches what we want.
                    if (searchInstance.getDepth() <= parentInstance.getDepth()) {
                        searchInstance = null;
                        break;
                    }

                    if (searchInstance.isHidden())
                        continue;

                    EntityDef searchEntityDef = searchInstance.getEntityDef();
                    if (searchEntityDef == entityDef && searchInstance.getDepth() == level)
                        break;
                }

                entityInstance = searchInstance;
            }
        }

        if (entityInstance != null)
            entityInstance = entityInstance.getLatestVersion();

        return entityInstance;
    }

    /**
     * Gets the cursor's entity instance.  Throws NullCursorException if the entity is null.
     * @return
     * @throws NullCursorException
     */
    private EntityInstanceImpl getExistingInstance(boolean allowHidden) throws NullCursorException {
        if (!viewCursor.isCursorInScope(this))
            throw new OutOfScopeException(this);

        EntityInstanceImpl ei = getEntityInstance(); // Potentially sets UNSET_CSR.
        if (ei == null)
            throw new NullCursorException(this);

        if (!allowHidden && ei.isHidden())
            throw new HiddenCursorException(this);

        if (!viewCursor.isCursorInScope(this))
            throw new ZeidonException("Cursor %s is out of scope", getEntityDef());

        // Sanity checking--make sure that the existing instance has at least one linked instance,
        // which is itself.
        assert ei.getAllLinkedInstances(allowHidden)
                .contains(ei) : "Entity doesn't have itself in linked instances";

        return ei;
    }

    private EntityInstanceImpl getExistingInstance() throws NullCursorException {
        return getExistingInstance(getView().isAllowHiddenEntities());
    }

    /**
     * Sets the EntityInstance for this cursor.
     *
     * Note:  Most code should call setCursor( ei ) instead of this method.
     * Other than simple validity checking this code does not perform any
     * extra processing (like reseting child cursors).  This should only be used by code
     * that expects to explicitly set all the cursors.
     *
     * @param entityInstance
     * @return
     */
    EntityInstanceImpl setEntityInstance(EntityInstanceImpl entityInstance) {
        if (entityInstance == null || entityInstance.getEntityDef() == getEntityDef()
                || entityInstance.getEntityDef().getRecursiveParent() == getEntityDef()) {
            this.entityInstance = entityInstance;
            return entityInstance;
        }

        throw new ZeidonException("Internal error: Attempting to set a cursor to an invalid entity def");
    }

    @Override
    public EntityInstanceImpl getParent() {
        if (getParentCursor() == null)
            return null;

        // If this entity is a recursive parent and the current view is in a subobject
        // then the parent is not necessarily determined by the parent cursor.
        if (getEntityDef().isRecursiveParent() && viewCursor.getRecursiveDiff() > 0) {
            // The current EntityDef is the parent of a recursive relationship and recursiveDiff
            // indicates we have a recursive subobject.  Check to see if there is a recursive root.
            if (getViewCursor().getRecursiveRoot() == null) {
                // The recursive root is null.  This means that when setSubobject was called
                // the subobject child was null and is now the parent.  Return the EI that
                // is the parent of the null EI.
                return getViewCursor().getRecursiveRootParent();
            } else
                return getViewCursor().getRecursiveRoot().getParent();
            //                assert getViewCursor().getRecursiveRoot().getParent() == getParentCursor().getExistingInstance();
        }

        EntityInstanceImpl parent = getParentCursor().getExistingInstance();
        return parent;
    }

    @Override
    public EntityInstance copySubobject(EntityInstance source, CursorPosition position) {
        if (!getEntityDef().isCreate())
            throw new ZeidonException("Entity is not flagged for create.").prependEntityDef(getEntityDef());

        if (getEntityDef() != source.getEntityDef())
            throw new ZeidonException("Source and target entity definitions must be the same.")
                    .prependEntityDef(getEntityDef())
                    .prependMessage("Source Entity = ", source.getEntityDef().getName());

        EntityInstanceImpl sourceInstance = (EntityInstanceImpl) source.getEntityInstance();
        createEntity(position);
        setMatchingAttributesByName(sourceInstance);

        // Now copy children.  We can't use the usual iterator because we need to skip over
        // children if we include a child entity.
        for (EntityInstanceImpl child = sourceInstance.getNextHier(); child != null
                && child.getDepth() > sourceInstance.getDepth(); child = child.getNextHier()) {
            if (child.isHidden()) {
                // Skip hidden children.
                child = child.getLastChildHier();
                continue;
            }

            EntityDef childEntityDef = child.getEntityDef();
            EntityCursorImpl childCursor = getView().cursor(childEntityDef);

            if (childEntityDef.isCreate()) {
                childCursor.createEntity();
                childCursor.setMatchingAttributesByName(child);
                continue;
            }

            if (childEntityDef.isInclude()) {
                childCursor.includeSubobject(child);
                child = child.getLastChildHier();
                continue;
            }

            throw new ZeidonException("Copied child entity is neither creatable or includable.")
                    .prependEntityDef(childEntityDef);
        }

        resetChildCursors(getExistingInstance());

        assert validateChains() : "Something is wrong with the chain pointers";
        return getExistingInstance();
    }

    @Override
    public EntityInstanceImpl createEntity() {
        return createEntity(CursorPosition.NEXT, CreateEntityFlags.DEFAULT);
    }

    @Override
    public EntityInstanceImpl createEntity(CursorPosition position, EnumSet<CreateEntityFlags> flags) {
        if (!flags.contains(CreateEntityFlags.fIGNORE_PERMISSIONS) && !getEntityDef().isCreate())
            throw new ZeidonException("Entity is not flagged for create.").prependEntityDef(getEntityDef());

        EntityInstanceImpl parent = getParent(); // Throws NullCursor if cursor is null.

        if (!flags.contains(CreateEntityFlags.fIGNORE_MAX_CARDINALITY))
            validateMaxCardinality();

        // If the entity is a derived entity or a work entity (both marked as derived) then
        // we don't need to check if the entity is read only.
        if (!flags.contains(CreateEntityFlags.fIGNORE_PERMISSIONS))
            validateOiUpdate();

        EntityInstanceImpl ei = getEntityInstance();

        EntityDef newInstanceEntityDef = getEntityDef();

        // Check for an edge case.  See if the EntityDef of the parent is the same as the
        // one we're about to create.  If it is then we are creating the child of a recursive
        // relationship.  If the EntityDef is the recursive parent then the LodDef of
        // the new instance should be the recursive child.
        if (parent != null && newInstanceEntityDef == parent.getEntityDef() && // Recursive relationship?
                newInstanceEntityDef.isRecursiveParent()) // EntityDef is recursive parent?
        {
            // Change the EntityDef of the instance we're about to create to be the child
            // of the recursive relationship.
            newInstanceEntityDef = newInstanceEntityDef.getRecursiveChild();
        }

        // Create a new instance and initialize the attributes.
        EntityInstanceImpl newInstance = EntityInstanceImpl.createEntity(getObjectInstance(), parent, ei,
                newInstanceEntityDef, position);

        // If recursiveDiff is > 0 then we are in a recursive subobject.  If recursiveRoot is
        // null then we just created the root of the recursive subobject so set it.
        if (getViewCursor().getRecursiveDiff() > 0 && getViewCursor().getRecursiveRoot() == null) {
            getViewCursor().setRecursiveParent(newInstance, newInstanceEntityDef, null);
        }

        if (!flags.contains(CreateEntityFlags.fDONT_INITIALIZE_ATTRIBUTES))
            newInstance.initializeDefaultAttributes();

        if (!flags.contains(CreateEntityFlags.fDONT_UPDATE_OI) && !newInstance.isVersioned())
            getObjectInstance().setUpdated(true);

        if (!flags.contains(CreateEntityFlags.fNO_SPAWNING)) {
            EntitySpawner spawner = new EntitySpawner(newInstance);
            spawner.spawnCreate();
        }

        if (flags.contains(CreateEntityFlags.fDBHANDLER))
            newInstance.dbhLoaded = true;

        resetChildCursors(newInstance);

        // Check to see if we need to execute the create constraint.  We'll assume we don't
        // execute it if the initialize flag is set because we don't want to execute the
        // constraint when loading from DB/file.
        if (getEntityDef().hasCreateConstraint()
                && !flags.contains(CreateEntityFlags.fDONT_INITIALIZE_ATTRIBUTES)) {
            entityDef.executeEntityConstraint(getView(), EntityConstraintType.CREATE);
        }

        assert validateChains() : "Something is wrong with the chain pointers";
        return newInstance;
    }

    @Override
    public EntityInstanceImpl createEntity(CursorPosition position) {
        return createEntity(position, CreateEntityFlags.DEFAULT);
    }

    @Override
    public EntityInstanceImpl createEntity(EnumSet<CreateEntityFlags> flags) {
        return createEntity(CursorPosition.NEXT, flags);
    }

    @Override
    public EntityInstanceImpl createEntity(CreateEntityFlags... flags) {
        EnumSet<CreateEntityFlags> set = EnumSet.copyOf(Arrays.asList(flags));
        return createEntity(CursorPosition.NEXT, set);
    }

    EntityInstanceImpl createEntity(CursorPosition position, CreateEntityFlags... flags) {
        EnumSet<CreateEntityFlags> set = EnumSet.copyOf(Arrays.asList(flags));
        return createEntity(position, set);
    }

    /* (non-Javadoc)
     * @see com.quinsoft.zeidon.EntityCursor#createTemporalEntity()
     */
    @Override
    public EntityInstance createTemporalEntity() {
        return createTemporalEntity(CursorPosition.NEXT);
    }

    /* (non-Javadoc)
     * @see com.quinsoft.zeidon.EntityCursor#createTemporalEntity(com.quinsoft.zeidon.CursorPosition)
     */
    @Override
    public EntityInstance createTemporalEntity(CursorPosition position) {
        EntityInstanceImpl ei = createEntity(position, CreateEntityFlags.fNO_SPAWNING,
                CreateEntityFlags.fDONT_UPDATE_OI);
        ei.setVersionedEntity();

        assert validateChains() : "Something is wrong with the chain pointers";
        return ei;
    }

    protected LodDef getLodDef() {
        return viewCursor.getLodDef();
    }

    /**
     * Reset the currently cursor to point to resetInstance and set all child cursors
     * to be unset.
     *
     * @param resetInstance
     */
    void resetChildCursors(EntityInstanceImpl resetInstance) {
        EntityInstanceImpl ei = resetInstance;
        if (ei != null)
            ei = resetInstance.getLatestVersion();

        setEntityInstance(ei);
        for (EntityCursorImpl resetCsr = this.getNextHierCursor(); resetCsr != null
                && resetCsr.getEntityDef().getDepth() > this.getEntityDef().getDepth(); resetCsr = resetCsr
                        .getNextHierCursor()) {
            resetCsr.setEntityInstance(null);
        }
    }

    /**
     * Validate that ei's EntityDef match that of the cursor.  Throws an exception if not.
     *
     * @return true if ei is a recursive child of this cursor, return false if not recursive.
     */
    private boolean validateEntityForCursor(EntityInstanceImpl ei) {
        // If they are the same entity then we're good.
        EntityDef sourceEntityDef = ei.getEntityDef();
        if (sourceEntityDef == getEntityDef()) {
            if (sourceEntityDef.isRecursive())
                return true;
            else
                return false;
        }

        // Check to see if ei is a recursive child of this cursor.
        if (sourceEntityDef.isRecursive() && sourceEntityDef.getRecursiveParent() == getEntityDef())
            return true;

        // If we get here then Houston we have a problem.
        throw new ZeidonException("Entity Instance %s is not a valid entity for this cursor.", sourceEntityDef);
    }

    private EntityInstanceImpl findMatchingLinkedInstance(EntityInstanceImpl targetInstance) {
        // The targetInstance belongs to a different OI.  Let's see if we can find a linked
        // instance that belongs to the current OI.
        for (EntityInstanceImpl ei : targetInstance.getLinkedInstances()) {
            if (ei.getObjectInstance() == getObjectInstance() && ei.getEntityDef() == targetInstance.getEntityDef())
                return ei;
        }

        // If we get here we didn't find one.
        throw new ZeidonException("Attempting to set a cursor to an Entity Instance that is from a different OI");
    }

    /**
     * Set 'this' cursor to match targetCursor.  This will change parent and child
     * cursors if necessary.
     *
     * @param targetCursor
     * @return
     */
    private CursorResult setCursorFromCursor(EntityCursorImpl targetCursor) {
        assert targetCursor.getEntityDef() == getEntityDef();
        assert targetCursor.getObjectInstance() == getObjectInstance();

        CursorResult cursorResult = CursorResult.SET;

        // Find the top-most parent cursor that needs to be changed.
        EntityCursorImpl parentTargetCursor = targetCursor;
        EntityCursorImpl parentSourceCursor = this;
        while (parentTargetCursor.getParentCursor() != null && parentTargetCursor
                .getParentCursor().entityInstance != parentSourceCursor.getParentCursor().entityInstance) {
            cursorResult = CursorResult.SET_NEWPARENT;
            parentTargetCursor = parentTargetCursor.getParentCursor();
            parentSourceCursor = parentSourceCursor.getParentCursor();
        }

        // Set the top-most parent and then set all children to UNSET.
        parentSourceCursor.resetChildCursors(parentTargetCursor.entityInstance);

        // Now search through the parents again.  This time we'll set the cursors.
        if (parentTargetCursor != targetCursor) {
            parentTargetCursor = targetCursor;
            parentSourceCursor = this;
            while (parentTargetCursor.getParentCursor() != null && parentTargetCursor
                    .getParentCursor().entityInstance != parentSourceCursor.getParentCursor().entityInstance) {
                // Set don't use setEntityInstance because that will attempt to set parents
                // and other logic.  We'll just set it directly.
                parentSourceCursor.entityInstance = parentSourceCursor.entityInstance;

                parentTargetCursor = parentTargetCursor.getParentCursor();
                parentSourceCursor = parentSourceCursor.getParentCursor();
            }

            // If we are changing parents then it's also possible we're changing
            // recursive entities.  Just copy the values from the target.
            viewCursor.copyRecursiveSettings(targetCursor.getViewCursor());
        }

        return cursorResult;
    }

    /**
     * Set the cursor to point to targetInstance and set all child cursors to point to
     * UNSET_CSR.  This will also check to see if the parent cursors need to be
     * set.
     *
     * @param newInstance
     * @return
     */
    @Override
    public CursorResult setCursor(EntityInstance targetInstance) {
        if (targetInstance == null)
            throw new ZeidonException("Cannot set a cursor to null.");

        // Optimization: if the target instance is a cursor then we can just
        // copy the entity instances from the target.
        // TODO: Following doesn't appear to be faster.  Why not?
        //        if ( targetInstance instanceof EntityCursorImpl &&
        //             targetInstance.getEntityDef() == getEntityDef() )
        //        {
        //            EntityCursorImpl targetCursor = (EntityCursorImpl) targetInstance;
        //            if ( targetCursor.getObjectInstance() == getObjectInstance() )
        //                return setCursorFromCursor( (EntityCursorImpl) targetInstance );
        //        }

        // Convert the targetInstance to an EntityInstanceImpl
        EntityInstanceImpl newInstance = (EntityInstanceImpl) targetInstance.getEntityInstance();

        if (newInstance.getObjectInstance() != getObjectInstance())
            newInstance = findMatchingLinkedInstance(newInstance);

        boolean recursive = validateEntityForCursor(newInstance);

        // Default return code to setting the cursor.
        CursorResult cursorResult = CursorResult.SET;

        if (recursive || getEntityDef().isRecursivePath()) {
            // If we get here then we're setting a subobject cursor.  We have a couple of situations to handle.
            // To illustrate, assume the following recursive subobject where A is the recursive parent of A'.
            //     A
            //     |
            //     B
            //    / \
            //   A'  C
            //   |
            //   D

            EntityDef targetEntityDef = newInstance.getEntityDef();
            EntityDef recursiveParent;

            if (!recursive) {
                // If we get here then we're not setting A or A' but one of the other
                // cursors (B, C or D above).

                // Find the recursive parent (A).
                recursiveParent = getEntityDef();
                while (recursiveParent.getRecursiveChild() == null)
                    recursiveParent = recursiveParent.getParent();
            } else
                recursiveParent = targetEntityDef.getRecursiveParent();

            // We're setting the parent cursor (A) to a subobject child (A').
            if (getEntityDef() == recursiveParent) {
                // Set the recursive structure.  We'll set the cursors later on.
                viewCursor.setRecursiveParent(newInstance, targetEntityDef, null);
            } else {
                assert getEntityDef() == targetEntityDef;

                EntityInstanceImpl parentInstance = newInstance.findMatchingParent(recursiveParent);
                if (parentInstance.getEntityDef() == recursiveParent) {
                    // If we get here then the parent of targetInstance is the root of the
                    // subobject so we're just resetting it.
                    viewCursor.resetSubobjectTop();
                } else {
                    viewCursor.setRecursiveParent(parentInstance, recursiveParent, null);
                }
            }
        } else
            viewCursor.resetRecursiveParent();

        // Check to see if we need to set the parent cursors. Find the highest root cursor that
        // needs to be reset.
        EntityCursorImpl searchCursor = this;
        EntityInstanceImpl topEi = newInstance;
        for (topEi = newInstance; topEi.getParent() != null; topEi = topEi.getParent()) {
            EntityCursorImpl searchParentCursor = searchCursor.getParentCursor();
            if (searchParentCursor == null) {
                while (topEi.getEntityDef().getErEntityToken() != searchCursor.getEntityDef().getErEntityToken())
                    topEi = topEi.getParent();

                break;
            }

            // If the cursor isn't in scope then we won't bother setting it.
            if (!viewCursor.isCursorInScope(searchParentCursor))
                break;

            // Don't use getEntityInstance() because it will potentially try to set
            // the parent cursors if entityInstance is null.
            if (searchParentCursor.entityInstance == topEi.getParent())
                break;

            searchCursor = searchCursor.getParentCursor();
        }

        searchCursor.resetChildCursors(topEi);

        // If topEi is different from newInstance that means we've just reset a parent
        // cursor.  Now loop through again and set all cursors between searchCursor and 'this'.
        if (topEi != newInstance) {
            cursorResult = CursorResult.SET_NEWPARENT;
            EntityCursorImpl tc = this;
            EntityInstanceImpl ei = newInstance;
            while (tc != searchCursor) {
                if (tc.getEntityDef() != ei.getEntityDef()
                        && tc.getEntityDef() != ei.getEntityDef().getRecursiveParent())
                    ei = ei.findMatchingParent(tc.getEntityDef());

                tc.setEntityInstance(ei);
                tc = tc.getParentCursor();
                ei = ei.getParent();
            }
        }

        return cursorResult;
    }

    private EntityCursorImpl getOtherCursor(EntityDef entityDef) {
        if (entityDef == null)
            return null;

        return getViewCursor().getEntityCursor(entityDef);
    }

    EntityCursorImpl getPrevHier() {
        return getOtherCursor(getEntityDef().getPrevHier());
    }

    EntityCursorImpl getNextHierCursor() {
        return getOtherCursor(getEntityDef().getNextHier());
    }

    @Override
    public EntityDef getEntityDef() {
        return entityDef;
    }

    @Override
    public CursorResult deleteEntity() throws NullCursorException {
        return deleteEntity(CursorPosition.NONE);
    }

    @Override
    public CursorResult excludeEntity() {
        return excludeEntity(CursorPosition.NONE);
    }

    /**
     * Re-positions the cursor after a delete or exclude.
     *
     * @param cursorPosition
     */
    private CursorResult repositionCursor(CursorPosition cursorPosition) {
        if (cursorPosition == CursorPosition.NONE)
            return CursorResult.UNCHANGED;

        // Save the current iterator.
        EntityIterator<EntityInstanceImpl> iterator = currentIterator;

        try {
            switch (cursorPosition) {
            case FIRST:
                return setFirst();

            case NEXT:
                CursorResult rc = setNext();
                if (rc == CursorResult.SET)
                    return rc;
                else
                    return setLast();

            case LAST:
                return setLast();

            case PREV:
                CursorResult rc2 = setPrev();
                if (rc2 == CursorResult.SET)
                    return rc2;
                else
                    return setFirst();

            default:
                throw new RuntimeException("Uknown CursorPosition " + cursorPosition);
            }
        } finally {
            currentIterator = iterator;
        }
    }

    @Override
    public CursorResult excludeEntity(CursorPosition position) {
        getExistingInstance().excludeEntity(getView());
        assert validateChains() : "Something is wrong with the chain pointers";
        return repositionCursor(position);
    }

    @Override
    public CursorResult deleteEntity(CursorPosition position) throws NullCursorException {
        getExistingInstance().deleteEntity(getView());
        assert validateChains() : "Something is wrong with the chain pointers";
        return repositionCursor(position);
    }

    @Override
    public CursorResult deleteAll() {
        CursorResult result = CursorResult.UNCHANGED;

        if (getEntityInstance() == null)
            return result;

        for (EntityInstanceImpl ei = getEntityInstance().getFirstTwin(); ei != null; ei = ei.getNextTwin()) {
            if (ei.isHidden())
                continue;

            ei.deleteEntity();
            result = CursorResult.SET;
        }

        return result;
    }

    private void validateMaxCardinality() {
        EntityInstanceImpl ei = getEntityInstance();
        if (ei != null)
            ei.validateMaxCardinality();
    }

    /**
     * Validates that this OI may be updated.
     */
    private void validateOiUpdate() {
        if (getEntityDef().isDerived())
            return;

        if (!getEntityDef().isPersistent())
            return;

        // If the entity is a derived entity or a work entity (both marked as derived) then
        // we don't need to check if the entity is read only.
        if (getEntityDef().isDerived() || getEntityDef().isDerivedPath())
            return;

        if (getObjectInstance().isReadOnly())
            throw new ZeidonException("Object Instance is read-only").prependEntityDef(getEntityDef());
    }

    @Override
    public void includeSubobject(EntityInstance sourceEi) throws NullCursorException {
        includeSubobject(sourceEi, CursorPosition.NEXT);
    }

    @Override
    public void includeSubobject(EntityInstance sourceEi, CursorPosition position) throws NullCursorException {
        includeSubobject(sourceEi, position, IncludeFlags.EMPTY);
    }

    @Override
    public void includeSubobject(EntityInstance sourceEi, CursorPosition position, EnumSet<IncludeFlags> options)
            throws NullCursorException {
        if (!options.contains(IncludeFlags.FROM_ACTIVATE)) {
            // Include constraints take some work.  Since nobody appears to use them let's not
            // worry about implementing them for now.
            if (entityDef.hasIncludeConstraint())
                throw new UnsupportedOperationException("Include constraints not supported yet.");

            validateMaxCardinality();
            validateOiUpdate();
        }

        EntityInstanceImpl source = (EntityInstanceImpl) sourceEi.getEntityInstance();
        EntityInstanceImpl parent = getParent();
        ObjectInstance oi = getObjectInstance();

        // Create a new instance and initialize the attributes.
        EntityInstanceImpl rootInstance = EntityInstanceIncluder.includeSubobject(getEntityInstance(),
                getEntityDef(), parent, oi, source, position, true, options);

        if (getEntityDef().getHashKeyAttributes() != null)
            rootInstance.addAllHashKeyAttributes();

        resetChildCursors(rootInstance);
        assert validateChains() : "Something is wrong with the chain pointers";
        // TODO: Add INCLUDE_WITH_COPY flag?
    }

    @Override
    public EntityInstance createTemporalSubobjectVersion() throws NullCursorException {
        validateOiUpdate();
        EntityInstanceImpl ei = getExistingInstance().createTemporalSubobjectVersion();
        assert validateChains() : "Something is wrong with the chain pointers";
        return ei;
    }

    @Override
    public int getDepth() throws NullCursorException {
        return getExistingInstance().getDepth();
    }

    /**
     * Returns the last child under the current entity instance.  If there is no child
     * under 'this', then returns 'this'.
     * @return
     */
    @Override
    public EntityInstanceImpl getLastChildHier() {
        return getExistingInstance().getLastChildHier();
    }

    @Override
    public boolean isCreated() throws NullCursorException {
        return getExistingInstance().isCreated();
    }

    @Override
    public boolean isDeleted() throws NullCursorException {
        // Use getEntityInstance instead of getExistingInstance because getExisting
        // will throw an exception for hidden instances.
        return getEntityInstance().isDeleted();
    }

    @Override
    public boolean isExcluded() throws NullCursorException {
        // Use getEntityInstance instead of getExistingInstance because getExisting
        // will throw an exception for hidden instances.
        return getEntityInstance().isExcluded();
    }

    @Override
    public boolean isHidden() throws NullCursorException {
        // Use getEntityInstance instead of getExistingInstance because getExisting
        // will throw an exception for hidden instances.
        return getEntityInstance().isHidden();
    }

    @Override
    public boolean isIncluded() throws NullCursorException {
        return getExistingInstance().isIncluded();
    }

    @Override
    public boolean isUpdated() throws NullCursorException {
        return getExistingInstance().isUpdated();
    }

    @Override
    public boolean isVersioned() {
        return getExistingInstance().isVersioned();
    }

    Iterable<AttributeDef> getNonNullAttributeList() throws NullCursorException {
        return getExistingInstance().getNonNullAttributeList();
    }

    /**
    * Gets the entity instance for the current cursor value matching scopingEntity.
    *
    * @param scopingEntity
    * @return
    */
    private EntityInstanceImpl getScopingEntityInstance(EntityDef scopingEntity) {
        // If the entity for this cursor has no parent then scoping isn't required.
        if (getEntityDef().getParent() == null)
            return null;

        if (scopingEntity == null)
            scopingEntity = getEntityDef().getParent();

        // If the scoping entity isn't the parent then we need to reset ancestor
        // cursors for everything under the scoping entity child.
        EntityDef searchEntity = getEntityDef().getParent();
        while (searchEntity != null && searchEntity != scopingEntity)
            searchEntity = searchEntity.getParent();

        if (searchEntity == null)
            throw new ZeidonException("Invalid scoping entity: Entity %s is not an ancestor of %s",
                    scopingEntity.getName(), this.getEntityDef().getName());

        // Find the root EI for the scoping entity.
        EntityCursorImpl cursor = viewCursor.getEntityCursor(searchEntity);
        EntityInstanceImpl rootEi = cursor.getEntityInstance();
        return rootEi;
    }

    @Override
    public CursorResult setFirst() {
        // For performance reasons we won't create an iterator;
        // we'll just manipulate the cursor directly.
        currentIterator = null;
        forwardDirection = true;

        EntityInstanceImpl ei = getEntityInstance();
        if (ei != null && ei.isDropped()) {
            this.resetChildCursors(null);
            ei = getEntityInstance();
        }

        if (ei == null)
            return CursorResult.NULL;

        // Find the first twin.
        ei = ei.getFirstTwin();
        while (ei != null && ei.isHidden())
            ei = ei.getNextTwin();

        if (ei == null || ei.isHidden())
            return CursorResult.NULL;

        setCursor(ei);
        return CursorResult.SET;
    }

    @Override
    public CursorResult setFirst(String scopingEntityName) {
        // We'll assume that a blank/null scoping entity means no scoping.
        if (StringUtils.isBlank(scopingEntityName))
            return setFirst();

        return setFirst(getLodDef().getEntityDef(scopingEntityName));
    }

    @Override
    public CursorResult setFirst(EntityDef scopingEntity) {
        if (scopingEntity == null)
            return setFirst();

        if (scopingEntity == getEntityDef().getParent())
            return setFirst();

        currentIterator = new IteratorBuilder(getObjectInstance())
                .withScoping(getScopingEntityInstance(scopingEntity)).forEntityDef(getEntityDef()).setCursor(this)
                .build();
        if (!currentIterator.hasNext())
            return CursorResult.NULL;

        currentIterator.next();
        return CursorResult.SET;
    }

    @Override
    public CursorResult setFirst(String attributeName, Object value) {
        return setFirst(getEntityDef().getAttribute(attributeName), value);
    }

    @Override
    public CursorResult setFirst(AttributeDef attribute, Object value) {
        currentIterator = new IteratorBuilder(getObjectInstance()).forEntityDef(getEntityDef())
                .forTwinsOf(getEntityInstance()).setCursor(this).withAttributeValue(attribute, value).build();

        if (!currentIterator.hasNext())
            return CursorResult.UNCHANGED;

        //TODO: It would be nice to get rid of this next call.  Reason: for situations
        // where we are only calling setFirst with no following setNext, this call
        // loops through to find the next EI that matches.  If the list of sibling
        // entities is long we're doing a lot of unnecessary work.
        currentIterator.next();
        return CursorResult.SET;
    }

    @Override
    public CursorResult setFirst(String attributeName, Object value, String scopingEntityName) {
        // We'll assume that a blank/null scoping entity means no scoping.
        if (StringUtils.isBlank(scopingEntityName))
            return setFirst(attributeName, value);

        EntityDef scopingEntity = getLodDef().getEntityDef(scopingEntityName);
        return setFirst(getEntityDef().getAttribute(attributeName), value, scopingEntity);
    }

    @Override
    public CursorResult setFirst(AttributeDef attribute, Object value, EntityDef scopingEntity) {
        currentIterator = new IteratorBuilder(getObjectInstance())
                .withScoping(getScopingEntityInstance(scopingEntity)).forEntityDef(getEntityDef()).setCursor(this)
                .withAttributeValue(attribute, value).build();

        if (!currentIterator.hasNext())
            return CursorResult.UNCHANGED;

        //TODO: It would be nice to get rid of this next call.  Reason: for situations
        // where we are only calling setFirst with no following setNext, this call
        // loops through to find the next EI that matches.  If the list of sibling
        // entities is long we're doing a lot of unnecessary work.
        currentIterator.next();
        return CursorResult.SET;
    }

    @Override
    public CursorResult setNextContinue() {
        if (currentIterator == null) {
            if (forwardDirection)
                return setNext();
            else
                return setPrev();
        }

        if (!currentIterator.hasNext())
            return CursorResult.UNCHANGED;

        currentIterator.next();
        return CursorResult.SET;
    }

    @Override
    public CursorResult setNext() {
        // For performance reasons we won't create an iterator;
        // we'll just manipulate the cursor directly.
        currentIterator = null;

        EntityInstanceImpl ei = getEntityInstance();
        if (ei == null)
            return CursorResult.NULL;

        ei = ei.getNextTwin();
        while (ei != null && ei.isHidden())
            ei = ei.getNextTwin();

        if (ei == null || ei.isHidden())
            return CursorResult.UNCHANGED;

        setCursor(ei);
        return CursorResult.SET;
    }

    @Override
    public CursorResult setNext(String scopingEntityName) {
        // We'll assume that a blank/null scoping entity means no scoping.
        if (StringUtils.isBlank(scopingEntityName))
            return setNext();

        return setNext(getLodDef().getEntityDef(scopingEntityName));
    }

    @Override
    public CursorResult setNext(EntityDef scopingEntity) {
        if (scopingEntity == null)
            return setNext();

        if (scopingEntity == getEntityDef().getParent())
            return setNext();

        currentIterator = new IteratorBuilder(getObjectInstance())
                .withScoping(getScopingEntityInstance(scopingEntity)).forEntityDef(getEntityDef()).setCursor(this)
                .currentInstance(getEntityInstance()).build();
        if (!currentIterator.hasNext())
            return CursorResult.NULL;

        currentIterator.next();
        return CursorResult.SET;
    }

    @Override
    public CursorResult setNext(String attributeName, Object value) {
        return setNext(getEntityDef().getAttribute(attributeName), value);
    }

    @Override
    public CursorResult setNext(AttributeDef attribute, Object value) {
        currentIterator = new IteratorBuilder(getObjectInstance()).forEntityDef(getEntityDef()).setCursor(this)
                .currentInstance(getEntityInstance()).withAttributeValue(attribute, value).build();

        if (!currentIterator.hasNext())
            return CursorResult.UNCHANGED;

        currentIterator.next();
        return CursorResult.SET;
    }

    @Override
    public CursorResult setNext(String attributeName, Object value, String scopingEntityName) {
        if (StringUtils.isBlank(scopingEntityName))
            return setNext(getEntityDef().getAttribute(attributeName), value);

        return setNext(getEntityDef().getAttribute(attributeName), value,
                getLodDef().getEntityDef(scopingEntityName));
    }

    @Override
    public CursorResult setNext(AttributeDef attribute, Object value, EntityDef scopingEntity) {
        currentIterator = new IteratorBuilder(getObjectInstance())
                .withScoping(getScopingEntityInstance(scopingEntity)).forEntityDef(getEntityDef()).setCursor(this)
                .currentInstance(getEntityInstance()).withAttributeValue(attribute, value).build();

        if (!currentIterator.hasNext())
            return CursorResult.NULL;

        currentIterator.next();
        return CursorResult.SET;

    }

    @Override
    public CursorResult setLast() {
        // For performance reasons we won't create an iterator;
        // we'll just manipulate the cursor directly.
        currentIterator = null;
        forwardDirection = false;

        EntityInstanceImpl ei = getEntityInstance();
        if (ei != null && ei.isDropped()) {
            this.resetChildCursors(null);
            ei = getEntityInstance();
            // KJS 10/07/15 - When I delete the last entity with cursorposition.NEXT, we get here
            // and ei is null. We will return then, otherwise getLastTwin gives null exception.
            if (ei == null)
                return CursorResult.NULL;
        }

        if (ei == null)
            return CursorResult.NULL;

        ei = ei.getLastTwin();
        while (ei != null && ei.isHidden())
            ei = ei.getPrevTwin();

        if (ei == null || ei.isHidden())
            return CursorResult.NULL;

        setCursor(ei);
        return CursorResult.SET;
    }

    @Override
    public CursorResult setPrevContinue() {
        if (currentIterator == null) {
            if (forwardDirection)
                return setNext();
            else
                return setPrev();
        }

        if (!currentIterator.hasPrev())
            return CursorResult.UNCHANGED;

        currentIterator.prev();
        return CursorResult.SET;
    }

    @Override
    public CursorResult setByEntityKey(long entityKey) {
        // TODO: This should be cleaned up.  We probably don't need to build
        // an iterator and we probably shouldn't be setting currentIterator because
        // there is no valid 'next' value.
        EntityIterator<EntityInstanceImpl> iter = new IteratorBuilder(getObjectInstance())
                .forEntityDef(getEntityDef()).forTwinsOf(getEntityInstance()).build();

        for (EntityInstance ei : iter) {
            if (ei.getEntityKey() == entityKey) {
                currentIterator = iter;
                return setCursor(ei);
            }
        }

        return CursorResult.NULL;
    }

    @Override
    public CursorResult setPosition(int position) {
        if (position < 0)
            return CursorResult.NULL;

        EntityInstanceImpl ei = getEntityInstance();
        if (ei == null)
            return CursorResult.NULL;

        ei = ei.getFirstTwin();
        while (true) {
            while (ei != null && ei.isHidden())
                ei = ei.getNextTwin();

            if (ei == null)
                return CursorResult.NULL;

            if (position == 0) {
                setCursor(ei);
                return CursorResult.SET;
            }

            ei = ei.getNextTwin();
            position--;
        }
    }

    @Override
    public CursorResult setPosition(int position, String scopingEntityName) {
        if (position < 0)
            return CursorResult.NULL;

        // We'll assume that a blank/null scoping entity means no scoping.
        if (StringUtils.isBlank(scopingEntityName))
            return setPosition(position);

        EntityDef scopingEntity = getLodDef().getEntityDef(scopingEntityName);
        EntityIterator<EntityInstanceImpl> iter = new IteratorBuilder(getObjectInstance())
                .withScoping(getScopingEntityInstance(scopingEntity)).forEntityDef(getEntityDef()).build();

        EntityInstanceImpl ei = null;
        for (int i = 0; i <= position; i++) {
            if (!iter.hasNext())
                return CursorResult.NULL;

            ei = iter.next();
        }

        setCursor(ei);
        return CursorResult.SET;
    }

    Iterable<EntityCursorImpl> getChildCursors() {
        return new ChildIterable(this);
    }

    @Override
    public EntityInstance acceptSubobject() {
        try {
            EntityInstanceImpl ei = getExistingInstance().acceptSubobject(getView());
            setEntityInstance(ei);

            // The child cursors still point to the old version.  Reset them all to point
            // to the new version so that the GC doesn't hold onto the old ones.
            for (EntityCursorImpl child : getChildCursors()) {
                // If the child cursor is pointing to something, reset it.
                if (child.entityInstance != null)
                    child.getEntityInstance();
            }

            assert validateChains() : "Something is wrong with the chain pointers";
            return ei;
        } catch (Throwable e) {
            throw ZeidonException.wrapException(e).prependEntityDef(getEntityDef());
        }
    }

    @Override
    public EntityInstance cancelSubobject() {
        EntityInstanceImpl ei = getExistingInstance().cancelSubobject(getView());
        setEntityInstance(ei);

        // The child cursors may still point to the new version.  Reset them all to point
        // to the old version so that the GC doesn't hold onto the new ones.
        for (EntityCursorImpl child : getChildCursors()) {
            // If the child cursor is pointing to something, reset it.
            if (child.entityInstance != null)
                child.getEntityInstance();
        }

        assert validateChains() : "Something is wrong with the chain pointers";
        return ei;
    }

    /* (non-Javadoc)
     * @see com.quinsoft.zeidon.EntityInstance#acceptTemporalEntity()
     */
    @Override
    public void acceptTemporalEntity() {
        getExistingInstance().acceptTemporalEntity(getView());
        assert validateChains() : "Something is wrong with the chain pointers";
    }

    /* (non-Javadoc)
     * @see com.quinsoft.zeidon.EntityCursor#cancelTemporalEntity(com.quinsoft.zeidon.CursorPosition)
     */
    @Override
    public CursorResult cancelTemporalEntity(CursorPosition position) {
        getExistingInstance().cancelTemporalEntity();
        assert validateChains() : "Something is wrong with the chain pointers";
        return repositionCursor(position);
    }

    /* (non-Javadoc)
     * @see com.quinsoft.zeidon.EntityInstance#cancelTemporalEntity()
     */
    @Override
    public CursorResult cancelTemporalEntity() {
        return cancelTemporalEntity(CursorPosition.NONE);
    }

    @Override
    public CursorResult dropEntity() {
        return dropEntity(CursorPosition.NONE);
    }

    /* (non-Javadoc)
     * @see com.quinsoft.zeidon.EntityCursor#dropEntity(com.quinsoft.zeidon.CursorPosition)
     */
    @Override
    public CursorResult dropEntity(CursorPosition position) {
        getExistingInstance().dropEntity();
        assert validateChains() : "Something is wrong with the chain pointers";
        return repositionCursor(position);
    }

    void setCreated(boolean isCreated) {
        getExistingInstance().setCreated(isCreated);
    }

    void setUpdated(boolean isUpdated) {
        getExistingInstance().setUpdated(isUpdated);
    }

    @Override
    public boolean isNull() {
        if (!viewCursor.isCursorInScope(this))
            throw new OutOfScopeException(this);

        EntityInstanceImpl ei = getEntityInstance();
        return ei == null || ei.isHidden();
    }

    private static final class ChildIterable implements Iterable<EntityCursorImpl> {
        private final EntityCursorImpl cursor;

        /**
         * @param start
         */
        private ChildIterable(EntityCursorImpl start) {
            this.cursor = start;
        }

        @Override
        public Iterator<EntityCursorImpl> iterator() {
            return new Iterator<EntityCursorImpl>() {
                private EntityCursorImpl current = cursor;
                private final int startLevel = cursor.getEntityDef().getDepth();

                @Override
                public boolean hasNext() {
                    EntityCursorImpl next = current.getNextHierCursor();
                    if (next == null)
                        return false;

                    if (next.getEntityDef().getDepth() <= startLevel)
                        return false;

                    return true;
                }

                @Override
                public EntityCursorImpl next() {
                    current = current.getNextHierCursor();
                    return current;
                }

                @Override
                public void remove() {
                    throw new UnsupportedOperationException("remove() not supported");
                }
            };
        }
    }

    private static class SortKey {
        AttributeDef attributeDef;
        boolean ascending;
        String context;

        SortKey(AttributeDef AttributeDef, boolean ascending, String context) {
            this.attributeDef = AttributeDef;
            this.ascending = ascending;
            this.context = context;
        }
    }

    /**
     * Class used as a comparator when ordering entities.
     *
     * @author DG
     *
     */
    private static class EntitySorter implements Comparator<EntityInstanceImpl>, Serializable {
        private static final long serialVersionUID = 1L;

        private final List<SortKey> sortAttribs;

        EntitySorter(List<SortKey> sortAttribs) {
            super();
            this.sortAttribs = sortAttribs;
        }

        private EntityInstanceImpl findMatchingChild(EntityInstanceImpl parent, EntityDef sortEntity) {
            // We need to find the child entity that matches sortEntity.
            for (EntityInstanceImpl child : parent.getChildrenHier()) {
                if (child.getEntityDef() == sortEntity)
                    return child;
            }

            return null;
        }

        @Override
        public int compare(EntityInstanceImpl ei1, EntityInstanceImpl ei2) {
            assert ei1.getEntityDef() == ei2.getEntityDef();

            for (SortKey key : sortAttribs) {
                // Since we might be performing the compare on a child entity instance,
                // create "compare" EIs.
                EntityInstanceImpl cei1 = ei1;
                EntityInstanceImpl cei2 = ei2;

                EntityDef sortEntity = key.attributeDef.getEntityDef();
                if (cei1.getEntityDef() != sortEntity) {
                    cei1 = findMatchingChild(cei1, sortEntity);
                    cei2 = findMatchingChild(cei2, sortEntity);

                    // Check for null entities.  If one is null then we can compare without
                    // checking the attributes.
                    if (cei1 == null || cei2 == null) {
                        if (cei1 != null)
                            return 1; // cei2 is null, cei1 is not.

                        if (cei2 != null)
                            return -1; // cei1 is null, cei2 is not.

                        return 0; // Both are null.
                    }
                }

                int cmp = 0;
                if (key.context != null) {
                    // Use context for comparing.
                    if (cei1.getAttribute(key.attributeDef).isNull()
                            || cei2.getAttribute(key.attributeDef).isNull()) {
                        if (!cei1.getAttribute(key.attributeDef).isNull())
                            return 1;
                        if (!cei2.getAttribute(key.attributeDef).isNull())
                            return -1;
                        return 0; // Both are null.
                    }
                    String value1 = cei1.getAttribute(key.attributeDef).getString(key.context);
                    String value2 = cei2.getAttribute(key.attributeDef).getString(key.context);

                    cmp = value1.compareTo(value2);
                } else {
                    cmp = cei1.getAttribute(key.attributeDef)
                            .compare(cei2.getAttribute(key.attributeDef).getValue());
                }
                if (!key.ascending)
                    cmp = -cmp;

                if (cmp != 0)
                    return cmp;

            }

            return 0;
        }
    }

    private List<SortKey> parseOrderKeys(String orderKeys) {
        // The old OE allowed the user to request using a bubble sort.  The bubble sort
        // kept already-sorted members in order.  The Java merge sort does the same
        // thing so there's no longer any need to support the bubble sort but we need
        // to ignore it if it's in the string.
        if (orderKeys.startsWith(".bubblesort "))
            orderKeys = orderKeys.substring(12); // Ignore the bubble sort text.

        // Replace all separating commas with emptystring.  Otherwise our ascending/descending values might be
        // "A," or "D,".
        orderKeys = orderKeys.replaceAll(",", "").replaceAll("  ", " ");

        List<SortKey> sortAttribs = new ArrayList<SortKey>();
        String[] strings = orderKeys.split(" ");
        for (int i = 0; i < strings.length; i++) {
            String name = strings[i];
            EntityDef sortEntity = getEntityDef();
            if (name.contains(".")) {
                String[] s = name.split("\\.");
                if (s.length != 2)
                    throw new ZeidonException("Ill-formed order keys.  Entity.attrib name expected.  Got '%s'",
                            name);

                sortEntity = getLodDef().getEntityDef(s[0]);
                name = s[1];
            }

            AttributeDef sortAttrib = sortEntity.getAttribute(name);

            // Look for A or D.
            boolean ascending = true;
            if (i + 1 < strings.length) {
                if (strings[i + 1].equals("A")) {
                    ascending = true;
                    i++; // Skip over the 'A'
                } else if (strings[i + 1].equals("D")) {
                    ascending = false;
                    i++; // Skip over the 'D'
                }
            }

            // Look for the context name.
            String context = null;
            if (i + 1 < strings.length) {
                // KJS 05/07/14 - Add context.
                if (strings[i + 1].startsWith("[")) {
                    context = strings[i + 1].substring(1, strings[i + 1].lastIndexOf("]"));
                    i++;
                }

            }

            sortAttribs.add(new SortKey(sortAttrib, ascending, context));
        }

        return sortAttribs;
    }

    /**
     * Sorts the entities according to the value of orderKeys.
     *      orderKeys = String of paired 'words', consisting of "AttributeName x",
     *      where x is A for ascending, or D for descending. i.e.,
     *          "LastName A FirstName A".
     *
     *      A context may be specified for the sorting attribute by putting the
     *      context name in square brackets ("[" and "]" after the sort order:
     *          "LastName A State A [Abbrev]"
     *
     * @param orderKeys
     */

    @Override
    public void orderEntities(String orderKeys) {
        List<SortKey> sortAttribs = parseOrderKeys(orderKeys);
        EntitySorter comparator = new EntitySorter(sortAttribs);
        orderEntities(comparator);
    }

    @SuppressWarnings("unchecked") // For Collections.sort(...)
    @Override
    public void orderEntities(Comparator<? extends EntityInstance> comparator) {
        // If there is an autoseq attribute then ordering for this entity matters, so
        // validate that it can be updated.
        boolean isAutoseq = getEntityDef().getAutoSeq() != null;
        if (isAutoseq)
            validateOiUpdate();

        // Get the first twin.  We do this first so that if the cursor is null
        // this throws the exception right away.
        if (getEntityInstance() == null)
            return;

        // Set cursor to first instance.  This will reposition the cursor to the first
        // non-hidden entity.
        setFirst();

        EntityInstanceImpl firstInstance = getExistingInstance().getFirstTwin();
        EntityInstanceImpl lastInstance = firstInstance.getLastTwin();
        EntityInstanceImpl prevHier = firstInstance.getPrevHier();
        if (firstInstance == lastInstance)
            return; // There's only one instance so there's no need to re-order.

        EntityInstanceImpl lastHier = lastInstance.getLastChildHier().getNextHier();

        // Copy the entities into a list.  We null out the next/prev twin pointers so
        // we can re-insert them later.
        List<EntityInstanceImpl> entities = new ArrayList<EntityInstanceImpl>();
        EntityInstanceImpl nextInstance = null;
        for (EntityInstanceImpl ei = firstInstance; ei != null; ei = nextInstance) {
            entities.add(ei);
            nextInstance = ei.getNextTwin();

            ei.setNextTwin(null);
            ei.setPrevTwin(null);
            ei.setPrevHier(null);
            ei.getLastChildHier().setNextHier(null);
        }

        // Temporarily remove the instances from the chain.
        EntityInstanceImpl parent = firstInstance.getParent();
        if (prevHier != null) {
            prevHier.setNextHier(lastHier);
            if (lastHier != null)
                lastHier.setPrevHier(prevHier);
        } else
            getObjectInstance().setRootEntityInstance(null);

        // Sort the entities.
        Collections.sort(entities, (Comparator<? super EntityInstance>) comparator);

        // Re-insert them into the chain.  We re-insert them starting with the last
        // twin because it's a bit faster.
        ObjectInstance oi = getObjectInstance();
        EntityInstanceImpl previouslyInserted = null;
        for (int i = entities.size() - 1; i >= 0; i--) {
            EntityInstanceImpl ei = entities.get(i);
            ei.insertInstance(oi, parent, previouslyInserted, CursorPosition.PREV, null);
            if (isAutoseq)
                ei.setUpdated(true); // This will set the OI updated flag as well.
            previouslyInserted = ei;
        }

        assert validateChains() : "Something is wrong with the chain pointers";
    }

    @Override
    public CursorResult checkExistenceOfEntity() {
        if (!viewCursor.isCursorInScope(this))
            return CursorResult.UNDEFINED;

        // Check to see if the entity is null.
        if (!isNull())
            return CursorResult.SET;

        // If we get here then the entity is null or it points to a hidden instance.
        // If it's a hidden instance then try to find a non-hidden instance.
        EntityInstanceImpl ei = getEntityInstance();
        if (ei == null)
            return CursorResult.NULL; // There are no twins so return NULL.

        // Try to find a non-hidden twin.
        EntityInstanceImpl search = ei.getNextTwin();
        while (search != null && search.isHidden())
            search = search.getNextTwin();

        // If search is still null then we'll search for entities before ei.
        if (search == null) {
            search = ei.getPrevTwin();
            while (search != null && search.isHidden())
                search = search.getPrevTwin();
        }

        // If search is *still* null then there are no non-hidden twins.
        // Return null.
        if (search == null)
            return CursorResult.NULL;

        // Search points to a non-hidden entity.  Reset the cursor to the new entity
        // and return SET.
        //        setEntityInstance( search );
        return CursorResult.UNDEFINED;
    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();

        // Don't use getEntityInstance() or getNull() because that will attempt to
        // establish the cursor.  We don't want toString() changing anything.
        if (entityInstance == null)
            builder.append(getEntityDef()).append(": NULL");
        else
            builder.append(entityInstance.toString());

        return builder.toString();
    }

    @Override
    public void setToSubobject() {
        if (entityDef.getParent() == null)
            throw new ZeidonException("Entity %s is the root of the LodDef", getEntityDef());

        if (!entityDef.isRecursive())
            throw new ZeidonException("Entity %s is not recursive", entityDef);

        EntityInstanceImpl ei = getEntityInstance();
        EntityInstanceImpl parentOfSubobject = getParentCursor().getExistingInstance();

        EntityDef recursiveParentEntityDef = getEntityDef().getRecursiveParent();
        viewCursor.setRecursiveParent(ei, getEntityDef(), parentOfSubobject);
        viewCursor.getEntityCursor(recursiveParentEntityDef).resetChildCursors(ei);
    }

    @Override
    public boolean resetSubobjectToParent() {
        return viewCursor.resetSubobjectToParent();
    }

    EntityCursorImpl getParentCursor() {
        if (getEntityDef().getParent() == null)
            return null;

        return viewCursor.getEntityCursor(getEntityDef().getParent());
    }

    @Override
    public int getEntityCount() throws NullCursorException {
        EntityInstanceImpl ei = getEntityInstance(); // Establishes the cursor if necessary.
        if (ei == null)
            return 0;

        return ei.getTwinCount();
    }

    @Override
    public EntityIterator<? extends EntityInstance> getChildren(EntityDef childEntityDef) {
        return getChildren(childEntityDef, false);
    }

    @Override
    public EntityIterator<? extends EntityInstance> getChildren(EntityDef childEntityDef, boolean allowHidden) {
        return new IteratorBuilder(getObjectInstance()).allowHidden(allowHidden).withScoping(getExistingInstance())
                .forEntityDef(childEntityDef).build();
    }

    @Override
    public EntityIterator<? extends EntityInstance> getChildren(String childEntityName) {
        return getChildren(getLodDef().getEntityDef(childEntityName));
    }

    /**
     * Iterates through all the children of 'this' in heir order.  If includeParent
     * is true, then the iteration includes 'this' at the beginning.
     *
     * @param includeParent If true, include 'this'.
     *
     * @return
     */
    @Override
    public EntityIterator<EntityInstanceImpl> getChildrenHier(boolean includeParent) {
        return getChildrenHier(includeParent, true, true);
    }

    @Override
    public EntityIterator<EntityInstanceImpl> getChildrenHier(boolean includeParent, boolean excludeHidden,
            boolean forceLazyLoad) {
        // We don't call getExistingEntity().getChildrenHier(...) because we want to set the
        // view so that the iterator changes the cursor.
        EntityIterator<EntityInstanceImpl> iter = new IteratorBuilder(getObjectInstance())
                .withScoping(getEntityInstance()).allowHidden(!excludeHidden).setLazyLoad(forceLazyLoad)
                .setView(getView()).includeHierParent(includeParent).build();
        if (!includeParent && iter.hasNext())
            iter.next(); // Skip past the parent.

        return iter;
    }

    @Override
    public CopyAttributesBuilder copyAttributes() {
        return getExistingInstance().copyAttributes();
    }

    @Override
    public boolean isDbhCreated() {
        return getExistingInstance().isDbhCreated();
    }

    @Override
    public boolean isDbhDeleted() {
        return getExistingInstance().isDbhDeleted();
    }

    @Override
    public boolean isDbhExcluded() {
        return getExistingInstance().isDbhExcluded();
    }

    @Override
    public boolean isDbhUpdated() {
        return getExistingInstance().isDbhUpdated();
    }

    @Override
    public boolean isDbhIncluded() {
        return getExistingInstance().isDbhIncluded();
    }

    @Override
    public boolean isDbhNeedsInclude() {
        return getExistingInstance().isDbhNeedsInclude();
    }

    @Override
    public boolean isDbhSeqUpdated() {
        return getExistingInstance().isDbhSeqUpdated();
    }

    @Override
    public boolean isDbhGenKeyNeeded() {
        return getExistingInstance().isDbhGenKeyNeeded();
    }

    @Override
    public boolean isDbhNoGenKey() {
        return getExistingInstance().isDbhNoGenKey();
    }

    @Override
    public boolean isDbhForeignKey() {
        return getExistingInstance().isDbhForeignKey();
    }

    @Override
    public long getEntityKey() {
        return getExistingInstance().getEntityKey();
    }

    /* (non-Javadoc)
     * @see com.quinsoft.zeidon.EntityInstance#getObjectInstanceId()
     */
    @Override
    public long getObjectInstanceId() {
        return getExistingInstance().getObjectInstanceId();
    }

    @Override
    public UUID getEntityUuid() {
        return getExistingInstance().getEntityUuid();
    }

    /* (non-Javadoc)
     * @see com.quinsoft.zeidon.EntityInstance#getObjectInstanceId()
     */
    @Override
    public UUID getObjectInstanceUuid() {
        return getExistingInstance().getObjectInstanceUuid();
    }

    @Override
    public ViewImpl getView() {
        return viewCursor.getView();
    }

    @Override
    public EntityIterator<EntityInstanceImpl> eachEntity() {
        return new IteratorBuilder(getObjectInstance()).setCursor(EntityCursorImpl.this)
                .forTwinsOf(getEntityInstance()).forEntityDef(getEntityDef()).build();
    }

    @Override
    public EntityIterator<? extends EntityInstance> eachEntity(String scopingEntityName) {
        // We'll assume that a blank/null scoping entity means no scoping.
        if (StringUtils.isBlank(scopingEntityName))
            return eachEntity();

        return eachEntity(getLodDef().getEntityDef(scopingEntityName));
    }

    @Override
    public EntityIterator<? extends EntityInstance> eachEntity(EntityDef scopingEntity) {
        EntityInstanceImpl scopingEi = getScopingEntityInstance(scopingEntity);
        return new IteratorBuilder(getObjectInstance()).withScoping(scopingEi).forEntityDef(getEntityDef())
                .setCursor(EntityCursorImpl.this).build();
    }

    @Override
    public CursorResult setLast(String scopingEntityName) {
        // We'll assume that a blank/null scoping entity means no scoping.
        if (StringUtils.isBlank(scopingEntityName))
            return setLast();

        return setLast(getLodDef().getEntityDef(scopingEntityName));
    }

    @Override
    public CursorResult setLast(EntityDef scopingEntity) {
        if (scopingEntity == null)
            return setLast();

        if (scopingEntity == getEntityDef().getParent())
            return setLast();

        currentIterator = new IteratorBuilder(getObjectInstance())
                .withScoping(getScopingEntityInstance(scopingEntity)).forEntityDef(getEntityDef()).setCursor(this)
                .setLast().build();
        if (!currentIterator.hasPrev()) // Is there a last entity?
            return CursorResult.NULL;

        currentIterator.prev();
        return CursorResult.SET;
    }

    @Override
    public CursorResult setLast(String attributeName, Object value) {
        return setLast(getEntityDef().getAttribute(attributeName), value);
    }

    @Override
    public CursorResult setLast(String attributeName, Object value, String scopingEntityName) {
        // We'll assume that a blank/null scoping entity means no scoping.
        if (StringUtils.isBlank(scopingEntityName))
            return setLast(attributeName, value);

        return setLast(getEntityDef().getAttribute(attributeName), value,
                getLodDef().getEntityDef(scopingEntityName));
    }

    @Override
    public CursorResult setLast(AttributeDef attributeDef, Object value) {
        currentIterator = new IteratorBuilder(getObjectInstance()).forTwinsOf(getEntityInstance())
                .forEntityDef(getEntityDef()).setCursor(this).withAttributeValue(attributeDef, value).setLast()
                .build();
        if (!currentIterator.hasPrev()) // Is there a last entity?
            return CursorResult.NULL;

        currentIterator.prev();
        return CursorResult.SET;
    }

    @Override
    public CursorResult setLast(AttributeDef attribute, Object value, EntityDef scopingEntity) {
        // TODO Auto-generated method stub
        throw new UnsupportedOperationException("Not written yet");
    }

    @Override
    public CursorResult setPrev() {
        // For performance reasons we won't create an iterator;
        // we'll just manipulate the cursor directly.
        currentIterator = null;

        EntityInstanceImpl ei = getEntityInstance();
        if (ei == null)
            return CursorResult.NULL;

        ei = ei.getPrevTwin();
        while (ei != null && ei.isHidden())
            ei = ei.getPrevTwin();

        if (ei == null || ei.isHidden())
            return CursorResult.UNCHANGED;

        setCursor(ei);
        return CursorResult.SET;
    }

    @Override
    public CursorResult setPrev(String scopingEntityName) {
        // We'll assume that a blank/null scoping entity means no scoping.
        if (StringUtils.isBlank(scopingEntityName))
            return setPrev();

        return setPrev(getLodDef().getEntityDef(scopingEntityName));
    }

    @Override
    public CursorResult setPrev(EntityDef scopingEntity) {
        currentIterator = new IteratorBuilder(getObjectInstance())
                .withScoping(getScopingEntityInstance(scopingEntity)).forEntityDef(getEntityDef()).setCursor(this)
                .currentInstance(getEntityInstance()).build();
        if (!currentIterator.hasPrev())
            return CursorResult.NULL;

        currentIterator.prev();
        return CursorResult.SET;
    }

    @Override
    public CursorResult setPrev(String attributeName, Object value, String scopingEntityName) {
        if (StringUtils.isBlank(scopingEntityName))
            return setPrev(getEntityDef().getAttribute(attributeName), value);

        return setPrev(getEntityDef().getAttribute(attributeName), value,
                getLodDef().getEntityDef(scopingEntityName));
    }

    @Override
    public CursorResult setPrev(AttributeDef attribute, Object value, EntityDef scopingEntity) {
        currentIterator = new IteratorBuilder(getObjectInstance())
                .withScoping(getScopingEntityInstance(scopingEntity)).forEntityDef(getEntityDef()).setCursor(this)
                .currentInstance(getEntityInstance()).withAttributeValue(attribute, value).build();

        if (!currentIterator.hasPrev())
            return CursorResult.NULL;

        currentIterator.prev();
        return CursorResult.SET;

    }

    @Override
    public CursorResult setPrev(String attributeName, Object value) {
        return setPrev(getEntityDef().getAttribute(attributeName), value);
    }

    @Override
    public CursorResult setPrev(AttributeDef attribute, Object value) {
        currentIterator = new IteratorBuilder(getObjectInstance()).forEntityDef(getEntityDef()).setCursor(this)
                .currentInstance(getEntityInstance()).withAttributeValue(attribute, value).setLast().build();

        if (!currentIterator.hasPrev())
            return CursorResult.UNCHANGED;

        currentIterator.prev();
        return CursorResult.SET;
    }

    /* (non-Javadoc)
     * @see com.quinsoft.zeidon.EntityInstance#display()
     */
    @Override
    public void logEntity() {
        logEntity(true, 0);
    }

    /* (non-Javadoc)
     * @see com.quinsoft.zeidon.EntityInstance#display(boolean)
     */
    @Override
    public void logEntity(boolean displayChildren) {
        logEntity(displayChildren, 0);
    }

    /* (non-Javadoc)
     * @see com.quinsoft.zeidon.EntityInstance#display(boolean, int)
     */
    @Override
    public void logEntity(boolean displayChildren, int indent) {
        getExistingInstance().logEntity(displayChildren, indent);
    }

    private CursorResult moveTwin(EntityInstanceImpl target, CursorPosition position, EntityInstanceImpl source) {
        validateOiUpdate();
        EntityInstanceImpl lastHierChild = source.removeEntityFromChains();
        source.insertInstance(getObjectInstance(), target.getParent(), target, position, lastHierChild);

        // Set OI incremental flags if the entities are sequenced.
        if (getEntityDef().getAutoSeq() != null) {
            target.setUpdated(true, false, true);
            source.setUpdated(true, false, true);
        }

        assert validateChains() : "Something is wrong with the chain pointers";
        return CursorResult.SET;
    }

    /**
     * @deprecated Use logEntity instead.
     */
    @Deprecated
    @Override
    public void displayEntity() {
        logEntity(true, 0);
    }

    /**
     * @deprecated Use logEntity instead.
     */
    @Deprecated
    @Override
    public void displayEntity(boolean logChildren) {
        logEntity(logChildren, 0);
    }

    /**
     * @deprecated Use logEntity instead.
     */
    @Deprecated
    @Override
    public void displayEntity(boolean logChildren, int indentN) {
        logEntity(logChildren, indentN);
    }

    /* (non-Javadoc)
     * @see com.quinsoft.zeidon.EntityCursor#moveSubobject(int, com.quinsoft.zeidon.EntityCursor, int)
     */
    @Override
    public CursorResult moveSubobject(CursorPosition position, EntityCursor source,
            CursorPosition sourceReposition) {
        return moveSubobject(position, (EntityInstance) source, sourceReposition);
    }

    /* (non-Javadoc)
     * @see com.quinsoft.zeidon.EntityCursor#moveSubobject(int, com.quinsoft.zeidon.EntityInstance)
     */
    @Override
    public CursorResult moveSubobject(CursorPosition position, EntityInstance source) {
        return moveSubobject(position, source, CursorPosition.NEXT);
    }

    private void verifySubobjectMove(EntityInstance source) {
        // Make sure source is not a parent of target.  If it is we're attempting to
        // move a parent under it's child.
        EntityInstanceImpl target = getEntityInstance();
        if (target == null)
            target = getParentCursor().getEntityInstance();

        if (source.getEntityInstance() == null)
            throw new ZeidonException("Source EntityCursor is null");

        if (target.isChildOf(source))
            throw new ZeidonException("Attempting to move an entity instance under one of its children")
                    .appendMessage("Target Entity = %s", getEntityDef().getName())
                    .appendMessage("Child entity = %s", source.getEntityDef().getName());

        EntityDef tgtEntityDef = getEntityDef();
        EntityDef srcEntityDef = source.getEntityDef();

        if (!tgtEntityDef.isInclude())
            throw new ZeidonException("Target of moveSubobject be be includable").appendMessage("Target = %s",
                    tgtEntityDef.getName());

        if (!srcEntityDef.isExclude())
            throw new ZeidonException("Source of moveSubobject be be excludable").appendMessage("Source = %s",
                    srcEntityDef.getName());

        // Verify that the EntityDefs are the same for source and target -or- one is a recursive
        // child of the other.
        // The COE requires them to be the same EntityDef but is that really necessary?
        if (tgtEntityDef == srcEntityDef)
            return;

        if (srcEntityDef.getLodDef() != tgtEntityDef.getLodDef())
            throw new ZeidonException("When moving subobjects, source and target OIs must be using the same LOD");

        if (tgtEntityDef.isRecursiveParent() && srcEntityDef.isRecursive()
                && tgtEntityDef.isAncestorOf(srcEntityDef)) {
            return;
        }

        if (srcEntityDef.isRecursiveParent() && tgtEntityDef.isRecursive()
                && srcEntityDef.isAncestorOf(tgtEntityDef)) {
            return;
        }

        // If we get here then user has specified incorrect EntityDefs.
        throw new ZeidonException("When moving subobjects, source and target must be the same entity type "
                + "or one must be a recursive parent of the other");
    }

    private CursorResult moveSubobject(CursorPosition position, EntityInstance source,
            CursorPosition sourceReposition) {
        validateOiUpdate();

        EntityInstanceImpl target = getEntityInstance();

        // If source and target are the same then there's nothing to do.  Call getEntityInstance() on
        // source because it may be a EntityCursor.
        if (target == source.getEntityInstance())
            return CursorResult.UNCHANGED;

        // If they have the same parent then we're moving twins.  Call a different method.
        // If this changes then we need to verify max cardinality.
        if (target != null && target.getParent() == source.getParent())
            return moveTwin(target, position, (EntityInstanceImpl) source.getEntityInstance());

        // Verify that the subobject can be moved between different parents.
        verifySubobjectMove(source);

        // If we get here then everything should be good.
        includeSubobject(source, position);
        if (source instanceof EntityCursor)
            return ((EntityCursor) source).excludeEntity(sourceReposition);

        source.excludeEntity();
        return CursorResult.SET;
    }

    /* (non-Javadoc)
     * @see com.quinsoft.zeidon.EntityInstance#getHierPosition()
     */
    @Override
    public long getHierPosition() {
        return getExistingInstance().getHierPosition();
    }

    @Override
    public long getPosition() {
        return getExistingInstance().getPosition();
    }

    /* (non-Javadoc)
     * @see com.quinsoft.zeidon.EntityCursor#setFirstWithinOi()
     */
    @Override
    public CursorResult setFirstWithinOi() {
        currentIterator = new IteratorBuilder(getObjectInstance()).setCursor(this)
                .withOiScoping(getObjectInstance()).forEntityDef(getEntityDef()).build();
        if (!currentIterator.hasNext())
            return CursorResult.NULL;

        currentIterator.next();
        return CursorResult.SET;
    }

    /* (non-Javadoc)
     * @see com.quinsoft.zeidon.EntityCursor#setNextWithinOi()
     */
    @Override
    public CursorResult setNextWithinOi() {
        currentIterator = new IteratorBuilder(getObjectInstance()).setCursor(this)
                .withOiScoping(getObjectInstance()).currentInstance(getEntityInstance())
                .forEntityDef(getEntityDef()).build();
        if (!currentIterator.hasNext())
            return CursorResult.UNCHANGED;

        currentIterator.next();
        return CursorResult.SET;
    }

    /* (non-Javadoc)
     * @see com.quinsoft.zeidon.EntityCursor#hasNext()
     */
    @Override
    public boolean hasNext() {
        if (!viewCursor.isCursorInScope(this))
            throw new OutOfScopeException(this);

        EntityInstanceImpl ei = getEntityInstance();
        if (ei == null)
            return false;

        // See if there is a next, nonhidden twin.
        for (EntityInstanceImpl search = ei.getNextTwin(); search != null; search = search.getNextTwin()) {
            if (!search.isHidden())
                return true;
        }

        // If we get here then we didn't find any non-hidden EIs.
        return false;
    }

    /* (non-Javadoc)
     * @see com.quinsoft.zeidon.EntityCursor#hasNext()
     */
    @Override
    public boolean hasPrev() {
        if (!viewCursor.isCursorInScope(this))
            throw new OutOfScopeException(this);

        EntityInstanceImpl ei = getEntityInstance();
        if (ei == null)
            return false;

        // Look for a prev non-hidden twin.
        for (EntityInstanceImpl search = ei.getPrevTwin(); search != null; search = search.getPrevTwin()) {
            if (!search.isHidden())
                return true;
        }

        // If we get here then we didn't find any non-hidden EIs.
        return false;
    }

    /* (non-Javadoc)
     * @see com.quinsoft.zeidon.EntityCursor#hasAny()
     */
    @Override
    public boolean hasAny() {
        if (!viewCursor.isCursorInScope(this))
            throw new OutOfScopeException(this);

        EntityInstanceImpl ei = getEntityInstance();
        if (ei == null)
            return false;

        if (!ei.isHidden())
            return true;

        // If we get here then ei is hidden. See if there are any non-hidden EIs
        // either before or after this ei.
        for (EntityInstanceImpl search = ei.getPrevTwin(); search != null; search = search.getPrevTwin()) {
            if (!search.isHidden())
                return true;
        }

        for (EntityInstanceImpl search = ei.getNextTwin(); search != null; search = search.getNextTwin()) {
            if (!search.isHidden())
                return true;
        }

        // If we get here then we didn't find any non-hidden EIs.
        return false;
    }

    /* (non-Javadoc)
     * @see com.quinsoft.zeidon.EntityCursor#hasAny(java.lang.String)
     */
    @Override
    public boolean hasAny(String scopingEntityName) {
        // We'll assume that a blank/null scoping entity means no scoping.
        if (StringUtils.isBlank(scopingEntityName))
            return hasAny();

        return hasAny(getLodDef().getEntityDef(scopingEntityName));
    }

    /* (non-Javadoc)
     * @see com.quinsoft.zeidon.EntityCursor#hasAny(com.quinsoft.zeidon.objectdefinition.EntityDef)
     */
    @Override
    public boolean hasAny(EntityDef scopingEntityDef) {
        EntityIterator<EntityInstanceImpl> iter = new IteratorBuilder(getObjectInstance())
                .withScoping(getScopingEntityInstance(scopingEntityDef)).forEntityDef(getEntityDef()).build();
        return iter.hasNext();
    }

    /* (non-Javadoc)
     * @see com.quinsoft.zeidon.EntityCursor#hasAnyWithinOi()
     */
    @Override
    public boolean hasAnyWithinOi() {
        EntityIterator<EntityInstanceImpl> iter = new IteratorBuilder(getObjectInstance())
                .withOiScoping(getObjectInstance()).forEntityDef(getEntityDef()).build();
        return iter.hasNext();
    }

    /* (non-Javadoc)
     * @see com.quinsoft.zeidon.EntityCursor#setFirstWithinOi(java.lang.String, java.lang.Object)
     */
    @Override
    public CursorResult setFirstWithinOi(AttributeDef attributeDef, Object value) {
        currentIterator = new IteratorBuilder(getObjectInstance()).setCursor(this)
                .withOiScoping(getObjectInstance()).forEntityDef(getEntityDef())
                .withAttributeValue(attributeDef, value).build();
        if (!currentIterator.hasNext())
            return CursorResult.NULL;

        currentIterator.next();
        return CursorResult.SET;
    }

    /* (non-Javadoc)
     * @see com.quinsoft.zeidon.EntityCursor#setNextWithinOi(com.quinsoft.zeidon.objectdefinition.AttributeDef, java.lang.Object)
     */
    @Override
    public CursorResult setNextWithinOi(AttributeDef attributeDef, Object value) {
        currentIterator = new IteratorBuilder(getObjectInstance()).setCursor(this)
                .withOiScoping(getObjectInstance()).currentInstance(getEntityInstance())
                .forEntityDef(getEntityDef()).withAttributeValue(attributeDef, value).build();

        if (!currentIterator.hasNext())
            return CursorResult.UNCHANGED;

        currentIterator.next();
        return CursorResult.SET;
    }

    /* (non-Javadoc)
     * @see com.quinsoft.zeidon.EntityCursor#hasAny(java.lang.String, java.lang.Object)
     */
    @Override
    public boolean hasAny(String attributeName, Object value) {
        return hasAny(getEntityDef().getAttribute(attributeName), value);
    }

    /* (non-Javadoc)
     * @see com.quinsoft.zeidon.EntityCursor#hasAny(java.lang.String, java.lang.Object, java.lang.String)
     */
    @Override
    public boolean hasAny(String attributeName, Object value, String scopingEntityName) {
        // We'll assume that a blank/null scoping entity means no scoping.
        if (StringUtils.isBlank(scopingEntityName))
            return hasAny(attributeName, value);

        return hasAny(getEntityDef().getAttribute(attributeName), value,
                getLodDef().getEntityDef(scopingEntityName));
    }

    /* (non-Javadoc)
     * @see com.quinsoft.zeidon.EntityCursor#hasAnyWithinOi(java.lang.String, java.lang.Object)
     */
    @Override
    public boolean hasAnyWithinOi(String attributeName, Object value) {
        return hasAnyWithinOi(getEntityDef().getAttribute(attributeName), value);
    }

    /* (non-Javadoc)
     * @see com.quinsoft.zeidon.EntityCursor#setLastWithinOi()
     */
    @Override
    public CursorResult setLastWithinOi() {
        currentIterator = new IteratorBuilder(getObjectInstance()).setCursor(this)
                .withOiScoping(getObjectInstance()).forEntityDef(getEntityDef()).setLast().build();
        if (!currentIterator.hasNext())
            return CursorResult.NULL;

        currentIterator.next();
        return CursorResult.SET;
    }

    /* (non-Javadoc)
     * @see com.quinsoft.zeidon.EntityCursor#setLastWithinOi(java.lang.String, java.lang.Object)
     */
    @Override
    public CursorResult setLastWithinOi(String attributeName, Object value) {
        return setLastWithinOi(getEntityDef().getAttribute(attributeName), value);
    }

    /* (non-Javadoc)
     * @see com.quinsoft.zeidon.EntityCursor#setPrevWithinOi()
     */
    @Override
    public CursorResult setPrevWithinOi() {
        currentIterator = new IteratorBuilder(getObjectInstance()).setCursor(this)
                .withOiScoping(getObjectInstance()).currentInstance(getEntityInstance())
                .forEntityDef(getEntityDef()).setLast().build();

        if (!currentIterator.hasPrev())
            return CursorResult.UNCHANGED;

        currentIterator.prev();
        return CursorResult.SET;
    }

    private boolean assertParentCursors() {
        if (getParentCursor() == null)
            return true;

        // Break this out with a 'if' statement to make it easier to set a breakpoint.
        if (getParentCursor().getEntityInstance() == getEntityInstance().getParent())
            return true;
        else
            return false;
    }

    /* (non-Javadoc)
     * @see com.quinsoft.zeidon.EntityCursor#setPrevWithinOi(com.quinsoft.zeidon.objectdefinition.AttributeDef, java.lang.Object)
     */
    @Override
    public CursorResult setPrevWithinOi(AttributeDef attributeDef, Object value) {
        currentIterator = new IteratorBuilder(getObjectInstance()).setCursor(this)
                .withOiScoping(getObjectInstance()).currentInstance(getEntityInstance())
                .forEntityDef(getEntityDef()).withAttributeValue(attributeDef, value).setLast().build();
        if (!currentIterator.hasNext())
            return CursorResult.UNCHANGED;

        currentIterator.next();
        return CursorResult.SET;
    }

    /* (non-Javadoc)
     * @see com.quinsoft.zeidon.EntityCursor#setFirstWithinOi(java.lang.String, java.lang.Object)
     */
    @Override
    public CursorResult setFirstWithinOi(String attributeName, Object value) {
        return setFirstWithinOi(getEntityDef().getAttribute(attributeName), value);
    }

    /* (non-Javadoc)
     * @see com.quinsoft.zeidon.EntityCursor#setNextWithinOi(java.lang.String, java.lang.Object)
     */
    @Override
    public CursorResult setNextWithinOi(String attributeName, Object value) {
        return setNextWithinOi(getEntityDef().getAttribute(attributeName), value);
    }

    /* (non-Javadoc)
     * @see com.quinsoft.zeidon.EntityCursor#setLastWithinOi(com.quinsoft.zeidon.objectdefinition.AttributeDef, java.lang.Object)
     */
    @Override
    public CursorResult setLastWithinOi(AttributeDef attributeDef, Object value) {
        currentIterator = new IteratorBuilder(getObjectInstance()).setCursor(this)
                .withOiScoping(getObjectInstance()).forEntityDef(getEntityDef())
                .withAttributeValue(attributeDef, value).setLast().build();
        if (!currentIterator.hasNext())
            return CursorResult.NULL;

        currentIterator.next();
        return CursorResult.SET;
    }

    /* (non-Javadoc)
     * @see com.quinsoft.zeidon.EntityCursor#hasAny(com.quinsoft.zeidon.objectdefinition.AttributeDef, java.lang.Object)
     */
    @Override
    public boolean hasAny(AttributeDef attributeDef, Object value) {
        EntityIterator<EntityInstanceImpl> iter = new IteratorBuilder(getObjectInstance())
                .forEntityDef(getEntityDef()).withAttributeValue(attributeDef, value).build();
        return iter.hasNext();
    }

    /* (non-Javadoc)
     * @see com.quinsoft.zeidon.EntityCursor#hasAny(com.quinsoft.zeidon.objectdefinition.AttributeDef, java.lang.Object, com.quinsoft.zeidon.objectdefinition.EntityDef)
     */
    @Override
    public boolean hasAny(AttributeDef attributeDef, Object value, EntityDef scopingEntityDef) {
        EntityIterator<EntityInstanceImpl> iter = new IteratorBuilder(getObjectInstance())
                .forEntityDef(getEntityDef()).withScoping(getScopingEntityInstance(scopingEntityDef))
                .withAttributeValue(attributeDef, value).build();
        return iter.hasNext();
    }

    /* (non-Javadoc)
     * @see com.quinsoft.zeidon.EntityCursor#hasAnyWithinOi(com.quinsoft.zeidon.objectdefinition.AttributeDef, java.lang.Object)
     */
    @Override
    public boolean hasAnyWithinOi(AttributeDef attributeDef, Object value) {
        EntityIterator<EntityInstanceImpl> iter = new IteratorBuilder(getObjectInstance())
                .withOiScoping(getObjectInstance()).forEntityDef(getEntityDef())
                .withAttributeValue(attributeDef, value).build();
        return iter.hasNext();
    }

    /* (non-Javadoc)
     * @see com.quinsoft.zeidon.EntityInstance#isLinked(com.quinsoft.zeidon.EntityInstance)
     */
    @Override
    public boolean isLinked(EntityInstance ei) {
        return getExistingInstance().isLinked(ei);
    }

    /* (non-Javadoc)
     * @see com.quinsoft.zeidon.EntityInstance#getPrevTwin()
     */
    @Override
    public EntityInstance getPrevTwin() {
        return getExistingInstance().getPrevTwin();
    }

    /* (non-Javadoc)
     * @see com.quinsoft.zeidon.EntityInstance#getNextTwin()
     */
    @Override
    public EntityInstance getNextTwin() {
        return getExistingInstance().getNextTwin();
    }

    /* (non-Javadoc)
     * @see com.quinsoft.zeidon.EntityInstance#linkInstances(com.quinsoft.zeidon.EntityInstance)
     */
    @Override
    public boolean linkInstances(EntityInstance ei) {
        return getExistingInstance().linkInstances(ei);
    }

    /* (non-Javadoc)
     * @see com.quinsoft.zeidon.EntityInstance#getLinkedInstances()
     */
    @Override
    public Collection<? extends EntityInstance> getLinkedInstances() {
        return getExistingInstance().getLinkedInstances();
    }

    boolean validateChains() {
        return getObjectInstance().validateChains();
    }

    /* (non-Javadoc)
     * @see com.quinsoft.zeidon.EntityInstance#setMatchingAttributesByName(com.quinsoft.zeidon.EntityInstance, long)
     */
    @Override
    public int setMatchingAttributesByName(EntityInstance sourceInstance, EnumSet<SetMatchingFlags> control) {
        return getExistingInstance().setMatchingAttributesByName(sourceInstance, control);
    }

    /* (non-Javadoc)
     * @see com.quinsoft.zeidon.EntityInstance#setMatchingAttributesByName(com.quinsoft.zeidon.EntityInstance)
     */
    @Override
    public int setMatchingAttributesByName(EntityInstance sourceInstance) {
        return getExistingInstance().setMatchingAttributesByName(sourceInstance);
    }

    /* (non-Javadoc)
     * @see com.quinsoft.zeidon.EntityCursor#getStatus()
     */
    @Override
    public CursorStatus getStatus() {
        if (!viewCursor.isCursorInScope(this))
            return CursorStatus.OUT_OF_SCOPE;

        EntityInstanceImpl ei = getEntityInstance(false);
        if (ei == null) {
            // The cursor is null.  It's possible that we haven't loaded a lazy load
            // entity.  Check for that by looking at each of the conditions required
            // for lazy load.  If none of them are true then return NULL.

            // Do we allow lazy loading for this entity?  If not, must be null.
            LazyLoadConfig config = getEntityDef().getLazyLoadConfig();
            if (config.isLazyLoad()) {
                assert getParentCursor() != null : "Root cannot be lazy load candidate";

                EntityInstanceImpl parent = getParentCursor().getEntityInstance(false);
                if (parent == null)
                    // TODO: What if there are multiple levels of LazyLoad?  It's possible that
                    // the parent entity wasn't loaded because it is lazyload.
                    return CursorStatus.NULL;

                if (parent.hasChildBeenLazyLoaded(getEntityDef()))
                    return CursorStatus.NULL;

                return CursorStatus.NOT_LOADED;
            } else if (config.hasLazyLoadParent()) {
                assert getParentCursor() != null : "Root cannot be lazy load candidate";

                // Get the status of the parent.  If the status isn't normal (i.e. set to an EI)
                // then the child must have the same status.
                EntityCursorImpl pcursor = getViewCursor().getEntityCursor(config.getLazyLoadParent());
                CursorStatus parentStatus = pcursor.getStatus();
                if (parentStatus != CursorStatus.SET)
                    return parentStatus;
            }

            // The lazy-load parent has been loaded.  That means we must be null.
            return CursorStatus.NULL;
        }

        if (ei.isHidden())
            return CursorStatus.HIDDEN;

        return CursorStatus.SET;
    }

    /* (non-Javadoc)
     * @see com.quinsoft.zeidon.EntityInstance#getKeyString()
     */
    @Override
    public String getKeyString() {
        return getExistingInstance().getKeyString();
    }

    /* (non-Javadoc)
     * @see com.quinsoft.zeidon.EntityInstance#setIncrementalFlags(java.util.EnumSet)
     */
    @Override
    public EntityInstanceImpl setIncrementalFlags(EnumSet<IncrementalEntityFlags> flags) {
        return getExistingInstance(true).setIncrementalFlags(flags);
    }

    /* (non-Javadoc)
     * @see com.quinsoft.zeidon.EntityInstance#setIncrementalFlags(com.quinsoft.zeidon.standardoe.IncrementalEntityFlags)
     */
    @Override
    public EntityInstance setIncrementalFlags(IncrementalEntityFlags flag) {
        return getExistingInstance(true).setIncrementalFlags(flag);
    }

    protected ViewCursor getViewCursor() {
        return viewCursor;
    }

    @Override
    public AttributeInstance getAttribute(String attributeName) {
        AttributeDef attributeDef = getEntityDef().getAttribute(attributeName);
        if (attributeDef.isHidden())
            throw new HiddenAttributeException(attributeDef);

        return getAttribute(attributeDef);
    }

    @Override
    public AttributeInstance getAttribute(AttributeDef attributeDef) {
        return getExistingInstance().getAttribute(getView(), attributeDef);
    }

    @Override
    public AttributeInstance createDynamicAttributeDef(DynamicAttributeDefConfiguration config) {
        return getExistingInstance().createDynamicAttributeDef(config);
    }

    @Override
    public EntityIterator<? extends EntityInstance> getDirectChildren() {
        return getExistingInstance().getDirectChildren();
    }

    @Override
    public EntityIterator<? extends EntityInstance> getDirectChildren(boolean allowHidden) {
        return getExistingInstance().getDirectChildren(allowHidden);
    }

    @Override
    public EntityIterator<? extends EntityInstance> getDirectChildren(boolean allowHidden, boolean allowLazyLoad) {
        return getExistingInstance().getDirectChildren(allowHidden, allowLazyLoad);
    }

    @Override
    public boolean hasNextTwin() {
        return getExistingInstance().hasNextTwin();
    }

    @Override
    public boolean hasPrevTwin() {
        return getExistingInstance().hasPrevTwin();
    }

    @Override
    public EntityIterator<? extends EntityInstance> allEntities() {
        return new IteratorBuilder(getObjectInstance()).setCursor(this).withOiScoping(getObjectInstance())
                .forEntityDef(getEntityDef()).build();
    }

    @Override
    public List<AttributeInstance> getAttributes() {
        return getExistingInstance(true).getAttributes();
    }

    @Override
    public List<AttributeInstance> getAttributes(boolean includeNullValues) {
        return getExistingInstance(true).getAttributes(includeNullValues);
    }

    @Override
    public void copyAttributes(CopyAttributesBuilder flags) {
        getExistingInstance(true).copyAttributes(flags);
    }

    @Override
    public boolean isIncomplete() {
        return getExistingInstance().isIncomplete();
    }

    @Override
    public boolean compareEntity(EntityInstance sourceInstance) {
        return compareEntity(sourceInstance, CompareEntityOptions.DEFAULT_OPTIONS);
    }

    @Override
    public boolean compareEntity(EntityInstance sourceInstance, CompareEntityOptions options) {
        return getExistingInstance().compareEntity(sourceInstance, options);
    }
}