001: /*
002: * $Id: Sequence.java,v 1.15 2007/11/13 19:04:02 rwald Exp $
003: * =======================================================================
004: * Copyright (c) 2002-2005 Axion Development Team. 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
011: * copyright notice, this list of conditions and the following
012: * disclaimer.
013: *
014: * 2. Redistributions in binary form must reproduce the above copyright
015: * notice, this list of conditions and the following disclaimer in
016: * the documentation and/or other materials provided with the
017: * distribution.
018: *
019: * 3. The names "Tigris", "Axion", nor the names of its contributors may
020: * not be used to endorse or promote products derived from this
021: * software without specific prior written permission.
022: *
023: * 4. Products derived from this software may not be called "Axion", nor
024: * may "Tigris" or "Axion" appear in their names without specific prior
025: * written permission.
026: *
027: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
028: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
029: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
030: * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
031: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
032: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
033: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
034: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
035: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
036: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
037: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
038: * =======================================================================
039: */
040:
041: package org.axiondb;
042:
043: import java.io.DataInput;
044: import java.io.DataOutput;
045: import java.io.IOException;
046: import java.io.Serializable;
047: import java.math.BigInteger;
048: import java.util.ArrayList;
049: import java.util.Iterator;
050: import java.util.List;
051:
052: import org.axiondb.event.DatabaseSequenceEvent;
053: import org.axiondb.event.SequenceModificationListener;
054: import org.axiondb.types.IntegerType;
055:
056: /**
057: * A database sequence. A sequence provides a mechanism for obtaining unique integer
058: * values from the database.
059: * <p>
060: * Note: If increment value is negative, then the sequence generator is a descending
061: * sequence generator; otherwise, it is an ascending sequence generator.
062: * <p>
063: * Note: The data type of a sequence generator must be exact numeric with scale 0.
064: *
065: * @version $Revision: 1.15 $ $Date: 2007/11/13 19:04:02 $
066: * @author Chuck Burdick
067: * @author Ahimanikya Satapathy
068: */
069: public class Sequence implements Serializable {
070:
071: public Sequence() {
072: }
073:
074: /**
075: * Create a sequence with all ANSI 2003 parameters.
076: */
077: public Sequence(String name, DataType type, BigInteger startVal,
078: BigInteger incrementBy, BigInteger maxValue,
079: BigInteger minValue, boolean isCycle) {
080: _type = type;
081: _nextValue = startVal;
082: _incrementBy = incrementBy;
083: _name = name.toUpperCase();
084: _listeners = new ArrayList<SequenceModificationListener>();
085: _maxValue = maxValue;
086: _minValue = minValue;
087: _isCycle = isCycle;
088: assertRules();
089: }
090:
091: /**
092: * Create a sequence starting whose initial value is <i>startVal </i>.
093: */
094: public Sequence(String name, int startVal) {
095: _type = new IntegerType();
096: _name = name.toUpperCase();
097: _nextValue = BigInteger.valueOf(startVal);
098: _listeners = new ArrayList<SequenceModificationListener>();
099: }
100:
101: public void addSequenceModificationListener(
102: SequenceModificationListener listener) {
103: _listeners.add(listener);
104: }
105:
106: /**
107: * Returns <code>true</code> iff <i>otherobject </i> is a {@link Sequence}whose
108: * name are equal to mine.
109: */
110: public boolean equals(Object otherobject) {
111: if (otherobject instanceof Sequence) {
112: Sequence that = (Sequence) otherobject;
113: return getName().equals(that.getName());
114: }
115: return false;
116: }
117:
118: /**
119: * Increment and return the next value in this sequence.
120: */
121: public Object evaluate() throws AxionException {
122: _currValue = _nextValue;
123: _nextValue = _nextValue.add(_incrementBy);
124: if (_nextValue.compareTo(_minValue) == -1
125: || _nextValue.compareTo(_maxValue) == 1) {
126: if (_isCycle) {
127: _nextValue = _incrementBy.signum() == 1 ? _minValue
128: : _maxValue;
129: } else {
130: throw new IllegalStateException(
131: "No more value available for this sequence...");
132: }
133: }
134:
135: Iterator it = _listeners.iterator();
136: while (it.hasNext()) {
137: SequenceModificationListener cur = (SequenceModificationListener) it
138: .next();
139: cur.sequenceIncremented(new DatabaseSequenceEvent(this ));
140: }
141: return getDataType().convert(_currValue);
142: }
143:
144: public Object getCuurentValue() throws AxionException {
145: return getDataType().convert(_currValue);
146: }
147:
148: public DataType getDataType() {
149: return _type;
150: }
151:
152: public BigInteger getIncrementBy() {
153: return _incrementBy;
154: }
155:
156: public BigInteger getMaxValue() {
157: return _maxValue;
158: }
159:
160: public BigInteger getMinValue() {
161: return _minValue;
162: }
163:
164: /**
165: * Get the name of this sequence.
166: */
167: public String getName() {
168: return _name;
169: }
170:
171: /**
172: * Get the current value of this sequence.
173: */
174: public Object getValue() throws AxionException {
175: return _nextValue;
176: }
177:
178: /**
179: * Returns a hash code in keeping with the standard {@link Object#equals equals}/
180: * {@link Object#hashCode hashCode}contract.
181: */
182: public int hashCode() {
183: return getName().hashCode();
184: }
185:
186: public boolean isCycle() {
187: return _isCycle;
188: }
189:
190: /**
191: * @see #write
192: */
193: public void read(DataInput in) throws Exception {
194: _name = in.readUTF();
195:
196: String dtypename = in.readUTF();
197: Class clazz = Class.forName(dtypename);
198: _type = (DataType) (clazz.newInstance());
199:
200: _nextValue = new BigInteger(in.readUTF(), Sequence.RADIX);
201: _incrementBy = new BigInteger(in.readUTF(), Sequence.RADIX);
202: _maxValue = new BigInteger(in.readUTF(), Sequence.RADIX);
203: _minValue = new BigInteger(in.readUTF(), Sequence.RADIX);
204: _isCycle = in.readBoolean();
205: _listeners = new ArrayList<SequenceModificationListener>();
206: }
207:
208: /**
209: * Writes the given <i>value </i> to the given <code>DataOutput</code>.
210: *
211: * @param value the value to write, which must be {@link Sequence}
212: */
213: public void write(DataOutput out) throws IOException {
214: out.writeUTF(getName());
215: out.writeUTF(getDataType().getClass().getName());
216: out.writeUTF(_nextValue.toString(Sequence.RADIX));
217: out.writeUTF(getIncrementBy().toString(Sequence.RADIX));
218: out.writeUTF(getMaxValue().toString(Sequence.RADIX));
219: out.writeUTF(getMinValue().toString(Sequence.RADIX));
220: out.writeBoolean(isCycle());
221: }
222:
223: private void assertRules() {
224: if (_incrementBy.signum() == 0) {
225: throw new IllegalArgumentException(
226: "IncrementBy Should be non-zero numeric literal");
227: }
228:
229: if (_minValue.compareTo(_maxValue) >= 0) {
230: throw new IllegalArgumentException(
231: "MinValue Should be less than MaxValue");
232: }
233:
234: if (_nextValue.compareTo(_minValue) == -1
235: || _nextValue.compareTo(_maxValue) == 1) {
236: throw new IllegalArgumentException(
237: "StartValue Should be within min and max Value");
238: }
239: }
240:
241: public static int RADIX = 10;
242:
243: private BigInteger _currValue;
244: private BigInteger _incrementBy = BigInteger.valueOf(1);
245: private boolean _isCycle = false;
246:
247: private List _listeners = null;
248: private BigInteger _maxValue = BigInteger
249: .valueOf(Integer.MAX_VALUE);
250: private BigInteger _minValue = BigInteger.valueOf(0);
251: private String _name = null;
252: private BigInteger _nextValue;
253: private DataType _type = null;
254:
255: private static final long serialVersionUID = -9173917866159022446L;
256: }
|