Package org.jpox.store.rdbms.poid

Source Code of org.jpox.store.rdbms.poid.TablePoidGenerator

/**********************************************************************
Copyright (c) 2003 Erik Bengtson 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:
2004 Andy Jefferson - removed MetaData requirement
2007 Andy Jefferson - revised to fit in with JPA requirements for table sequences
    ...
**********************************************************************/
package org.jpox.store.rdbms.poid;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import org.jpox.store.mapped.DatastoreClass;
import org.jpox.store.mapped.MappedStoreManager;
import org.jpox.store.poid.PoidBlock;
import org.jpox.store.poid.PoidException;
import org.jpox.store.rdbms.RDBMSManager;
import org.jpox.store.rdbms.adapter.RDBMSAdapter;
import org.jpox.store.rdbms.sqlidentifier.SQLIdentifier;
import org.jpox.store.rdbms.table.SequenceTable;
import org.jpox.util.JPOXLogger;

/**
* Identity generator for RDBMS databases that generates ids using a table in the database.
* This generator is coupled to JPOX core and can't be used in standalone mode.
* <P>
* The following properties define the name of the sequence being generated. If "sequence-name" is specified then it is
* used. Otherwise the name of the sequence will either be based on the table name or the class name (for what we are
* generating the ids).
* <UL>
* <LI><U>sequence-name</U> - Name for the sequence</LI>
* <LI><U>sequence-table-basis</U> - Basic for the sequence name (if "sequence-name" not provided). This can be
* "table" or "class".</LI>
* </UL>
* <p>
* The following properties define the table where the identities are generated.
* </p>
* <UL>
* <LI><U>sequence-catalog-name</U> - the catalog name for the table (defaults to the default catalog)</LI>
* <LI><U>sequence-schema-name</U> - the schema name for the table (defaults to the default schema)</LI>
* <LI><U>sequence-table-name</U> - the table name for the table (defaults to SEQUENCE_TABLE)</LI>
* <LI><U>sequence-name-column-name</U> - the name for the column that represent sequence names</LI>
* <LI><U>sequence-nextval-column-name</U> - the name for the column that represent incrementing sequence values</LI>
* <UL>
* <p>
* The following properties control the initial value, and the number of ids that are cached (generated) in each call.
* </p>
* <UL>
* <LI><U>key-initial-value</U> - start value (if we have no current value). If not specified and we have
* no current value then we do a "SELECT max(column-name) FROM table-name" for the column being incremented</LI>
* <LI><U>key-cache-size</U> - number of unique identifiers to cache (defaults to 5)</LI>
* </UL>
* <p>
* The following properties are used when finding the starting point for the identities generated.
* </p>
* <UL>
* <li><U>table-name</U> - name of the table whose column we are generating the value for</li>
* <li><U>column-name</U> - name of the column that we are generating the value for</li>
* </UL>
* </P>
*
* @version $Revision: 1.5 $
*/
public final class TablePoidGenerator extends AbstractRDBMSPoidGenerator
{
    /** Table where we store the identities for each table. */
    private SequenceTable sequenceTable = null;

    /** Name of the sequence that we are storing values under in the SequenceTable. */
    private final String sequenceName;

    /** Default name for the datastore table storing the sequence values. Defaults to SEQUENCE_TABLE */
    private static final String DEFAULT_TABLE_NAME = "SEQUENCE_TABLE";

    /**
     * Constructor.
     * @param name Symbolic name for this generator
     * @param props Properties defining the behaviour of this generator
     */
    public TablePoidGenerator(String name, Properties props)
    {
        super(name, props);
        allocationSize = 5;
        if (properties != null)
        {
            if (properties.get("key-cache-size") != null)
            {
                try
                {
                    allocationSize = Integer.parseInt((String)properties.get("key-cache-size"));
                }
                catch (Exception e)
                {
                    throw new PoidException(LOCALISER.msg("Sequence040006",properties.get("key-cache-size")));
                }
            }
            if (properties.get("key-initial-size") != null)
            {
                try
                {
                    initialValue = new Integer(properties.getProperty("key-initial-value")).intValue();
                }
                catch (NumberFormatException nfe)
                {
                    // Not an integer so ignore it
                }
            }
        }

        if (properties.getProperty("sequence-name") != null)
        {
            // Specified sequence-name so use that
            sequenceName = properties.getProperty("sequence-name");
        }
        else if (properties.getProperty("sequence-table-basis") != null &&
            properties.getProperty("sequence-table-basis").equalsIgnoreCase("table"))
        {
            // Use table name in the sequence table as the sequence name
            sequenceName = properties.getProperty("table-name");
        }
        else
        {
            // Use root class name (for this inheritance tree) in the sequence table as the sequence name
            sequenceName = properties.getProperty("root-class-name");
        }
    }

    /**
     * Method to reserve a block of "size" identities.
     * @param size Block size
     * @return The reserved block
     */
    public PoidBlock reserveBlock(long size)
    {
        if (size < 1)
        {
            return null;
        }

        // search for an ID in the database
        List oid = new ArrayList();
        try
        {
            if (sequenceTable == null)
            {
                initialiseSequenceTable();
            }

            SQLIdentifier sourceTableIdentifier = null;
            if (properties.getProperty("table-name") != null)
            {
                sourceTableIdentifier = (SQLIdentifier)((MappedStoreManager)storeMgr).getIdentifierFactory().newDatastoreContainerIdentifier(properties.getProperty("table-name"));
                // TODO Apply passed in catalog/schema to this identifier rather than the default for the factory
            }
            Long nextId = sequenceTable.getNextVal(sequenceName, connection, (int)size,
                sourceTableIdentifier, properties.getProperty("column-name"), initialValue);
            for (int i=0; i<size; i++)
            {
                oid.add(nextId);
                nextId = new Long(nextId.longValue()+1);
            }
            if (JPOXLogger.POID.isDebugEnabled())
            {
                JPOXLogger.POID.debug(LOCALISER.msg("040004", "" + size));
            }
            return new PoidBlock(oid);
        }
        catch (SQLException e)
        {
            throw new PoidException(LOCALISER_RDBMS.msg("061001",e.getMessage()));
        }
    }

    /**
     * Indicator for whether the generator requires its own repository.
     * This class needs a repository so returns true.
     * @return Whether a repository is required.
     */
    protected boolean requiresRepository()
    {
        return true;
    }

  /**
   * Method to create the repository for ids to be stored.
   * @return Whether it was created successfully.
   */
  protected boolean createRepository()
  {
        try
        {
            if (sequenceTable == null)
            {
                initialiseSequenceTable();
            }

            // Create the table if it doesnt physically exist
            sequenceTable.exists((Connection) connection.getConnection(), true);

            return true;
        }
        catch (SQLException e)
        {
        throw new PoidException(e.toString());
        }
  }

    /**
     * Method to initialise the sequence table used for storing the sequence values.
     */
    protected void initialiseSequenceTable()
    {
        // Set catalog/schema name (using properties, and if not specified using the values for the table)
        String catalogName = properties.getProperty("sequence-catalog-name");
        if (catalogName == null)
        {
            catalogName = properties.getProperty("catalog-name");
        }
        String schemaName = properties.getProperty("sequence-schema-name");
        if (schemaName == null)
        {
            schemaName = properties.getProperty("schema-name");
        }
        String tableName = (properties.getProperty("sequence-table-name") == null ?
                DEFAULT_TABLE_NAME : properties.getProperty("sequence-table-name"));

        MappedStoreManager storeMgr = (MappedStoreManager)this.storeMgr;
        SQLIdentifier identifier = (SQLIdentifier)storeMgr.getIdentifierFactory().newDatastoreContainerIdentifier(tableName);
        if (((RDBMSAdapter)storeMgr.getDatastoreAdapter()).supportsCatalogsInTableDefinitions() && catalogName != null)
        {
            identifier.setCatalogName(catalogName);
        }
        if (((RDBMSAdapter)storeMgr.getDatastoreAdapter()).supportsSchemasInTableDefinitions() && schemaName != null)
        {
            identifier.setSchemaName(schemaName);
        }

        DatastoreClass table = storeMgr.getDatastoreClass(identifier);
        if (table != null)
        {
            sequenceTable = (SequenceTable)table;
        }
        else
        {
            String sequenceNameColumnName = "SEQUENCE_NAME";
            String nextValColumnName = "NEXT_VAL";
            if (properties.getProperty("sequence-name-column-name") != null)
            {
                sequenceNameColumnName = properties.getProperty("sequence-name-column-name");
            }
            if (properties.getProperty("sequence-nextval-column-name") != null)
            {
                nextValColumnName = properties.getProperty("sequence-nextval-column-name");
            }
            sequenceTable = new SequenceTable(identifier, (RDBMSManager)storeMgr, sequenceNameColumnName, nextValColumnName);
            sequenceTable.initialize(storeMgr.getOMFContext().getClassLoaderResolver(null));
            storeMgr.addDatastoreContainer(sequenceTable);
        }
    }
}
TOP

Related Classes of org.jpox.store.rdbms.poid.TablePoidGenerator

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.