Package org.jpox.store.poid

Source Code of org.jpox.store.poid.AbstractPoidGenerator

/**********************************************************************
Copyright (c) 2006 Andy Jefferson and others. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.


Contributors:
    ...
**********************************************************************/
package org.jpox.store.poid;

import java.util.Properties;

import org.jpox.ObjectManagerFactoryImpl;
import org.jpox.exceptions.JPOXDataStoreException;
import org.jpox.util.JPOXLogger;
import org.jpox.util.Localiser;

/**
* Abstract POID generator.
*
* @version $Revision: 1.9 $
*/
public abstract class AbstractPoidGenerator implements PoidGenerator
{
    /** Localisation of messages */
    protected static final Localiser LOCALISER = Localiser.getInstance("org.jpox.store.Localisation",
        ObjectManagerFactoryImpl.class.getClassLoader());

    /** Symbolic name for the sequence. */
    protected String name;

    /** Properties controlling the generator behaviour. */
    protected Properties properties;

    /** Allocation size */
    protected int allocationSize = 5;

    /** Initial value (of the first id). */
    protected int initialValue = 0;

    /** The current block of ids that have been reserved. */
    protected PoidBlock poidBlock;

    /**
     * Constructor.
     * JPOX Core will pass the following properties (as a minimum) through this constructor.
     * <ul>
     * <li>class-name : Name of the class whose object is being inserted.</li>
     * <li>root-class-name : Name of the root class in this inheritance tree</li>
     * <li>field-name : Name of the field with the strategy (unless datastore identity field)</li>
     * <li>catalog-name : Catalog of the table (if specified)</li>
     * <li>schema-name : Schema of the table (if specified)</li>
     * <li>table-name : Name of the root table for this inheritance tree (containing the field).</li>
     * <li>column-name : Name of the column in the table (for the field)</li>
     * <li>sequence-name : Name of the sequence (if specified in MetaData as "sequence)</li>
     * </ul>
     *
     * @param name Symbolic name for this generator
     * @param props Properties controlling the behaviour of the generator (or null if not required).
     */
    public AbstractPoidGenerator(String name, Properties props)
    {
        this.name = name;
        this.properties = props;
    }

    /**
     * Accessor for the storage class for POIDs generated with this generator.
     * @return Storage class (e.g Long.class)
     */
    public static Class getStorageClass()
    {
        return Long.class;
    }

    /**
     * Accessor for the symbolic name for this generator.
     * @return Symbolic name for the generator.
     */
    public String getName()
    {
        return name;
    }

    /**
     * Get next value from the reserved block of values.
     * @return The next value
     */
    public synchronized Object next()
    {
        // If the current block of ids is null or empty get a new one
        if (poidBlock == null || !poidBlock.hasNext())
        {
            // No more elements left in the block so replace it with a new one
            poidBlock = obtainPoidBlock();
        }

        return poidBlock.next().getOid();
    }

    /**
     * Accessor for the current value allocated.
     * Returns null if none are allocated
     * @return The current value
     */
    public synchronized Object current()
    {
        if (poidBlock == null)
        {
            return null;
        }
        return poidBlock.current().getOid();
    }

    /**
     * Accessor for the next element in the sequence as a long.
     * @return The next element
     * @throws JPOXDataStoreException Thrown if not numeric
     */
    public long nextValue()
    {
        return getLongValueForObject(next());
    }

    /**
     * Accessor for the current element in the sequence as a long.
     * @return The current element
     * @throws JPOXDataStoreException Thrown if not numeric
     */
    public long currentValue()
    {
        return getLongValueForObject(current());
    }

    /**
     * Convenience method to convert an object id into a long.
     * Throws JPOXDataStoreException if the id is not numeric.
     * @param oid The id
     * @return The long value
     * @throws JPOXDataStoreException Thrown if not numeric
     */
    private long getLongValueForObject(Object oid)
    {
        if (oid instanceof Long)
        {
            return ((Long)oid).longValue();
        }
        else if (oid instanceof Integer)
        {
            return ((Integer)oid).longValue();
        }
        else if (oid instanceof Short)
        {
            return ((Short)oid).longValue();
        }

        throw new JPOXDataStoreException(LOCALISER.msg("040009", name));
    }

    /**
     * Method to allocate a number of values into the block.
     * If the block already exists and has remaining values, the
     * additional values are added to the block.
     * @param additional The number to allocate
     */
    public synchronized void allocate(int additional)
    {
        if (poidBlock == null)
        {
            // No existing block so replace the existing block
            poidBlock = obtainPoidBlock(additional);
        }
        else
        {
            // Existing block so append to it
            poidBlock.addBlock(obtainPoidBlock(additional));
        }
    }

    /**
     * Get a new PoidBlock with the default number of ids.
     * @return the PoidBlock
     */
    protected PoidBlock obtainPoidBlock()
    {
        // -1 here implies just use the default reserveBlock on the generator
        return obtainPoidBlock(-1);
    }

    /**
     * Get a new PoidBlock with the specified number of ids.
     * @param number The number of additional ids required
     * @return the PoidBlock
     */
    protected PoidBlock obtainPoidBlock(int number)
    {
        PoidBlock block = null;

        // Try getting the block
        boolean repository_exists=true;
        try
        {
            try
            {
                if (number < 0)
                {
                    block = reserveBlock();
                }
                else
                {
                    block = reserveBlock(number);
                }
            }
            catch (PoidException poidex)
            {
                JPOXLogger.POID.info(LOCALISER.msg("040003", poidex.getMessage()));

                // attempt to obtain the block of unique identifiers is invalid
                if (requiresRepository())
                {
                    repository_exists = false;
                }
                else
                {
                    throw poidex;
                }
            }
            catch (RuntimeException ex)
            {
                //exceptions cached by the poid should be enclosed in PoidException
                //when the exceptions are not catched exception by poid, we give a new try
                //in creating the repository
                JPOXLogger.POID.info(LOCALISER.msg("040003", ex.getMessage()));
                // attempt to obtain the block of unique identifiers is invalid
                if (requiresRepository())
                {
                    repository_exists = false;
                }
                else
                {
                    throw ex;
                }
            }
        }
        finally
        {
        }

        // If repository didn't exist, try creating it and then get block
        if (!repository_exists)
        {
            try
            {
                JPOXLogger.POID.info(LOCALISER.msg("040005"));
                if (!createRepository())
                {
                    throw new PoidException(LOCALISER.msg("040002"));
                }
                else
                {
                    if (number < 0)
                    {
                        block = reserveBlock();
                    }
                    else
                    {
                        block = reserveBlock(number);
                    }
                }
            }
            finally
            {
            }
        }
        return block;
    }

    /**
     * Method to reserve a default sized block of identities.
     * @return The reserved block
     */
    protected PoidBlock reserveBlock()
    {
        return reserveBlock(allocationSize);
    }

    /**
     * Method to reserve a blobk of "size" ids.
     * @param size Number of ids to reserve
     * @return The allocated block
     */
    protected abstract PoidBlock reserveBlock(long size);

    /**
     * Indicator for whether the generator requires its own repository.
     * AbstractPoidGenerator returns false and this should be overridden by all
     * generators requiring a repository.
     * @return Whether a repository is required.
     */
    protected boolean requiresRepository()
    {
        return false;
    }

    /**
     * Method to create any needed repository for the ids.
     * AbstractPoidGenerator just returns true and should be overridden by any
     * implementing generator requiring its own repository.
     * @return If all is ready for use
     */
    protected boolean createRepository()
    {
        // Do nothing - to be overridden by generators that want to create a repository for their ids
        return true;
    }
}
TOP

Related Classes of org.jpox.store.poid.AbstractPoidGenerator

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