gov.medicaid.services.impl.SequenceGeneratorBean.java Source code

Java tutorial

Introduction

Here is the source code for gov.medicaid.services.impl.SequenceGeneratorBean.java

Source

/*
 * Copyright 2012-2013 TopCoder, Inc.
 *
 * This code was developed under U.S. government contract NNH10CD71C. 
 *
 * 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.
 */
package gov.medicaid.services.impl;

import gov.medicaid.entities.SystemId;
import gov.medicaid.services.SequenceGenerator;
import gov.medicaid.services.util.Util;

import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import javax.ejb.Local;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.ejb.TransactionManagement;
import javax.ejb.TransactionManagementType;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.hibernate.Session;
import org.hibernate.cfg.EJB3NamingStrategy;
import org.hibernate.cfg.NamingStrategy;
import org.hibernate.cfg.ObjectNameNormalizer;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.id.MultipleHiLoPerTableGenerator;
import org.hibernate.type.LongType;

/**
 * This implementation of the sequence generator interface uses the HIBERNATE {@link SequenceGeneratorBean} to minimize
 * database calls on sequence generation.
 * 
 * v1.1 - WAS Porting - upgraded to JPA 2
 * @author TCSASSEMBLER
 * @version 1.1
 */
@Stateless
@Local(SequenceGenerator.class)
@TransactionManagement(TransactionManagementType.CONTAINER)
public class SequenceGeneratorBean implements SequenceGenerator {

    /**
     * String length of the sequence.
     */
    private static final int SEQ_LENGTH = 20;

    /**
     * String length for the system id.
     */
    private static final int SYSTEM_ID_LENGTH = 8;

    /**
     * Maximum low numbers to generated before a new fetch.
     */
    private static final int MAXIMUM_LO = 1000;

    /**
     * The entity manager.
     */
    @PersistenceContext(unitName = "cms")
    private EntityManager em;

    /**
     * Cache of known sequence generators.
     */
    private transient Map<String, MultipleHiLoPerTableGenerator> generators;

    /**
     * Sets the value of the field <code>em</code>.
     *
     * @param em the em to set
     */
    public void setEm(EntityManager em) {
        this.em = em;
    }

    /**
     * Creates a new sequence if necessary.
     *
     * @param sequenceName the sequence to get the next set of values for
     * @return the generator
     */
    private MultipleHiLoPerTableGenerator configure(String sequenceName) {
        Properties params = new Properties();
        params.put(MultipleHiLoPerTableGenerator.ID_TABLE, "CMS_SEQUENCE");
        params.put(MultipleHiLoPerTableGenerator.PK_COLUMN_NAME, "SEQ_NAME");
        params.put(MultipleHiLoPerTableGenerator.PK_VALUE_NAME, sequenceName);
        params.put(MultipleHiLoPerTableGenerator.VALUE_COLUMN_NAME, "NEXT_HI");
        params.put(MultipleHiLoPerTableGenerator.MAX_LO, MAXIMUM_LO);
        params.put(MultipleHiLoPerTableGenerator.IDENTIFIER_NORMALIZER, new ObjectNameNormalizer() {
            /**
             * Returns false.
             */
            protected boolean isUseQuotedIdentifiersGlobally() {
                return false;
            }

            /**
             * Returns the default naming strategy.
             */
            protected NamingStrategy getNamingStrategy() {
                return EJB3NamingStrategy.INSTANCE;
            }
        });

        Session sess = (Session) em.getDelegate();
        SessionFactoryImplementor impl = (SessionFactoryImplementor) sess.getSessionFactory();
        MultipleHiLoPerTableGenerator generator = new MultipleHiLoPerTableGenerator();
        generator.configure(LongType.INSTANCE, params, impl.getDialect());
        generators.put(sequenceName, generator);
        return generator;
    }

    /**
     * Retrieves the next value for the sequence.
     *
     * @param sequenceName the name of the sequence
     * @return the next value (using HI-LO algorithm)
     */
    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
    public long getNextValue(String sequenceName) {
        if (generators == null) {
            generators = new HashMap<String, MultipleHiLoPerTableGenerator>();
        }
        MultipleHiLoPerTableGenerator generator = generators.get(sequenceName);
        if (generator == null) {
            generator = configure(sequenceName);
        }
        Session sess = (Session) em.getDelegate();
        return ((Number) generator.generate((SessionImplementor) sess, null)).longValue();
    }

    /**
     * Creates a unique 28 character string by combining a sequence and the system name.
     *
     * @param system the system name to prepend to the unique value
     * @param sequenceName the name of the sequence
     * @return the next value for the named sequence
     */
    public String getNextSystemValue(SystemId system, String sequenceName) {
        return Util.pad(system.value(), SYSTEM_ID_LENGTH, 'X')
                + Util.pad("" + getNextValue(sequenceName), SEQ_LENGTH, '0');
    }
}