001: /**
002: * Speedo: an implementation of JDO compliant personality on top of JORM generic
003: * I/O sub-system.
004: * Copyright (C) 2001-2004 France Telecom R&D
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2 of the License, or (at your option) any later version.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: *
020: *
021: *
022: * Contact: speedo@objectweb.org
023: *
024: * Authors: S.Chassande-Barrioz.
025: *
026: */package org.objectweb.speedo.sequence.lib;
027:
028: import org.objectweb.jorm.facility.naming.generator.LongGen;
029: import org.objectweb.speedo.lib.Personality;
030: import org.objectweb.speedo.pm.api.POManagerItf;
031: import org.objectweb.speedo.pm.api.POManagerFactoryItf;
032: import org.objectweb.speedo.sequence.api.SequenceManager;
033: import org.objectweb.speedo.sequence.api.SpeedoSequenceItf;
034:
035: /**
036: * This class corresponds to the description of the tag sequence
037: * in the XML file.
038: * A sequence has :
039: * - a name
040: * - a datastore name (not mandatory)
041: * - a factory class (not mandatory)
042: * - a strategy
043: * - a package name
044: * @author Y.Bersihand
045: */
046: public abstract class SpeedoSequence implements SpeedoSequenceItf {
047:
048: private static final long serialVersionUID = -1595384241096230234L;
049:
050: public final static byte NON_TRANSACTIONAL = 1;
051: public final static byte CONTIGUOUS = 2;
052: public final static byte TRANSACTIONAL = 3;
053:
054: public final static String NON_TRANSACTIONAL_STRING = "nontransactional";
055: public final static String CONTIGUOUS_STRING = "contiguous";
056: public final static String TRANSACTIONAL_STRING = "transactional";
057:
058: /**
059: * The name of the sequence
060: */
061: public String name;
062:
063: /**
064: * The name of the sequence in the datastore
065: * Can be null or ""
066: */
067: public String datastoreName;
068:
069: /**
070: * The name of the factory class
071: * Can be null or ""
072: */
073: public String factoryClass;
074:
075: /**
076: * The strategy of the sequence (NON_TRANSACTIONAL | CONTIGUOUS | NON_CONTIGUOUS)
077: */
078: public byte strategy;
079:
080: /**
081: * The name of the package in which the sequence has been defined
082: */
083: public String packageName;
084:
085: public Integer increment = new Integer(1);
086: public Integer start;
087: public Integer cache;
088:
089: //the sequence manager
090: private SequenceManager sequenceManager = null;
091: private Personality personality = null;
092:
093: //the long gen associated to this sequence
094: private LongGen longGen = null;
095:
096: //used for the allocate method to avoid I/O
097: private int countDown = 0;
098: private long currentId = 0;
099:
100: public LongGen getLongGen() {
101: return longGen;
102: }
103:
104: public void setLongGen(LongGen longGen) {
105: this .longGen = longGen;
106: //set the increment of the longGen
107: this .longGen.setIncrement(this .increment.intValue());
108: }
109:
110: /**
111: * Transforms a String into a Byte. The String must corresponds to local variables.
112: * It returns the byte associated with the variable.
113: * @param s String to transform.
114: * @return the byte associated to the String.
115: */
116: public static byte strategyToByte(String s) {
117: if (s.equalsIgnoreCase(TRANSACTIONAL_STRING))
118: return TRANSACTIONAL;
119: else if (s.equalsIgnoreCase(CONTIGUOUS_STRING))
120: return CONTIGUOUS;
121: else
122: return NON_TRANSACTIONAL;
123: }
124:
125: /**
126: * Transforms a byte into a String.
127: * @param b the byte to transform.
128: * @return the String associated to the byte.
129: */
130: public static String strategyToString(byte b) {
131: if (b == TRANSACTIONAL)
132: return TRANSACTIONAL_STRING;
133: else if (b == CONTIGUOUS)
134: return CONTIGUOUS_STRING;
135: else
136: return NON_TRANSACTIONAL_STRING;
137: }
138:
139: public SequenceManager getSequenceManager() {
140: return sequenceManager;
141: }
142:
143: public void setSequenceManager(SequenceManager sequenceManager) {
144: this .sequenceManager = sequenceManager;
145: personality = sequenceManager.getPMF().getPersonality();
146: }
147:
148: // IMPLEMENTATION OF THE Sequence INTERFACE //
149: //-------------------------------------------//
150:
151: /**
152: * Provides a hint to the implementation that
153: * the application will need additional sequence
154: * value objects in short order.
155: */
156: public void allocate(int additional) {
157: if (longGen != null) {
158: try {
159: currentId = longGen.allocateIds(additional)
160: - (additional * increment.intValue());
161: countDown += additional;
162: } catch (Exception e) {
163: return;
164: }
165: }
166: }
167:
168: /**
169: * Returns the current sequence value object if it is available.
170: */
171: public Object current() {
172: if (longGen != null) {
173: if (countDown == 0) {
174: try {
175: return new Long(longGen.current());
176: } catch (Exception e) {
177: throw personality.newDataStoreRuntimeException(
178: "Problem on current() with sequence "
179: + name + ": " + e.getMessage(), e);
180: }
181: } else {
182: return new Long(currentId);
183: }
184: }
185: throw personality
186: .newDataStoreRuntimeException("Problem on current() with sequence "
187: + name + ": id generator not ready.");
188: }
189:
190: /**
191: * Returns the fully qualified name of the Sequence.
192: */
193: public String getName() {
194: return (packageName == null) ? ("") : (packageName + ".")
195: + name;
196: }
197:
198: /**
199: * Returns the next sequence value object.
200: */
201: public Object next() {
202: if (longGen != null) {
203: if (checkStrategy()) {
204: // if count down is not equal to zero, use the internal counter
205: if (countDown == 0) {
206: //else, make a call to the datastore
207: try {
208: return new Long(longGen.genId());
209: } catch (Exception e) {
210: throw personality.newDataStoreRuntimeException(
211: "Problem on next() with sequence "
212: + name + ": " + e.getMessage(),
213: e);
214: }
215: } else {
216: long res;
217: countDown--;
218: res = currentId;
219: currentId += increment.intValue();
220: return new Long(res);
221: }
222:
223: }
224: }
225: throw personality
226: .newDataStoreRuntimeException("Problem on next() with sequence "
227: + name + ": id generator not ready.");
228: }
229:
230: public long nextValue() {
231: return ((Long) next()).longValue();
232: }
233:
234: public long currentValue() {
235: return ((Long) current()).longValue();
236: }
237:
238: /**
239: * @return true if the operation is allowed according to the strategy
240: * else, false.
241: */
242: private boolean checkStrategy() {
243: //at the moment, only support for transactional and nontransactional strategy
244: if (strategy != NON_TRANSACTIONAL) {
245: //get the pmf
246: POManagerFactoryItf pmf = sequenceManager.getPMF();
247: //get the pm
248: POManagerItf pm = pmf.lookup();
249: //check that a transaction is active
250: return (pm != null && pm.getSpeedoTransaction().isActive());
251: }
252: return true;
253: }
254: }
|