001    package org.apache.ojb.broker.util.sequence;
002    
003    /* Copyright 2003-2005 The Apache Software Foundation
004     *
005     * Licensed under the Apache License, Version 2.0 (the "License");
006     * you may not use this file except in compliance with the License.
007     * You may obtain a copy of the License at
008     *
009     *     http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    
018    import org.apache.ojb.broker.PersistenceBroker;
019    import org.apache.ojb.broker.metadata.FieldDescriptor;
020    
021    import java.util.HashMap;
022    
023    /**
024     * <p>
025     * A High/Low database sequence based implementation.
026     * See {@link org.apache.ojb.broker.util.sequence.SequenceManagerNextValImpl}
027     * for more information.
028     * </p>
029     *
030     * <p>
031     * Implementation configuration properties:
032     * </p>
033     *
034     * <table cellspacing="2" cellpadding="2" border="3" frame="box">
035     * <tr>
036     *     <td><strong>Property Key</strong></td>
037     *     <td><strong>Property Values</strong></td>
038     * </tr>
039     * <tr>
040     *     <td>grabSize</td>
041     *     <td>
042     *         Integer entry determines the
043     *         number of IDs allocated within the
044     *         H/L sequence manager implementation.
045     *         Default was '20'.
046     *    </td>
047     * </tr>
048     * <tr>
049     *     <td>autoNaming</td>
050     *     <td>
051     *          Default was 'true'. If set 'true' OJB try to build a
052     *          sequence name automatic if none found in field-descriptor
053     *          and set this generated name as <code>sequence-name</code>
054     *          in field-descriptor. If set 'false' OJB throws an exception
055     *          if none sequence name was found in field-descriptor.
056     *    </td>
057     * </tr>
058     * </table>
059     * <br/>
060     * <p>
061     * <b>Limitations:</b>
062     * <ul>
063     *      <li>do not use when other applications use the database based sequence ditto</li>
064     * </ul>
065     * </p>
066     * <br/>
067     * <br/>
068     *
069     * @author <a href="mailto:armin@codeAuLait.de">Armin Waibel</a>
070     * @version $Id: SequenceManagerSeqHiLoImpl.java,v 1.1 2007-08-24 22:17:29 ewestfal Exp $
071     */
072    public class SequenceManagerSeqHiLoImpl extends SequenceManagerNextValImpl
073    {
074        public static final String PROPERTY_GRAB_SIZE = SequenceManagerHighLowImpl.PROPERTY_GRAB_SIZE;
075        private static HashMap hiLoMap = new HashMap();
076    
077        protected int grabSize;
078    
079        public SequenceManagerSeqHiLoImpl(PersistenceBroker broker)
080        {
081            super(broker);
082            grabSize = Integer.parseInt(getConfigurationProperty(PROPERTY_GRAB_SIZE, "20"));
083        }
084    
085        protected long getUniqueLong(FieldDescriptor field) throws SequenceManagerException
086        {
087            String sequenceName = calculateSequenceName(field);
088            // we have to be threadsafe
089            synchronized (hiLoMap)
090            {
091                HiLoEntry entry = (HiLoEntry) hiLoMap.get(sequenceName);
092                if (entry == null)
093                {
094                    entry = new HiLoEntry(grabSize, grabSize);
095                    hiLoMap.put(sequenceName, entry);
096                }
097                if (entry.needNewSequence())
098                {
099                    entry.maxVal = grabSize * (super.getUniqueLong(field) + 1);
100                    entry.counter = 0;
101                }
102                return entry.nextVal();
103            }
104        }
105    
106        class HiLoEntry
107        {
108            long maxVal;
109            long counter;
110    
111            public HiLoEntry(long maxVal, long counter)
112            {
113                this.maxVal = maxVal;
114                this.counter = counter;
115            }
116    
117            boolean needNewSequence()
118            {
119                return counter == grabSize;
120            }
121    
122            long nextVal()
123            {
124                return maxVal + counter++;
125            }
126        }
127    }