All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.quinsoft.zeidon.standardoe.ObjectInstance Maven / Gradle / Ivy

There is a newer version: 2.2.0
Show newest version
/**
    This file is part of the Zeidon Java Object Engine (Zeidon JOE).

    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 .

    Copyright 2009-2015 QuinSoft
 */
/**
 *
 */
package com.quinsoft.zeidon.standardoe;

import java.util.Iterator;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;

import com.quinsoft.zeidon.ActivateOptions;
import com.quinsoft.zeidon.ZeidonException;
import com.quinsoft.zeidon.objectdefinition.LodDef;

/**
 * @author DG
 *
 */
class ObjectInstance
{
    private TaskImpl            task;
    private final LodDef        lodDef;

    /**
     * A unique internal ID created for each OI.  Note this ID is unique only within
     * a single JOE instance.  Use uuid for IDs that are unique across instances.
     */
    private final long          id;

    private final UUID          uuid;

    private EntityInstanceImpl  rootEntityInstance;
    private boolean             isLocked;
    private boolean             isReadOnly;
    private final AtomicInteger versionedInstances;

    /**
     * If true then this OI has been updated since it was last loaded from the DB.
     */
    private boolean         updated = false;

    /**
     * If true then this OI has been updated since it was last loaded from a file.
     */
    private boolean         updatedFile = false;

    /**
     * Stores the options used when activating the OI.  This is intended to be used by lazy load
     * and pagination processing.
     */
    private ActivateOptions activateOptions;

    // Following used for commit processing
    boolean dbhNeedsForeignKeys;
    boolean dbhNeedsGenKeys;

    /**
     * If true, then tell cursor processing to not attempt to lazy load entities.
     * This is intended to be used during activation so we don't go through
     * unnecessary processing.
     */
    private boolean ignoreLazyLoadEntities = false;

    /**
     * This keeps track of attribute hash keys that are global to the OI.  Intended for use
     * by cursor.setFirst() processing.
     */
    private AttributeHashKeyMap attributeHashkeyMap;

    /**
     * This is a weak map of the ViewCursors that refer to this ObjectInstance.
     * Note: This is currently only used if the LodDef has physical mappings; it
     * is intended to be used by merge processing for commits that are made on
     * remote servers.
     */
    //private final ConcurrentMap referringViewCursors;

    /**
     * This is the total count of root entities.  For OIs loaded with paging this
     * is the total number of roots, not just the ones loaded.
     */
    private Integer totalRootCount;

    ObjectInstance(TaskImpl task, LodDef lodDef)
    {
        this.task = task;
        this.lodDef = lodDef;
        id = task.getObjectEngine().getNextObjectKey();
        uuid = task.getObjectEngine().generateUuid();
        versionedInstances = new AtomicInteger( 0 );
    }

    LodDef getLodDef()
    {
        return lodDef;
    }

    TaskImpl getTask()
    {
        return task;
    }

    /**
     * A unique internal ID created for each OI.  Note this ID is unique only within
     * a single JOE instance.  Use uuid for IDs that are unique across instances.
     */
    long getId()
    {
        return id;
    }

    EntityInstanceImpl getRootEntityInstance()
    {
        return rootEntityInstance;
    }

    EntityInstanceImpl getLastEntityInstance()
    {
        if ( rootEntityInstance == null )
            return null;

        return rootEntityInstance.getLastTwin().getLastChildHier();
    }


    void setRootEntityInstance(EntityInstanceImpl rootEntityInstance)
    {
        this.rootEntityInstance = rootEntityInstance;
    }

    boolean isUpdated()
    {
        return updated;
    }

    void setUpdated(boolean updated)
    {
        this.updated = updated;
        if ( updated )
            setUpdatedFile( true );
    }

    boolean isUpdatedFile()
    {
        return updatedFile;
    }

    void setUpdatedFile(boolean updatedFile)
    {
        this.updatedFile = updatedFile;
    }

    boolean isLocked()
    {
        return isLocked;
    }

    void setLocked(boolean isLocked)
    {
        this.isLocked = isLocked;
    }

    boolean isReadOnly()
    {
        return isReadOnly;
    }

    void setReadOnly(boolean isReadOnly)
    {
        this.isReadOnly = isReadOnly;
    }

    void incrementVersionedCount()
    {
        versionedInstances.incrementAndGet();
    }

    void decrementVersionedCount()
    {
        versionedInstances.decrementAndGet();
    }

    boolean isVersioned()
    {
        return versionedInstances.intValue() > 0;
    }

    EntityInstanceImpl findByHierIndex( long index )
    {
        return getRootEntityInstance().findByHierIndex( index );
    }

    /**
     * Iterable that loops through all entities, including hidden ones.
     *
     * @return
     */
    Iterable getEntities()
    {
        return getEntities( true );
    }

    Iterable getEntities( final boolean allowHidden )
    {
        return new Iterable()
        {
            @Override
            public Iterator iterator()
            {
                return new IteratorBuilder(ObjectInstance.this)
                                .withOiScoping( ObjectInstance.this )
                                .allowHidden( allowHidden )
                                .setLazyLoad( false )
                                .build();
            }
        };
    }

    @Override
    public String toString()
    {
        return lodDef.toString();
    }

    /**
     * Goes through all the prev/next pointers and attempts to verify that they are correctly
     * set.
     *
     * @return
     */
    boolean validateChains()
    {
        EntityInstanceImpl root = getRootEntityInstance();
        if ( root == null )
            return true;

        root = root.getLatestVersion();
        for ( EntityInstanceImpl scan = root; scan != null; scan = scan.getNextHier() )
        {
            if ( scan.getObjectInstance() != this )
            {
                writeValidateError( scan, scan, "EI has mis-matching OI" );
                return false;
            }

            if ( scan.getPrevHier() != null )
            {
                if ( scan.getPrevHier().getNextHier() != scan )
                {
                    writeValidateError( scan, scan.getPrevHier(), "Prev/Next hier pointers don't match" );
                    return false;
                }
            }

            EntityInstanceImpl next = scan.getNextHier();
            if ( next != null )
            {
                if ( next.getPrevHier() != scan )
                {
                    writeValidateError( scan, next, "Next/prev hier pointers don't match" );
                    scan.logEntity( false );
                    next.logEntity( false );
                    return false;
                }
            }

            if ( scan.getNextTwin() != null )
            {
                if ( scan.getNextTwin().getPrevTwin() != scan )
                {
                    writeValidateError( scan, scan.getNextTwin(), "Next/prev Twin pointers don't match" );
                    return false;
                }

                if ( scan.getNextTwin().getEntityDef() != scan.getEntityDef() )
                {
                    writeValidateError( scan, scan.getNextTwin(), "EntityDef next Twin pointers don't match" );
                    return false;
                }
            }

            if ( scan.getPrevTwin() != null )
            {
                if ( scan.getPrevTwin().getParent() != scan.getParent() )
                {
                    writeValidateError( scan, scan.getPrevTwin(), "Parent pointers don't match" );
                    return false;
                }

                if ( scan.getPrevTwin().getNextTwin() != scan )
                {
                    writeValidateError( scan, scan.getPrevTwin(), "Prev/Next twin pointers don't match" );
                    return false;
                }

                if ( scan.getPrevTwin().getEntityDef() != scan.getEntityDef() )
                {
                    writeValidateError( scan, scan.getPrevTwin(), "Prev twin EntityDef don't match" );
                    return false;
                }
            }
        }

        return true;
    }

    private void writeValidateError( EntityInstanceImpl scan, EntityInstanceImpl other, String msg )
    {
        getTask().log().error( msg + "\nScan = %s (%d)\nEI2  = %s (%d)",
                               scan, scan.getEntityKey(), other, other.getEntityKey() );
    }

    /**
     * @param task2
     */
    void setTask( TaskImpl task )
    {
        this.task = task;
    }

    synchronized AttributeHashKeyMap getAttributeHashkeyMap()
    {
        if ( attributeHashkeyMap == null )
            attributeHashkeyMap = new AttributeHashKeyMap( this );

        return attributeHashkeyMap;
    }

    /**
     * @return the activateOptions
     */
    ActivateOptions getActivateOptions()
    {
        return activateOptions;
    }

    /**
     * @param activateOptions the activateOptions to set
     */
    void setActivateOptions( ActivateOptions activateOptions )
    {
        this.activateOptions = activateOptions;
    }

    UUID getUuid()
    {
        return uuid;
    }

    boolean isIgnoreLazyLoadEntities()
    {
        return ignoreLazyLoadEntities;
    }

    void setIgnoreLazyLoadEntities( boolean ignoreLazyLoadEntities )
    {
        this.ignoreLazyLoadEntities = ignoreLazyLoadEntities;
    }

    /**
     * Creates a new View that references this OI.  If ei is not null
     * then set the cursor as well.
     *
     * @param ei
     * @return
     */
    ViewImpl createView( EntityInstanceImpl ei )
    {
        ViewImpl view = new ViewImpl( this );
        if ( ei != null )
            view.cursor( ei.getEntityDef() ).setCursor( ei );

        return view;
    }

    int getEntityCount( boolean includeHidden )
    {
        int count = 0;
        for ( EntityInstanceImpl ei = rootEntityInstance; ei != null; ei = ei.getNextHier() )
        {
            if ( includeHidden || ! ei.isHidden() )
                count++;
        }

        return count;
    }

    Integer getTotalRootCount()
    {
        return totalRootCount;
    }

    void setTotalRootCount( int totalRootCount )
    {
        if ( this.totalRootCount != null )
            throw new ZeidonException( "Total root count has already been set for this OI." );

        this.totalRootCount = totalRootCount;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy