KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > oracle > toplink > essentials > sequencing > Sequence


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the "License"). You may not use this file except
5  * in compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * glassfish/bootstrap/legal/CDDLv1.0.txt or
9  * https://glassfish.dev.java.net/public/CDDLv1.0.html.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * HEADER in each file and include the License file at
15  * glassfish/bootstrap/legal/CDDLv1.0.txt. If applicable,
16  * add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your
18  * own identifying information: Portions Copyright [yyyy]
19  * [name of copyright owner]
20  */

21 // Copyright (c) 1998, 2006, Oracle. All rights reserved.
22
package oracle.toplink.essentials.sequencing;
23
24 import java.util.Vector JavaDoc;
25 import java.io.Serializable JavaDoc;
26 import oracle.toplink.essentials.internal.sessions.AbstractSession;
27 import oracle.toplink.essentials.internal.databaseaccess.Platform;
28 import oracle.toplink.essentials.internal.databaseaccess.DatasourcePlatform;
29 import oracle.toplink.essentials.internal.databaseaccess.Accessor;
30 import oracle.toplink.essentials.exceptions.ValidationException;
31
32 /**
33  * <p>
34  * <b>Purpose</b>: Define an interface for sequencing customization.
35  * <p>
36  * <b>Description</b>: Customary sequencing behavior could be achieved by
37  * implementing this interface and passing the instance to
38  * DatabaseSession.getSequencingControl().setValueGenerationPolicy(..).
39  * TopLink internally uses the same method to set its default implementation
40  * of this interface, which provides native sequencing and table sequencing.
41  * Note that the following methods:
42  * shouldAcquireValueAfterInsert();
43  * shouldUsePreallocation();
44  * shouldUseSeparateConnection();
45  * shouldUseTransaction();
46  * are called only once - during creation of the sequencing object.
47  * Therefore during the lifetime of sequencing object these methods
48  * should return the same values as when called for the first time.
49  * If this is not true - resetSequencing (call SequencingControl.resetSequencing()).
50  * <p>
51  * <b>Responsibilities</b>:
52  * <ul>
53  * <li> Define the APIs for customary sequencing.
54  * </ul>
55  * @see SequencingControl
56  */

57 public abstract class Sequence implements Serializable JavaDoc, Cloneable JavaDoc {
58     // name
59
protected String JavaDoc name = "";
60
61     // preallocation size
62
protected int size = 50;
63
64     // owner platform
65
protected Platform platform;
66     
67     protected int initialValue = 1;
68
69     // number of times onConnect was called - number of times onDisconnect was called
70
protected int depth;
71
72     public Sequence() {
73         super();
74     }
75
76     public Sequence(String JavaDoc name) {
77         this();
78         setName(name);
79     }
80
81     public Sequence(String JavaDoc name, int size) {
82         this();
83         setName(name);
84         setPreallocationSize(size);
85     }
86     
87     public Sequence(String JavaDoc name, int size, int initialValue) {
88         this();
89         setName(name);
90         setPreallocationSize(size);
91         setInitialValue(initialValue);
92     }
93
94     public String JavaDoc getName() {
95         return name;
96     }
97
98     public void setName(String JavaDoc name) {
99         this.name = name;
100     }
101
102     public int getPreallocationSize() {
103         return size;
104     }
105
106     public void setPreallocationSize(int size) {
107         this.size = size;
108     }
109     
110     public int getInitialValue() {
111         return initialValue;
112     }
113
114     public void setInitialValue(int initialValue) {
115         this.initialValue = initialValue;
116     }
117
118     public Object JavaDoc clone() {
119         try {
120             Sequence clone = (Sequence)super.clone();
121             if (isConnected()) {
122                 clone.depth = 1;
123                 clone.onDisconnect(getDatasourcePlatform());
124             }
125             return clone;
126         } catch (Exception JavaDoc exception) {
127             throw new InternalError JavaDoc("Clone failed");
128         }
129     }
130
131     public boolean equals(Object JavaDoc obj) {
132         if (obj instanceof Sequence) {
133             return equalNameAndSize(this, (Sequence)obj);
134         } else {
135             return false;
136         }
137     }
138
139     public static boolean equalNameAndSize(Sequence seq1, Sequence seq2) {
140         if (seq1 == seq2) {
141             return true;
142         }
143         return seq1.getName().equals(seq2.getName()) && (seq1.getPreallocationSize() == seq2.getPreallocationSize());
144     }
145
146     protected void setDatasourcePlatform(Platform platform) {
147         this.platform = platform;
148     }
149
150     public Platform getDatasourcePlatform() {
151         return platform;
152     }
153
154     /**
155     * INTERNAL:
156     * Indicates whether sequencing value should be acquired after INSERT.
157     * Note that preallocation could be used only in case sequencing values
158     * should be acquired before insert (this method returns false).
159     * In default implementation, it is true for table sequencing and native
160     * sequencing on Oracle platform, false for native sequencing on other platforms.
161     */

162     public abstract boolean shouldAcquireValueAfterInsert();
163
164     /**
165     * INTERNAL:
166     * Indicates whether several sequencing values should be acquired at a time
167     * and be kept by TopLink. This in only possible in case sequencing numbers should
168     * be acquired before insert (shouldAcquireValueAfterInsert()==false).
169     * In default implementation, it is true for table sequencing and native
170     * sequencing on Oracle platform, false for native sequencing on other platforms.
171     */

172     public boolean shouldUsePreallocation() {
173         return !shouldAcquireValueAfterInsert();
174     }
175
176     /**
177     * INTERNAL:
178     * Indicates whether TopLink should internally call beginTransaction() before
179     * getGeneratedValue/Vector, and commitTransaction after.
180     * In default implementation, it is true for table sequencing and
181     * false for native sequencing.
182     */

183     public abstract boolean shouldUseTransaction();
184
185     /**
186     * INTERNAL:
187     * Indicates whether existing attribute value should be overridden.
188     * This method is called in case an attribute mapped to PK of sequencing-using
189     * descriptor contains non-null value.
190     * @param seqName String is sequencing number field name
191     * @param existingValue Object is a non-null value of PK-mapped attribute.
192     */

193     public abstract boolean shouldOverrideExistingValue(String JavaDoc seqName, Object JavaDoc existingValue);
194
195     /**
196     * INTERNAL:
197     * Indicates whether existing attribute value should be overridden.
198     * This method is called in case an attribute mapped to PK of sequencing-using
199     * descriptor contains non-null value.
200     * @param existingValue Object is a non-null value of PK-mapped attribute.
201     */

202     public boolean shouldOverrideExistingValue(Object JavaDoc existingValue) {
203         return shouldOverrideExistingValue(getName(), existingValue);
204     }
205
206     /**
207     * INTERNAL:
208     * Return the newly-generated sequencing value.
209     * Used only in case preallocation is not used (shouldUsePreallocation()==false).
210     * Accessor may be non-null only in case shouldUseSeparateConnection()==true.
211     * Even in this case accessor could be null - if SequencingControl().shouldUseSeparateConnection()==false;
212     * Therefore in case shouldUseSeparateConnection()==true, implementation should handle
213     * both cases: use a separate connection if provided (accessor != null), or get by
214     * without it (accessor == null).
215     * @param accessor Accessor is a separate sequencing accessor (may be null);
216     * @param writeSession Session is a Session used for writing (either ClientSession or DatabaseSession);
217     * @param seqName String is sequencing number field name
218     */

219     public abstract Object JavaDoc getGeneratedValue(Accessor accessor, AbstractSession writeSession, String JavaDoc seqName);
220
221     /**
222     * INTERNAL:
223     * Return the newly-generated sequencing value.
224     * Used only in case preallocation is not used (shouldUsePreallocation()==false).
225     * Accessor may be non-null only in case shouldUseSeparateConnection()==true.
226     * Even in this case accessor could be null - if SequencingControl().shouldUseSeparateConnection()==false;
227     * Therefore in case shouldUseSeparateConnection()==true, implementation should handle
228     * both cases: use a separate connection if provided (accessor != null), or get by
229     * without it (accessor == null).
230     * @param accessor Accessor is a separate sequencing accessor (may be null);
231     * @param writeSession Session is a Session used for writing (either ClientSession or DatabaseSession);
232     */

233     public Object JavaDoc getGeneratedValue(Accessor accessor, AbstractSession writeSession) {
234         return getGeneratedValue(accessor, writeSession, getName());
235     }
236
237     /**
238     * INTERNAL:
239     * Return a Vector of newly-generated sequencing values.
240     * Used only in case preallocation is used (shouldUsePreallocation()==true).
241     * Accessor may be non-null only in case shouldUseSeparateConnection()==true.
242     * Even in this case accessor could be null - if SequencingControl().shouldUseSeparateConnection()==false;
243     * Therefore in case shouldUseSeparateConnection()==true, implementation should handle
244     * both cases: use a separate connection if provided (accessor != null), or get by
245     * without it (accessor == null).
246     * @param accessor Accessor is a separate sequencing accessor (may be null);
247     * @param writeSession Session is a Session used for writing (either ClientSession or DatabaseSession);
248     * @param seqName String is sequencing number field name
249     * @param size int number of values to preallocate (output Vector size).
250     */

251     public abstract Vector JavaDoc getGeneratedVector(Accessor accessor, AbstractSession writeSession, String JavaDoc seqName, int size);
252
253     /**
254     * INTERNAL:
255     * Return a Vector of newly-generated sequencing values.
256     * Used only in case preallocation is used (shouldUsePreallocation()==true).
257     * Accessor may be non-null only in case shouldUseSeparateConnection()==true.
258     * Even in this case accessor could be null - if SequencingControl().shouldUseSeparateConnection()==false;
259     * Therefore in case shouldUseSeparateConnection()==true, implementation should handle
260     * both cases: use a separate connection if provided (accessor != null), or get by
261     * without it (accessor == null).
262     * @param accessor Accessor is a separate sequencing accessor (may be null);
263     * @param writeSession Session is a Session used for writing (either ClientSession or DatabaseSession);
264     */

265     public Vector JavaDoc getGeneratedVector(Accessor accessor, AbstractSession writeSession) {
266         return getGeneratedVector(accessor, writeSession, getName(), getPreallocationSize());
267     }
268
269     /**
270     * INTERNAL:
271     * This method is called when Sequencing object is created.
272     * Don't override this method.
273     * @param ownerSession DatabaseSession
274     */

275     public void onConnect(Platform platform) {
276         if (isConnected()) {
277             verifyPlatform(platform);
278         } else {
279             setDatasourcePlatform(platform);
280             onConnect();
281         }
282         depth++;
283     }
284
285     /**
286     * INTERNAL:
287     * This method is called when Sequencing object is created.
288     * If it requires initialization, subclass should override this method.
289     * @param ownerSession DatabaseSession
290     */

291     protected abstract void onConnect();
292
293     /**
294     * INTERNAL:
295     * This method is called when Sequencing object is destroyed.
296     * Don't overridethis method.
297     */

298     public void onDisconnect(Platform platform) {
299         if (isConnected()) {
300             depth--;
301             if (depth == 0) {
302                 onDisconnect();
303                 setDatasourcePlatform(null);
304             }
305         }
306     }
307
308     /**
309     * INTERNAL:
310     * This method is called when Sequencing object is destroyed.
311     * If it requires deinitialization, subclass should override this method.
312     */

313     protected abstract void onDisconnect();
314
315     /**
316     * PUBLIC:
317     * Indicates that Sequence is connected.
318     */

319     public boolean isConnected() {
320         return platform != null;
321     }
322
323     /**
324     * INTERNAL:
325     * Make sure that the sequence is not used by more than one platform.
326     */

327     protected void verifyPlatform(Platform otherPlatform) {
328         if (getDatasourcePlatform() != otherPlatform) {
329             String JavaDoc hashCode1 = Integer.toString(System.identityHashCode(getDatasourcePlatform()));
330             String JavaDoc name1 = ((DatasourcePlatform)getDatasourcePlatform()).toString() + '(' + hashCode1 + ')';
331
332             String JavaDoc hashCode2 = Integer.toString(System.identityHashCode(otherPlatform));
333             String JavaDoc name2 = ((DatasourcePlatform)otherPlatform).toString() + '(' + hashCode2 + ')';
334
335             throw ValidationException.sequenceCannotBeConnectedToTwoPlatforms(getName(), name1, name2);
336         }
337     }
338 }
339
Popular Tags