001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * // Copyright (c) 1998, 2007, Oracle. All rights reserved.
005: *
006: *
007: * The contents of this file are subject to the terms of either the GNU
008: * General Public License Version 2 only ("GPL") or the Common Development
009: * and Distribution License("CDDL") (collectively, the "License"). You
010: * may not use this file except in compliance with the License. You can obtain
011: * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
012: * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
013: * language governing permissions and limitations under the License.
014: *
015: * When distributing the software, include this License Header Notice in each
016: * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
017: * Sun designates this particular file as subject to the "Classpath" exception
018: * as provided by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the License
020: * Header, with the fields enclosed by brackets [] replaced by your own
021: * identifying information: "Portions Copyrighted [year]
022: * [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * If you wish your version of this file to be governed by only the CDDL or
027: * only the GPL Version 2, indicate your decision by adding "[Contributor]
028: * elects to include this software in this distribution under the [CDDL or GPL
029: * Version 2] license." If you don't indicate a single choice of license, a
030: * recipient has the option to distribute your version of this file under
031: * either the CDDL, the GPL Version 2 or to extend the choice of license to
032: * its licensees as provided above. However, if you add GPL Version 2 code
033: * and therefore, elected the GPL Version 2 license, then the option applies
034: * only if the new code is made subject to such option by the copyright
035: * holder.
036: */
037: package oracle.toplink.essentials.sequencing;
038:
039: import java.util.Vector;
040: import java.math.*;
041: import oracle.toplink.essentials.internal.sessions.AbstractSession;
042: import oracle.toplink.essentials.internal.databaseaccess.Accessor;
043: import oracle.toplink.essentials.exceptions.ValidationException;
044: import oracle.toplink.essentials.exceptions.DatabaseException;
045:
046: /**
047: * <p>
048: * <b>Purpose</b>: An abstract class providing default sequence behavior.
049: * <p>
050: */
051: public abstract class StandardSequence extends Sequence {
052: public StandardSequence() {
053: super ();
054: }
055:
056: public StandardSequence(String name) {
057: super (name);
058: }
059:
060: public StandardSequence(String name, int size) {
061: super (name, size);
062: }
063:
064: public StandardSequence(String name, int size, int initialValue) {
065: super (name, size, initialValue);
066: }
067:
068: public void onConnect() {
069: // does nothing
070: }
071:
072: public void onDisconnect() {
073: // does nothing
074: }
075:
076: protected abstract Number updateAndSelectSequence(
077: Accessor accessor, AbstractSession writeSession,
078: String seqName, int size);
079:
080: public abstract boolean shouldAcquireValueAfterInsert();
081:
082: public abstract boolean shouldUseTransaction();
083:
084: public Object getGeneratedValue(Accessor accessor,
085: AbstractSession writeSession, String seqName) {
086: if (shouldUsePreallocation()) {
087: return null;
088: } else {
089: Number value = updateAndSelectSequence(accessor,
090: writeSession, seqName, 1);
091: if (value == null) {
092: throw DatabaseException
093: .errorPreallocatingSequenceNumbers();
094: }
095: return value;
096: }
097: }
098:
099: public Vector getGeneratedVector(Accessor accessor,
100: AbstractSession writeSession, String seqName, int size) {
101: if (shouldUsePreallocation()) {
102: Number value = updateAndSelectSequence(accessor,
103: writeSession, seqName, size);
104: if (value == null) {
105: throw DatabaseException
106: .errorPreallocatingSequenceNumbers();
107: }
108: return createVector(value, seqName, size);
109: } else {
110: return null;
111: }
112: }
113:
114: /**
115: * INTERNAL:
116: * Indicates whether existing attribute value should be overridden.
117: * This method is called in case an attribute mapped to PK of sequencing-using
118: * descriptor contains non-null value.
119: * Default implementation is: Always override for "after insert" sequencing,
120: * override non-positive Numbers for "before insert" sequencing.
121: * @param seqName String is sequencing number field name
122: * @param existingValue Object is a non-null value of PK-mapped attribute.
123: */
124: public boolean shouldOverrideExistingValue(String seqName,
125: Object existingValue) {
126: if (shouldAcquireValueAfterInsert()) {
127: return true;
128: } else {
129: // Check if the stored number is greater than zero (a valid sequence number)
130: if (existingValue instanceof BigDecimal) {
131: if (((BigDecimal) existingValue).signum() <= 0) {
132: return true;
133: }
134: } else if (existingValue instanceof BigInteger) {
135: if (((BigInteger) existingValue).signum() <= 0) {
136: return true;
137: }
138: }
139: //CR#2645: Fix for String ClassCastException. Now we don't assume
140: //anything which is not a BigDecimal to be a Number.
141: else if (existingValue instanceof Number
142: && (((Number) existingValue).longValue() <= 0)) {
143: return true;
144: }
145:
146: return false;
147: }
148: }
149:
150: /**
151: * INTERNAL:
152: * given sequence = 10, size = 5 will create Vector (6,7,8,9,10)
153: * @param seqName String is sequencing number field name
154: * @param existingValue Object is a non-null value of PK-mapped attribute.
155: * @param size int size of Vector to create.
156: */
157: protected Vector createVector(Number sequence, String seqName,
158: int size) {
159: BigDecimal nextSequence;
160: BigDecimal increment = new BigDecimal(1);
161:
162: if (sequence instanceof BigDecimal) {
163: nextSequence = (BigDecimal) sequence;
164: } else {
165: nextSequence = new BigDecimal(sequence.doubleValue());
166: }
167:
168: Vector sequencesForName = new Vector(size);
169:
170: nextSequence = nextSequence.subtract(new BigDecimal(size));
171:
172: // Check for incorrect values return to validate that the sequence is setup correctly.
173: // PRS 36451 intvalue would wrap
174: if (nextSequence.doubleValue() < -1) {
175: throw ValidationException.sequenceSetupIncorrectly(seqName);
176: }
177:
178: for (int index = size; index > 0; index--) {
179: nextSequence = nextSequence.add(increment);
180: sequencesForName.addElement(nextSequence);
181: }
182: return sequencesForName;
183: }
184: }
|