001: /*--
002:
003: Copyright (C) 2002-2005 Adrian Price.
004: All rights reserved.
005:
006: Redistribution and use in source and binary forms, with or without
007: modification, are permitted provided that the following conditions
008: are met:
009:
010: 1. Redistributions of source code must retain the above copyright
011: notice, this list of conditions, and the following disclaimer.
012:
013: 2. Redistributions in binary form must reproduce the above copyright
014: notice, this list of conditions, and the disclaimer that follows
015: these conditions in the documentation and/or other materials
016: provided with the distribution.
017:
018: 3. The names "OBE" and "Open Business Engine" must not be used to
019: endorse or promote products derived from this software without prior
020: written permission. For written permission, please contact
021: adrianprice@sourceforge.net.
022:
023: 4. Products derived from this software may not be called "OBE" or
024: "Open Business Engine", nor may "OBE" or "Open Business Engine"
025: appear in their name, without prior written permission from
026: Adrian Price (adrianprice@users.sourceforge.net).
027:
028: THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
029: WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
030: OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
031: DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
032: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
033: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
034: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
035: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
036: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
037: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
038: POSSIBILITY OF SUCH DAMAGE.
039:
040: For more information on OBE, please see
041: <http://obe.sourceforge.net/>.
042:
043: */
044:
045: package org.obe.server.j2ee.ejb;
046:
047: import java.lang.ref.WeakReference;
048: import java.util.HashMap;
049: import java.util.Iterator;
050: import java.util.Map;
051:
052: /**
053: * Tracks a named, unique, monotonically increasing sequence.
054: * <p/>
055: * <em>N.B. Instances of this class are not threadsafe, and require external
056: * synchronization.</em>
057: *
058: * @author Adrian Price.
059: */
060: public final class Sequence {
061: private static final Map _allSequences = new HashMap();
062: private final String _sequenceName;
063: private long _maxkey;
064: private long _lastkey;
065: private int _keyIncrement;
066:
067: /**
068: * Returns the named sequence, if it exists.
069: *
070: * @param seqName
071: * @return The named sequence, if it exists.
072: */
073: public static synchronized Sequence get(String seqName) {
074: WeakReference reference = (WeakReference) _allSequences
075: .get(seqName);
076: return reference == null ? null : (Sequence) reference.get();
077: }
078:
079: /**
080: * Resets all known sequences.
081: */
082: public static synchronized void resetAll() {
083: for (Iterator iter = _allSequences.values().iterator(); iter
084: .hasNext();) {
085: WeakReference ref = (WeakReference) iter.next();
086: Sequence seq = (Sequence) ref.get();
087: if (seq != null)
088: seq.reset();
089: }
090: }
091:
092: /**
093: * Create a new Sequence.
094: *
095: * @param sequenceName The sequence name.
096: * @param keyIncrement The reallocation block size.
097: * @throws IllegalArgumentException if a sequence with the specified name
098: * already exists.
099: */
100: public Sequence(String sequenceName, int keyIncrement) {
101: synchronized (Sequence.class) {
102: if (_allSequences.containsKey(sequenceName))
103: throw new IllegalArgumentException(sequenceName);
104: _sequenceName = sequenceName;
105: _keyIncrement = keyIncrement;
106: _allSequences.put(sequenceName, new WeakReference(this ));
107: }
108: }
109:
110: /**
111: * Returns the key increment.
112: *
113: * @return The key increment.
114: */
115: public int getKeyIncrement() {
116: return _keyIncrement;
117: }
118:
119: /**
120: * Returns the maximum key value in this block.
121: *
122: * @return The maximum key value.
123: */
124: public long getMaxkey() {
125: return _maxkey;
126: }
127:
128: /**
129: * Sets the maximum key value for this block.
130: *
131: * @param maxkey The maximum key value.
132: */
133: public void setMaxkey(long maxkey) {
134: _maxkey = maxkey;
135: }
136:
137: /**
138: * Sets the value of the last key allocated.
139: *
140: * @param lastkey Last key value.
141: */
142: public void setLastkey(long lastkey) {
143: _lastkey = lastkey;
144: }
145:
146: /**
147: * Returns the value of the last key allocated.
148: *
149: * @return Value of the last id key
150: */
151: public long getLastkey() {
152: return _lastkey;
153: }
154:
155: /**
156: * Returns the sequence name.
157: *
158: * @return Name of table associated with this object
159: */
160: public String getSequenceName() {
161: return _sequenceName;
162: }
163:
164: /**
165: * Check to see if a key is available from this sequence.
166: *
167: * @return <code>true</code> if a new key is available, <code>false</code>
168: * if reallocation is required.
169: */
170: public boolean hasNext() {
171: return _lastkey < _maxkey;
172: }
173:
174: /**
175: * Returns the next key in the sequence.
176: *
177: * @return New key value.
178: */
179: public long getNext() {
180: return _lastkey++;
181: }
182:
183: /**
184: * Resets the sequence to its starting point (0).
185: */
186: public void reset() {
187: _lastkey = _maxkey = 0L;
188: }
189: }
|